大家好,欢迎来到IT知识分享网。

作者:吴聪
在PostgreSQL的page头部使用t_bits来表示null值的列。
定义如下:
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]; /* bitmap of NULLs */
之前看的时候以为其长度就是8个bit位,用1个字节来存储。今天和别人聊的时候才发现如果只是8个bit位那完全不够啊,pg中表最多允许1600列,那不是应该需要1600位?
于是建个70列的表测试下看看:
bill@bill=>create table t1( bill(# c1 int, c2 int, c3 int, c4 int, c5 int, bill(# c6 int, c7 int, c8 int, c9 int, c10 int, bill(# c11 int, c12 int, c13 int, c14 int, c15 int, bill(# c16 int, c17 int, c18 int, c19 int, c20 int, bill(# c21 int, c22 int, c23 int, c24 int, c25 int, bill(# c26 int, c27 int, c28 int, c29 int, c30 int, bill(# c31 int, c32 int, c33 int, c34 int, c35 int, bill(# c36 int, c37 int, c38 int, c39 int, c40 int, bill(# c41 int, c42 int, c43 int, c44 int, c45 int, bill(# c46 int, c47 int, c48 int, c49 int, c50 int, bill(# c51 int, c52 int, c53 int, c54 int, c55 int, bill(# c56 int, c57 int, c58 int, c59 int, c60 int, bill(# c61 int, c62 int, c63 int, c64 int, c65 int, bill(# c66 int, c67 int, c68 int, c69 int, c70 int bill(# ); CREATE TABLE
插入数据查看t_bits:
bill@bill=>insert into t1(c1,c2) values(1,1); INSERT 0 1 bill@bill=>select * from heap_page_items(get_raw_page('t1',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 | 40 | 3974 | 0 | 0 | (0,1) | 70 | 2049 | 32 | 000000000000000000000000000000000 0000000000000000000000000000 | | \x00000 (1 row)
可以看到t_bits总共72位,前两位为1刚好表示c1和c2列不为空。那看来t_bits的大小确实不是8个bit位就能搞定的,那是怎么计算的呢?
仔细观察发现,t_bits[FLEXIBLE_ARRAY_MEMBER]其实是使用了C语言中的FLEXIBLE_ARRAY_MEMBER,即弹性数组。这个之前确实也不太清楚,查了下资料什么是弹性数组呢?
其形式如下:
struct Foo { int a; char b[]; // 有时也写成 char b[0];};
如果不使用弹性数组,那么我们需要写成:
struct Foo { int a;};struct Foo *foo = malloc(sizeof(struct Foo) + 128);char *b = (char *)foo + sizeof(struct Foo);
这样就能很明显的看出,弹性数组只是一个语法糖,它在结构体最后增加一个成员变量,让我们可以使用foo->b这种方式,直接访问结构体之后的内存。事实上,你如果自己计算偏移量,也可以到达一样的效果。
而这里的t_bits是其实也是这样,其长度是要在使用时去计算偏移量的。
#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8) if (hasnull) len += BITMAPLEN(numberOfAttributes);
可以看到t_bits的长度其实是和列的个数有关的,这也是为什么定义为bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]的原因了。
参考链接:
https://zhuanlan.zhihu.com/p/
include/access/htup_details.h
backend/access/common/heaptuple.c
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/179284.html