KingbaseES roaringbitmap扩展介绍
关键字
KingbaseES、roaringbitmap、大数据量、支持索引、人大金仓
问题描述
业务应用场景中常有通过标签进行筛选查询的功能,在数据量较大且标签值较多的场景下,数据容量会占用很多,性能也会较差,如何高效快速且不占用太多数据容量的情况下进行目标资源筛查,成为业务管理优化的不变话题。
roaringbitmap 在业务中常用来存储用户的属性标签,可增删改查这些属性标签以及根据这些存储的用户的标签,通过并集、交集等方法来筛选出特定的用户,以达到超大规模属性数据的精准快速查找,既提升了性能,同时也能降低存储空间,是大数据分析场景下极佳的应用实践。
Roaring Bitmap算法介绍
背景
为了解决位图稀疏存储浪费空间的问题,出现了很多稀疏位图的压缩方法,Roaring Bitmap就是其中的一种。Roaring Bitmap(高效压缩位图)是一种高效的Bitmap压缩算法,常用于标签筛选、去重、时间序列等计算中。
原理
Roaring Bitmap算法是将32位的INT类型数据划分为高16位和低16位两部分,其中高16位作为桶的编号,共划分出2^16个桶,即最多可能有2^16=65536个桶,相关论文内称为container。然后再将低 16 位值存放在相应的 Container 中(存储时如果找不到就会新建一个)。
Container的类型
①ArrayContainer(数组容器)
在创建一个新Container时,如果只插入一个元素,Roaring Bitmap默认会用ArrayContainer来存储。其中每一个元素的类型为short int 占两字节。当ArrayContainer的容量超过4096后,会自动转成BitmapContainer。
关于4096这个阈值,低于4096时,ArrayContainer比较省空间,高于它时,BitmapContainer比较省空间。ArrayContainer用来存储稀疏数据,BitmapContainer用来存储稠密数据,这样可以最大限度地避免内存浪费。
②BitmapContainer
底层实现为位图。这种Container使用long[]存储位图数据。我们知道,每个Container处理16位整形的数据,也就是0~65535,因此根据位图的原理,需要65536个bit来存储数据,每个比特位用1来表示有,用0来表示无,每个long有64位,因此需要1024个long来提供65536个比特。
这就意味着,不管一个BitmapContainer值在构建时就会初始化长度为1024的long[]。这就意味着,不管一个BitmapContainer中指存储了一个数据还是65536个数据,占用的空间都是同样的8kb。
③RunContainer
一种利用步长来压缩空间的方法。比如连续的整数序列11,12,13,14,15,27,28,29会被压缩为两个二元组11,4,27,2表示:11后面紧跟着4个连续递增的值,27后面跟着2个连续递增的值。这样一来,原先16个字节的空间,现在只需要8个字节。
问题分析
roaringbitmap扩展在不同数据库中的支持情况
数据库 | 支持roaringbimap扩展 |
KES | 支持 |
pg | 支持(开源插件) |
oracle | 不支持 |
mysql | 不支持 |
dm8 | 不支持 |
roaringbitmap扩展介绍
功能
roaringbitmap通过逻辑复杂度来换空间时间复杂度的方法对存储性能进行优化。KES使用时需要注意:
1. 此扩展非内置扩展。
2. 可重定位:alter extension能把扩展换schema。
3. 支持在oracle、pg模式下创建此扩展,其他模式下不支持。
4. roaringbitmap支持create index语法。
使用
使用roaringbitmap扩展时,需要首先创建扩展:
支持创建扩展create extension roaringbitmap;
支持卸载扩展 drop extension roaringbitmap;
数据类型
类型名称 | 描述 |
roaringbitmap | 本插件实现的基本类型,roaringbitmap类型。 |
使用示例:
select '{-1,3,5}'::roaringbitmap;
结果:
roaringbitmap
--------------------------------------------------------------------------------
\x3a3000000200000000000100ffff0000180000001c00000003000500ffff
(1 行记录)
函数
名称 | 描述 |
roaringbitmap_in | 将字符串转换为roaringbitmap类型 |
roaringbitmap_out | 将roaringbitmap类型转换为字符串 |
roaringbitmap_recv | 将二进制转换为roaringbitmap类型 |
roaringbitmap_send | 将roaringbitmap类型转换为二进制类型 |
roaringbitmap | 将二进制形式转换为roaringbitmap类型 |
rb_and | 将两个roaringbitmap类型进行与操作 |
rb_or | 将两个roaringbitmap类型进行或操作 |
rb_xor | 将两个roaringbitmap类型进行亦或操作 |
rb_andnot | 将两个roaringbitmap类型进行not操作 |
rb_add | 将roaringbitmap类型集合中添加int类型值 |
rb_remove | 将roaringbitmap类型集合中移除int类型值 |
rb_shiftright | 将roaringbitmap类型集合中的元素加上int类型值 |
rb_shiftleft | 将roaringbitmap类型集合中的元素减去int类型值 |
rb_contains | 判断两个roaringbitmap变量的包含关系 |
rb_containedby | 判断两个roaringbitmap变量的包含关系 |
rb_intersect | 返回两个roaringbitmap变量的交集 |
rb_equals | 判断两个roaringbitmap变量是否相等 |
rb_not_equals | 判断两个roaringbitmap变量是否不相等 |
rb_build | 通过int数组构建roaringbitmap变量 |
rb_index | 返回int类型值在roaringbitmap变量集合中的索引 |
rb_cardinality | 返回roaringbitmap中的元素数量 |
rb_and_cardinality | 返回两个集合交集的元素数量 |
rb_or_cardinality | 返回两个集合并集的元素数量 |
rb_xor_cardinality | 返回两个集合亦或操作后的元素数量 |
rb_andnot_cardinality | 返回两个集合差集操作后的元素数量 |
rb_is_empty | 判断roaringbitmap集合是否为空 |
rb_fill | 对roaringbitmap进行填充 |
rb_remove | 对roaringbitmap指定序列删除 |
rb_range | 返回roaringbitmap中在值域范围内的集合 |
rb_range_cardinality | 返回roaringbitmap中在值域范围内的元素数量 |
rb_min | 返回roaringbitmap中的最小值 |
rb_max | 返回roaringbitmap中的最大值 |
rb_rank | 返回roaringbitmap中小于指定值的个数 |
rb_select | 从roaringbitmap中返回指定数量的集合 |
rb_to_array | 将roaringbitmap转换成int数组 |
rb_iterate | 将roaringbitmap以表的形式输出 |
rb_or_agg | 聚集函数,对roaringbitmap进行与操作 |
rb_or_cardinality_agg | 聚集函数,对roaringbitmap进行与操作之后的元素个数 |
rb_and_agg | 聚集函数,对roaringbitmap进行或操作 |
rb_and_cardinality_agg | 聚集函数,对roaringbitmap进行或操作之后的元素个数 |
rb_xor_agg | 聚集函数,对roaringbitmap进行亦或操作 |
rb_xor_cardinality_agg | 聚集函数,对roaringbitmap进行亦或操作之后的元素个数 |
rb_gt | 对两个roaringbitmap类型进行大于比较 |
rb_ge | 对两个roaringbitmap类型进行大于等于比较 |
rb_lt | 对两个roaringbitmap类型进行小于比较 |
rb_le | 对两个roaringbitmap类型进行大于等于比较 |
rb_cmp | 对两个roaringbitmap类型进行比较 |
使用示例1:
select rb_and_cardinality('{1,2,10}','{1,10,100}');
结果:
rb_and_cardinality
-------------------------
2
(1 行记录)
使用示例2:
select rb_index('{1,10,100}',99);
结果:
rb_index
---------------
-1
(1 行记录)
转换
源类型 | 目标类型 |
roaringbitmap | bytea |
bytea | roaringbitmap |
使用示例1:
select '{1,9999}'::roaringbitmap::bytea;
结果:
bytea
--------------------------------------------------------
\x3a30000001000000000001001000000001000f27
(1 行记录)
使用示例2:
select '{1}'::roaringbitmap::bytea::roaringbitmap;
结果:
roaringbitmap
-----------------------------------------------------
\x3a3000000100000000000000100000000100
(1 行记录)
操作符
左类型 | 操作符 | 右类型 |
roaringbitmap | & | roaringbitmap |
roaringbitmap | | | roaringbitmap |
roaringbitmap | | | int4 |
roaringbitmap | # | roaringbitmap |
roaringbitmap | << | bigint |
roaringbitmap | >> | bigint |
roaringbitmap | - | roaringbitmap |
roaringbitmap | - | Int4 |
roaringbitmap | @> | roaringbitmap |
roaringbitmap | @> | Int4 |
roaringbitmap | @< | roaringbitmap |
Int4 | @< | roaringbitmap |
roaringbitmap | && | roaringbitmap |
roaringbitmap | = | roaringbitmap |
roaringbitmap | <> | roaringbitmap |
roaringbitmap | > | roaringbitmap |
roaringbitmap | >= | roaringbitmap |
roaringbitmap | < | roaringbitmap |
roaringbitmap | <= | roaringbitmap |
使用示例:
select roaringbitmap('{1,2,3}') @> roaringbitmap('{3,4,5}');
结果:
?column?
----------
f
(1 行记录)
索引
KES中的roaringbitmap插件支持Btree索引。
结论
KES支持roaringbitmap扩展,该扩展通过逻辑复杂度来换空间时间复杂度的方法对存储性能进行优化。