postgresql tuple介绍

文章目录

  • 前言
  • tuple结构
  • tupleheader介绍
  • tuple组装
  • 结尾

前言

本文是基于postgresql 14的代码进行分析解读,演示是在centos8系统上进行。


1、tuple结构

 

	 +---------------------+---------------+----------------+
	 | HeapTupleHeaderData |  nulls bitmap | padding        |
	 +------------+--------+---------------+----------------+
	 | object ID  |  value1 value2 value3 ...               |
	 +------------+-----------------------------------------+
  

  数据表里看到的每一行数据,在page中是以tuple的形式存储,tuple的结构有:

 

(1) HeapTupleHeaderData 

(2)nulls bitmap ; 这是个可选项,当t_infomaskHEAP_HASNULL标志的话,这个数组就会有值;

(3) padding ;  前面null bitmap的长度不确定,为了后面数据能对齐,这里对HeapTupleHeaderData+nulls bitmap 字节对齐,这里会有留空。

(4) OID值,这是个可选项,当t_infomask有HEAP_HASOID_OLD时,会有此值;

(5)用户数据;也就是各列的数据;

 

 

2、tupleheader介绍

 

struct HeapTupleHeaderData

{

    union

    {

        HeapTupleFields t_heap;

        DatumTupleFields t_datum;

    }           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 */

};

  • 字段说明

(1) t_choice

HeapTupleFields 结构和 DatumTupleFields 结构组成的联合体,分别在tuple构建和tuplepage中两种情况下选择使用,又不能同时存在。

 

  • t_datum

当一个tuple在内 存中构建时,需要填充这个结构体。这时候还不需要可见性判断和并发控制的信息。

结构说明:

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

当把tuple加入到表的page中时,就必须填充这个结构体。将DatumTupleFields直接强转成HeapTupleFields结构来使用。

 

结构说明:

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组装

在insert/update时都会组装一个新的tuple,然后找到一个剩余空间足够的page,加到里面。当然寻找空间足够的page有一定策略,这个后面再讲。

  • 新建一个tuple

HeapTuple

heap_form_tuple(TupleDesc tupleDescriptor,

                Datum *values,

                bool *isnull);

在这个接口中计算tuple的len,包括tupleheader+各属性列的值的大小,

另外len还需要包括HeapTupleData结构体的大小,该结构体记录了 行指针数据和tuple的数据,以及他们的总长度;

 

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;

 

然后t_datat_choice.t_datum会被赋值,长度取值为tuple长度向左移2位;

  • tuple操作

tupleheadert_choice.t_datum赋值操作

HeapTupleHeaderSetDatumLength(td, len);

HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);

HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);

  • 属性列个数限制

#define MaxTupleAttributeNumber 1664    /* 8 * 208 */

在内存中构建tuple时会判断是否超过这个上限

#define MaxHeapAttributeNumber  1600    /* 8 * 200 */

这里最大1600个列,当列的字段长时会小于这个数字;这个数字是留有一定余量。


结尾

作者邮箱:[email protected]
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

猜你喜欢

转载自blog.csdn.net/senllang/article/details/123674067