相关
bitmapset在优化器、update、plpgsql中都有大量应用。bitmapset本身结构简单,代码量少,这里简单分析记录。
调试方法 和 口算bitmap包含哪些数的方法见最后。
内存结构
bitmapset初始化后,在内存中是Bitmapset结构后跟n个uint32的结构,见下图:
typedef struct Bitmapset
{
int nwords; /* number of words in array */
bitmapword words[FLEXIBLE_ARRAY_MEMBER]; /* really [nwords] */
} Bitmapset;
内存结构
在使用时,用到了柔型数组的技巧,在PG中有大量应用:sizeof(Bitmapset) == sizeof(int)
,可以一次性申请好全部需要的内存,释放时也只需要一次即可。在找某一个uint32时,直接用word[x]即可。
常用API
集合运算比较简单,函数都在bitmapset.c
中,下面是一些常用函数。
所有函数基本都遵循如下流程:
1、wordnum = x / 32
2、bitnum = x % 32
3、a->words[wordnum] & ((bitmapword) 1 << bitnum)
其他API
// 集合union计算
extern Bitmapset *bms_union(const Bitmapset *a, const Bitmapset *b);
// 集合相交计算
extern Bitmapset *bms_intersect(const Bitmapset *a, const Bitmapset *b);
// 集合差异计算
extern Bitmapset *bms_difference(const Bitmapset *a, const Bitmapset *b);
// 判断子集
extern bool bms_is_subset(const Bitmapset *a, const Bitmapset *b);
// 计算两个集合的关系:相等、子集、有差异
extern BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b);
// x是不是在bitmap中
extern bool bms_is_member(int x, const Bitmapset *a);
// 判断是否重叠部分
extern bool bms_overlap(const Bitmapset *a, const Bitmapset *b);
// 判断重叠List
extern bool bms_overlap_list(const Bitmapset *a, const struct List *b);
调试方法
一般使用64位系统,实际调试时基本都是用64取余的。
例如有变量hot_attrs、key_attrs
Bitmapset *hot_attrs;
Bitmapset *key_attrs;
(gdb) p *hot_attrs
$23 = {nwords = 1, words = 0x1ca5818}
(gdb) p *key_attrs
$24 = {nwords = 1, words = 0x1ca5910}
查看二进制的值
nwords=1就只有一个words[0],否则用words[n]看后面的
(gdb) p/t (unsigned long int)hot_attrs->words[0]
$21 = 1101100000000
(gdb) p/t (unsigned long int)key_attrs->words[0]
$25 = 100000000
口算值word[0]的1101100000000:包含8、9、11、12
1101100000000:因为在words[0],所以这一组都是直接 余64出来的,数1在第几位就可以了。这里包含8、9、11、12
验证:
(gdb) p bms_is_member(8,hot_attrs)
$26 = true
(gdb) p bms_is_member(9,hot_attrs)
$27 = true
(gdb) p bms_is_member(10,hot_attrs)
$28 = false
(gdb) p bms_is_member(11,hot_attrs)
$29 = true
(gdb) p bms_is_member(12,hot_attrs)
$30 = true
口算值word[1]的0000000000010:包含66
0000000000010:因为在words[1],所以这一组是除了一个64然后余64出来的,数1在第2位:64+2=66