Article directory
- foreword
- tuple structure
- Introduction to tuple headers
- tuple assembly
- end
foreword
This article is based on the analysis and interpretation of the postgresql 14 code, and the demonstration is carried out on the centos8 system.
1. tuple structure
+---------------------+---------------+----------------+
| HeapTupleHeaderData | nulls bitmap | padding |
+------------+--------+---------------+----------------+
| object ID | value1 value2 value3 ... |
+------------+-----------------------------------------+
Each row of data seen in the data table is stored in the form of tuple in the page. The structure of tuple is:
(1) HeapTupleHeaderData
(2)nulls bitmap; This is an option, when the t_infomask has the HEAP_HASNULL flag, this array will have a value;
(3) padding ; The length of the null bitmap in front is uncertain. In order to align the subsequent data, here is the byte alignment of HeapTupleHeaderData+nulls bitmap, and there will be a blank here.
(4) OID value, this is an option, when t_infomask has HEAP_HASOID_OLD, it will have this value;
(5) user data; that is, the data of each column;
2. Introduction to tuple headers
struct HeapTupleHeaderData
{
union
{
HeapTupleFields t_heap;
DateTupleFields t_date ;
} t_choice;
ItemPointerData t_ctid; /* current TID of this or newer tuple (or a
* speculative insertion token) */
/* Fields below here must match MinimalTupleData! */
#define FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK2 2
uint16 t_infomask2; /* number of attributes + various flags */
#define FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK 3
uint16 t_infomask; /* various flag bits, see below */
#define FIELDNO_HEAPTUPLEHEADERDATA_HOFF 4
uint8 t_hoff; /* sizeof header incl. bitmap, padding */
/* ^ - 23 bytes - ^ */
#define FIELDNO_HEAPTUPLEHEADERDATA_BITS 5
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]; /* bitmap of NULLs */
/* MORE DATA FOLLOWS AT END OF STRUCT */
};
- field description
(1) t_choice
The union composed of the HeapTupleFields structure and the DatumTupleFields structure can be selected and used in the two cases of tuple construction and tuple in the page respectively, and cannot exist at the same time.
- t_data
This structure needs to be filled when a tuple is constructed in memory. At this time, there is no need for visibility judgment and concurrency control information.
Structure description:
typedef struct DatumTupleFields
{
int32 datum_len_; /* varlena header (do not touch directly!) */
int32 datum_typmod; /* -1, or identifier of a record type */
Oid datum_typeid; /* composite type OID, or RECORDOID */
/*
* datum_typeid cannot be a domain over composite, only plain composite,
* even if the datum is meant as a value of a domain-over-composite type.
* This is in line with the general principle that CoerceToDomain does not
* change the physical representation of the base type value.
*
* Note: field ordering is chosen with thought that Oid might someday
* widen to 64 bits.
*/
} DatumTupleFields;
- t_heap
This structure must be populated when the tuple is added to the table's page . Directly convert DatumTupleFields to HeapTupleFields structure for use.
Structure description:
typedef struct HeapTupleFields
{
TransactionId t_xmin; /* inserting xact ID */
TransactionId t_xmax; /* deleting or locking xact ID */
union
{
CommandId t_cid; /* inserting or deleting command ID, or both */
TransactionId t_xvac; /* old-style VACUUM FULL xact ID */
} t_field3;
} HeapTupleFields;
3. Tuple assembly
A new tuple will be assembled during insert/update, and then a page with enough remaining space will be found and added to it. Of course, there are certain strategies for finding a page with enough space, which will be discussed later.
- Create a new tuple
HeapTuple
heap_form_tuple(TupleDesc tupleDescriptor,
Datum *values,
bool *isnull);
Calculate the len of the tuple in this interface, including the size of the value of the tupleheader+ each attribute column,
In addition, len also needs to include the size of the HeapTupleData structure, which records the row pointer data and tuple data, as well as their total length;
typedef struct HeapTupleData
{
uint32 t_len; /* length of *t_data */
ItemPointerData t_self; /* SelfItemPointer */
Oid t_tableOid; /* table the tuple came from */
#define FIELDNO_HEAPTUPLEDATA_DATA 3
HeapTupleHeader t_data; /* -> tuple header and data */
} HeapTupleData;
Then t_choice . t_datum of t_data will be assigned a value, and the length value is the tuple length shifted to the left by 2 bits;
- tuple operation
Assignment operation to t_choice.t_datum in tupleheader _
HeapTupleHeaderSetDatumLength(td, len);
HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
- Limit on the number of attribute columns
#define MaxTupleAttributeNumber 1664 /* 8 * 208 */
When constructing tuple in memory, it will judge whether this upper limit is exceeded
#define MaxHeapAttributeNumber 1600 /* 8 * 200 */
The maximum number of columns here is 1600. When the column field is long, it will be smaller than this number; this number is a certain margin.
end
Author email: [email protected]
If there are any mistakes or omissions, please point them out and learn from each other.
Note: Do not reprint without consent!