本文为您介绍Hologres中BSI(Bit-sliced Index)扩展函数的使用。
原理介绍
BSI本质上是对(cid::int, value::bigint
)键值数据的压缩。下面以表数据为例为您介绍BSI的原理与结构。
cid | value(十进制) | value(二进制) |
1 | 3 | 0011 |
2 | 6 | 0110 |
3 | 4 | 0100 |
4 | 10 | 1010 |
5 | 7 | 0111 |
6 | NULL | - |
表中包含cid和value列。其中,value的最大值为10,即二进制最大位数为4位,因此将所有value的二进制值补充为4位。然后对二进制数据从低位向高位遍历,记录每位值为1时对应的cid数组的roaringbitmap,形成位切片索引Bit-sliced Index(BSI)。上表数据最终建立了如下切片索引:
slice 0:roaringbitmap '{1,5}'
slice 1:roaringbitmap '{1,2,4,5}'
slice 2:roaringbitmap '{2,3,5}'
slice 3:roaringbitmap '{4}'
此外,BSI中还会存储如下信息:
Existence bitmap(ebm):存储cid数组(值非空)的roaringbitmap,本示例中为roaringbitmap '{1,2,3,4,5}'。
max:value的最大值,本示例为10。
min:value的最小值,本示例为3。
bitCount:value的二进制位数,本示例为4。
基于上述原理与示例,如果已经通过RoaringBitmap进行位图计算,得到某个人群圈选结果为crowd='{1,3,5}',通过BSI即可继续针对value的高效计算,快速得到结果。比如:
计算圈选的人群对应的value之和:
rb_and_cardinality(crowd, slice0) * 20 + ... + rb_and_cardinality(crowd, slice3) * 23 = 14
计算圈选的人群对应的value的Top 2:
crowd & slice3 = NULL crowd & slice2 = {3,5} -- top2为{3,5} {3,5} & slice1 = {5} -- top1为{5}
通过BSI算法,对键值数据进行压缩存储,可以将cid的RoaringBitmap计算与value的计算完美结合,有效提升用户画像分析场景下“属性标签”与“行为标签”结合的计算效率。基于BSI函数的用户画像分析方案请参见画像分析 - BSI优化方案(Beta)。
使用限制
仅Hologres V2.1版本起支持BSI函数,如果您的实例版本为V2.1以下版本,请先升级实例版本,详情请参见实例升级。
BSI函数中的各个值仅支持正整数(1 ~ 231-1),不支持0和负数。
需要Superuser执行以下语句开启两个Extension。创建Extension是DB级别,一个DB只需要开启一次即可。
--创建extension。创建bsi需要先创建roaringbitmap CREATE EXTENSION roaringbitmap; CREATE EXTENSION bsi; --删除extension DROP EXTENSION roaringbitmap; DROP EXTENSION bsi;
重要不推荐使用
DROP EXTENSION <extension_name> CASCADE;
命令级联卸载Extension。CASCADE(级联)删除命令不仅会删除指定扩展本身,还会一并清除扩展数据(例如PostGIS数据、RoaringBitmap数据、Proxima数据、Binlog数据、BSI数据等)以及依赖该扩展的对象(包括元数据、表、视图、Server数据等)。
函数列表
BSI构造函数
函数名 | 输入 | 输出 | 描述 | 示例 | 返回结果 |
bsi_build | integer[], bigint[] | bsi | 通过两个一维数据创建一个BSI。 |
|
|
bsi_add_value | bsi, integer, bigint | bsi | 为BSI增加一个键值对。 |
|
|
BSI展开函数
函数名 | 输入 | 输出 | 描述 | 示例 | 返回结果 |
bsi_iterate | bsi | set of integer[] | 将BSI按键值展开。 |
|
|
bsi_show | bsi/bytea, integer | text | 将BSI按键值展开,并展示前integer个键值对。 |
|
|
BSI查询函数
函数名 | 输入 | 输出 | 描述 | 示例 | 返回结果 |
bsi_ebm | bsi/bytea | roaringbitmap | 查询BSI的ebm数组的roaringbitmap。 |
|
|
bsi_eq | bsi, bigint [, bytea] | roaringbitmap | 查询BSI value等于bigint的部分,返回对应ebm数组的roaringbitmap。 如果有第三入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再进行比较查询。 |
|
|
bsi_filter | bsi/bytea, bytea | bsi | 查询BSI的ebm和指定bytea的交集部分,返回新的BSI。 |
|
|
bsi_ge | bsi, bigint [, bytea] | roaringbitmap | 查询BSI的value大于等于bigint的部分,返回对应ebm组成的roaringbitmap。 如果有第三入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再进行比较查询。 |
|
|
bsi_gt | bsi, bigint [, bytea] | roaringbitmap | 查询BSI的value大于bigint的部分,返回对应ebm组成的roaringbitmap。 如果有第三入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再进行比较查询。 |
|
|
bsi_le | bsi, bigint [, bytea] | roaringbitmap | 查询BSI的value小于等于bigint的部分,返回对应ebm组成的roaringbitmap。 如果有第三入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再进行比较查询。 |
|
|
bsi_lt | bsi, bigint [, bytea] | roaringbitmap | 查询BSI的value小于bigint的部分,返回对应ebm组成的roaringbitmap。 如果有第三入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再进行比较查询。 |
|
|
bsi_neq | bsi, bigint [, bytea] | roaringbitmap | 查询BSI的value不等于bigint的部分,返回对应ebm组成的roaringbitmap。 如果有第三入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再进行比较查询。 |
|
|
bsi_range | bsi, bigint, bigint [, bytea] | roaringbitmap | 查询BSI的value介于两个bigint之间(两端闭区间)的部分,返回对应ebm组成的roaringbitmap。 如果有第三入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再进行比较查询。 |
|
|
bsi_compare | text, bsi, [bytea,] bigint, bigint | roaringbitmap | 对BSI进行比较过滤查询。
|
|
|
BSI聚合分析函数
函数名 | 输入 | 输出 | 描述 | 示例 | 返回结果 |
bsi_add | bsi, bsi | bsi | 将两个BSI相同ebm对应的value相加,返回新的BSI。 |
|
|
bsi_add_agg | bsi | bsi | 求和聚合计算。 |
|
|
bsi_merge | bsi, bsi | bsi | 将两个BSI合并,要求两个BSI的ebm没有交集。 |
|
|
bsi_merge_agg | bsi | bsi | 合并聚合计算,要求BSI的ebm没有交集。 |
|
|
bsi_stat | bigint[], bsi/bytea [, bytea] | text | BSI value的分布统计。分布区间根据输入的边界值数组切分。 如果有第三入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再进行分布统计。 |
|
|
bsi_sum | bsi/bytea [, bytea] | bigint[] | 返回BSI value之和sum以及ebm基数cardinality组成的数组。 如果有第二入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再计算sum与基数。 |
|
|
bsi_topk | bsi/bytea, [bytea, ] integer | roaringbitmap | 返回BSI top k个最大value对应的ebm组成的roaringbitmap。 如果有第二入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再计算top K。 |
|
|
bsi_transpose | bsi/bytea [, bytea] | roaringbitmap | 返回BSI的value转置结果,即去重后组成的roaringbitmap。 如果有第二入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再计算转置。 |
|
|
bsi_transpose_with_count | bsi/bytea [, bytea] | bsi | 将BSI的value转置并统计次数,返回新的BSI。 如果有第二入参roaringbitmap类型序列化的bytea,则先查询BSI的ebm和bytea的交集部分,再计算转置并统计。 |
|
|