我一直在研究 postgres 实际上如何在堆表元组中存储数据
我最初创建了表格,并填充了示例值。 后来尝试打印存储的属性
test=# SELECT * FROM heap_page_item_attrs(get_raw_page('sectable', 0), 'sectable'::regclass);^C
test=# CREATE table exp(id int, value varchar(10));
CREATE TABLE
test=# insert into exp(id, value) values (1, 'cat');
INSERT 0 1
test=# select * from exp;
id | value
----+-------
1 | cat
(1 row)
test=# SELECT * FROM heap_page_item_attrs(get_raw_page('exp', 0), 'exp'::regclass);
lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_attrs
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------+-------------------------------
1 | 8160 | 1 | 32 | 758 | 0 | 0 | (0,1) | 2 | 2306 | 24 | | | {"\\x01000000","\\x09636174"}
(1 row)
test=# insert into exp(id, value) values (2, 'x');
INSERT 0 1
test=# SELECT * FROM heap_page_item_attrs(get_raw_page('exp', 0), 'exp'::regclass);
lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_attrs
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------+-------------------------------
1 | 8160 | 1 | 32 | 758 | 0 | 0 | (0,1) | 2 | 2306 | 24 | | | {"\\x01000000","\\x09636174"}
2 | 8128 | 1 | 30 | 759 | 0 | 0 | (0,2) | 2 | 2050 | 24 | | | {"\\x02000000","\\x0578"}
(2 rows)
值 cat 存储为:\x09636174(t_data 字段) 值“x”存储为 \x0578
问题在于为什么 cat 值在开头有额外的 09,因为从十六进制转换为文本时 636174 给出了 CAT 同样,对于“x”,其十六进制值为 78,但在开头附加了额外的 05,我无法理解。
存储的值 cat 应该是 \x636174 并且存储的值“x”应该\x78
我尝试搜索 postgres 代码,但找不到任何与此相关的内容。
存储可变长度数据类型(如
character varying
)的常规方法是使用包含数据长度的四字节标头。
PostgreSQL的TOAST机制将短数据缩短为单个字节,多出的一位表示TOAST。
如果您对实现感兴趣,请在源代码中查找关键字“varlena”和“toast”。