Table row layout
物理行首部、空值位图、对齐与列数据。
当前查看 PostgreSQL 18.6。
说明
物理行首部、空值位图、对齐与列数据。
HeapTupleHeaderData 布局
| 字段 | 类型 | 长度 | 说明 |
|---|---|---|---|
| t_xmin | TransactionId | 4 字节 | 插入事务的 XID |
| t_xmax | TransactionId | 4 字节 | 删除事务的 XID |
| t_cid | CommandId | 4 字节 | 插入和/或删除命令的 CID,与 t_xvac 共用存储位置 |
| t_xvac | TransactionId | 4 字节 | VACUUM 操作移动行版本时使用的 XID |
| t_ctid | ItemPointerData | 6 字节 | 本行版本或较新行版本的当前 TID |
| t_infomask2 | uint16 | 2 字节 | 属性数量及各种标志位 |
| t_infomask | uint16 | 2 字节 | 各种标志位 |
| t_hoff | uint8 | 1 字节 | 用户数据的偏移量 |
手册定义
所有表行的结构都相同。它们都有一个固定大小的头部(在大多数机器上占 23 字节),后面跟着可选的空值位图、可选的对象 ID 字段以及用户数据。头部的详细格式见表 66.4。实际用户数据(行的各列)从 t_hoff 指示的偏移位置开始,它必须始终是该平台 MAXALIGN 对齐单位的整数倍。只有当 HEAP_HASNULL 位在 t_infomask 中被置位时,空值位图才存在。若存在,它紧随固定头部之后,并占用足够多的字节,以便为每个数据列提供一位(也就是说,其位数等于 t_infomask2 中的属性个数)。在这个位图中,1 表示非空,0 表示空值。当位图不存在时,假定所有列都非空。只有当 HEAP_HASOID_OLD 位在 t_infomask 中被置位时,对象 ID 才存在。若存在,它位于 t_hoff 边界之前。为了让 t_hoff 成为 MAXALIGN 的整数倍所需的任何填充,都会出现在空值位图与对象 ID 之间。(这又反过来保证了对象 ID 的对齐是合适的。)
表 66.4. HeapTupleHeaderData 布局
| 字段 | 类型 | 长度 | 说明 |
|---|---|---|---|
| t_xmin | TransactionId | 4 字节 | 插入事务的 XID |
| t_xmax | TransactionId | 4 字节 | 删除事务的 XID |
| t_cid | CommandId | 4 字节 | 插入和/或删除命令的 CID,与 t_xvac 共用存储位置 |
| t_xvac | TransactionId | 4 字节 | VACUUM 操作移动行版本时使用的 XID |
| t_ctid | ItemPointerData | 6 字节 | 本行版本或较新行版本的当前 TID |
| t_infomask2 | uint16 | 2 字节 | 属性数量及各种标志位 |
| t_infomask | uint16 | 2 字节 | 各种标志位 |
| t_hoff | uint8 | 1 字节 | 用户数据的偏移量 |
所有细节都可以在 src/include/access/htup_details.h 中找到。
要解释实际数据,必须借助从其他表中获得的信息,其中大部分来自 pg_attribute。识别字段位置所需的关键值是 attlen 和 attalign。除非所有字段都是定宽且没有空值,否则没有办法直接取得某个特定属性。所有这些技巧都封装在 heap_getattr、fastgetattr 和 heap_getsysattr 这些函数中。
读取数据时,需要依次检查每个属性。首先根据空值位图判断该字段是否为 NULL。如果是,就继续下一个。然后确认对齐是否正确。如果字段是定宽字段,那么它的所有字节都是直接摆放的;如果它是变长字段(attlen = -1),情况就会稍复杂一些。所有变长数据类型都共享一个通用头部结构体 struct varlena,其中包含已存储值的总长度以及一些标志位。根据这些标志,数据可能是行内存储的,也可能位于 TOAST 表中;它也可能是经过压缩的(见第 66.2 节)。
文档与源码
来源构建
- 版本
- 18.6
- 构建
- https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2
- 来源指纹
555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f
版本比较
PostgreSQL 10 → 11: 新增收录。
以下差异保留原始字段名与英文源描述。
--- PostgreSQL 10
+++ PostgreSQL 11
@@ -1 +1,76 @@
-该版未收录
+{
+ "layouts": [
+ {
+ "columns": [
+ {
+ "key": "c0",
+ "label": "Field"
+ },
+ {
+ "key": "c1",
+ "label": "Type"
+ },
+ {
+ "key": "c2",
+ "label": "Length"
+ },
+ {
+ "key": "c3",
+ "label": "Description"
+ }
+ ],
+ "key": "layout-2",
+ "rows": [
+ {
+ "c0": "t_xmin",
+ "c1": "TransactionId",
+ "c2": "4 bytes",
+ "c3": "insert XID stamp"
+ },
+ {
+ "c0": "t_xmax",
+ "c1": "TransactionId",
+ "c2": "4 bytes",
+ "c3": "delete XID stamp"
+ },
+ {
+ "c0": "t_cid",
+ "c1": "CommandId",
+ "c2": "4 bytes",
+ "c3": "insert and/or delete CID stamp (overlays with t_xvac)"
+ },
+ {
+ "c0": "t_xvac",
+ "c1": "TransactionId",
+ "c2": "4 bytes",
+ "c3": "XID for VACUUM operation moving a row version"
+ },
+ {
+ "c0": "t_ctid",
+ "c1": "ItemPointerData",
+ "c2": "6 bytes",
+ "c3": "current TID of this or newer row version"
+ },
+ {
+ "c0": "t_infomask2",
+ "c1": "uint16",
+ "c2": "2 bytes",
+ "c3": "number of attributes, plus various flag bits"
+ },
+ {
+ "c0": "t_infomask",
+ "c1": "uint16",
+ "c2": "2 bytes",
+ "c3": "various flag bits"
+ },
+ {
+ "c0": "t_hoff",
+ "c1": "uint8",
+ "c2": "1 byte",
+ "c3": "offset to user data"
+ }
+ ],
+ "title": "HeapTupleHeaderData Layout"
+ }
+ ]
+}
比较已记录的接口与属性,排除来源指纹和构建元数据。某个样本中没有记录,不能据此判断实际引入或移除的版本。
相关条目
导出 JSON · 返回存储结构 · 收录范围为 PostgreSQL 11 至 20;最早采样版本不一定是实际引入版本。