PostgreSQL记录中的null值是如何存储的
2020-10-27 09:10 abce 阅读(1595) 评论(0) 编辑 收藏 举报
PostgreSQL如何存储null值的?
PostgreSQL存储null值的方法
使用pageinspact工具来观察null是如何存储的。执行下面的测试:
postgres=# create table t(i int, j int, k int); CREATE TABLE postgres=# insert into t values(8,1,6); INSERT 0 1 postgres=# insert into t values(3,NULL,7); INSERT 0 1 postgres=# insert into t values(4,9,2); INSERT 0 1 postgres=# select lp,t_infomask,t_bits,t_data from heap_page_items(get_raw_page('t', 0)); lp | t_infomask | t_bits | t_data ----+------------+----------+---------------------------- 1 | 2048 | | \x080000000100000006000000 2 | 2049 | 10100000 | \x0300000007000000 3 | 2048 | | \x040000000900000002000000 (3 rows) postgres=#
可以看到,null值没有在元组的数据部分标记出来。
同时,可以看到带有null值的第二条记录的't_infomask'和’t_bits‘的值与第一条和第三条是不一致的。因此,这可能就是如何读取null值的秘密所在。
‘t_bits’是一个uint8的数组,当元组中没有null值的时候,t_bits可以被认为是空的,当元组有null值的列时,t_bits使用一个位(bit)来表示一个列是否为null。
postgres=# create table t0(i1 int,i2 int,i3 int,i4 int,i5 int,i6 int, postgres(# i7 int,i8 int,i9 int,i10 int,i11 int,i12 int postgres(# ); CREATE TABLE postgres=# insert into t0 values(1,2,3,4,5,6,7,8,9,10,NULL,12); INSERT 0 1 postgres=# insert into t0 values(1,2,3,4,5,6,7,8,9,NULL,NULL,12); INSERT 0 1 postgres=# insert into t0 values(1,2,3,4,5,6,7,8,NULL,NULL,NULL,12); INSERT 0 1 postgres=# insert into t0 values(1,2,3,4,5,6,7,8,9,10,11,12); INSERT 0 1 postgres=# postgres=# select lp,t_infomask,t_bits from heap_page_items(get_raw_page('t0', 0)); lp | t_infomask | t_bits ----+------------+------------------ 1 | 2049 | 1111111111010000 2 | 2049 | 1111111110010000 3 | 2049 | 1111111100010000 4 | 2048 | (4 rows) postgres=#
上面的脚本会创建一个表t0,共有12个列,然后插入几条元组,执行pageinspect工具查询研究元组。注意看元组的t_bits值:
可以得出结论:
·在t_bits中,尚未使用的标记为是0
·1表示对应的列是非空的(not null),否则就是null
在PostgreSQL中,表的列被删除后,这个列的数据结构会被保留在目录中,但是对用户是不可见的。完成下面的测试:
postgres=# alter table t0 drop column i1; ALTER TABLE postgres=# insert into t0 values(2,3,4,5,6,7,8,9,10,11,12); INSERT 0 1 postgres=# select lp,t_infomask,t_bits from heap_page_items(get_raw_page('t0', 0)); lp | t_infomask | t_bits ----+------------+------------------ 1 | 2049 | 1111111111010000 2 | 2049 | 1111111110010000 3 | 2049 | 1111111100010000 4 | 2048 | 5 | 2049 | 0111111111110000 (5 rows) postgres=#
在这个测试中,我们删除了表t0的列'i1'并插入一个不含有null值的记录。使用pageinspact工具,我们可以发现插入的不含有null值的数据(lp=5)。被删除的列的t_bits值显示其也被认为是null值。
结论