KingbaseESV8R6使用pageinspect插件观察空值

发布时间 2023-09-19 18:42:00作者: KINGBASE研究院

前言

在KingbaseES元组头数据中,有一个t_bits数组,用于存储空值位图。当元组中没有null值的时候,t_bits是空的,当元组有null值的列时,t_bits使用一个bit来表示列是否为null。
元组中空值存储在Heap TupleData中的前位,它之后存储的是data数据。

pageinspact插件观察空值存储

创建插件

CREATE EXTENSION pageinspect;

创建测试表

create table t(a int,b int,c int);

insert into t values(2,6,1);
insert into t values(1,NULL,7);

TEST=# select * from t;
 a | b | c
---+---+---
 2 | 6 | 1
 1 |   | 7
(2 rows)

pageinspact可以观察空值是如何存储的

字段说明:
t_bits数组不为空:10100000,第一和第三个1表示这两列不为空,中间的0表示第二列为空,其余的0表示这些列未被使用。
t_data中的记录不包含空值数据。

TEST=# select * from heap_page_items(get_raw_page('t',0));
 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_data
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+----------+-------+----------------------------
  1 |   8152 |        1 |     36 |   2040 |      0 |        0 | (0,1)  |           3 |       2304 |     24 |          |       | \x020000000600000001000000
  2 |   8120 |        1 |     32 |   2041 |      0 |        0 | (0,2)  |           3 |       2305 |     24 | 10100000 |       | \x0100000007000000
(2 rows)

为了看t_bits列更清晰,我们创建表后多加几列

说明:
第四行没有空值,因此对应t_bits数组为空。
一共12列,因此数组中后四位均未用到,均为0。
111111111101中的0表示null值的位置,所以t_bits仅显示出有空值的元组。

create table t02(i1 int,i2 int,i3 int,i4 int,i5 int,i6 int, i7 int,i8 int,i9 int,i10 int,i11 int,i12 int);
insert into t02 values(1,2,3,4,5,6,7,8,9,10,NULL,12);
insert into t02 values(1,2,3,4,5,6,7,8,9,NULL,NULL,12);
insert into t02 values(1,2,3,4,5,6,7,8,NULL,NULL,NULL,12);
insert into t02 values(1,2,3,4,5,6,7,8,9,10,11,12);

select t_bits from  heap_page_items(get_raw_page('t02', 0));

      t_bits     

------------------
 1111111111010000
 1111111110010000
 1111111100010000

(4 rows)

观察表中删掉其中一列的效果

alter table t02 drop column i1;
TEST=# select t_bits from  heap_page_items(get_raw_page('t02', 0));
      t_bits
------------------
 1111111111010000
 1111111110010000
 1111111100010000

位图并没有变化

再插入一行非空值
insert into t02 values(2,3,4,5,6,7,8,9,10,11,12);
TEST=# select t_bits from  heap_page_items(get_raw_page('t02', 0));
      t_bits
------------------
 1111111111010000
 1111111110010000
 1111111100010000

 0111111111110000
(5 rows)

可以看到,表中已删除列为第一列,被视为空列,以0标识,这里的0并不是空值的意思,然后连续出现11个1,表示该元组没有空值。
当表中有许多列时,删除列将为每条记录生成额外的t_bit,这将导致存储膨胀。