全部產品
Search
文件中心

Hologres:BSI函數

更新時間:Jun 30, 2024

本文為您介紹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的計算完美結合,有效提升使用者Portrait analysis情境下“屬性標籤”與“行為標籤”結合的計算效率。基於BSI函數的使用者Portrait analysis方案請參見Portrait analysis - BSI最佳化方案(Beta)

使用限制

  • 僅Hologres V2.1版本起支援BSI函數,如果您的執行個體版本為V2.1以下版本,請先升級執行個體版本,詳情請參見執行個體升級

  • 需要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。

SELECT bsi_iterate(bsi_build('{1,2,3}','{2,4,6}'));
{1,2}
{2,4}
{3,6}

bsi_add_value

bsi, integer, bigint

bsi

為BSI增加一個索引值對。

SELECT bsi_iterate(bsi_add_value(bsi_build('{1,2,3}','{2,4,6}'),4,8));
{1,2}
{2,4}
{3,6}
{4,8}

BSI展開函數

函數名

輸入

輸出

描述

樣本

返回結果

bsi_iterate

bsi

set of integer[]

將BSI按索引值展開。

SELECT bsi_iterate(bsi_build('{1,2,3}','{2,4,6}'));
{1,2}
{2,4}
{3,6}

bsi_show

bsi/bytea, integer

text

將BSI按索引值展開,並展示前integer個索引值對。

SELECT bsi_show(bsi_build('{1,2,3}','{2,4,6}'),2);
1=2,2=4...left 1

BSI查詢函數

函數名

輸入

輸出

描述

樣本

返回結果

bsi_ebm

bsi/bytea

roaringbitmap

查詢BSI的ebm數組的roaringbitmap。

SELECT rb_to_array(bsi_ebm(bsi_build('{1,2,3}','{2,4,6}')));
{1,2,3}

bsi_eq

bsi, bigint [, bytea]

roaringbitmap

查詢BSI value等於bigint的部分,返回對應ebm數組的roaringbitmap。

如果有第三入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再進行比較查詢。

SELECT rb_to_array(bsi_eq(bsi_build('{1,2,3,4}','{2,4,4,8}'),4));
{2,3}

bsi_filter

bsi/bytea, bytea

bsi

查詢BSI的ebm和指定bytea的交集部分,返回新的BSI。

SELECT bsi_iterate(bsi_filter(bsi_build('{1,2,3}','{2,4,6}'),rb_build('{1,2}')));
{1,2}
{2,4}

bsi_ge

bsi, bigint [, bytea]

roaringbitmap

查詢BSI的value大於等於bigint的部分,返回對應ebm組成的roaringbitmap。

如果有第三入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再進行比較查詢。

SELECT rb_to_array(bsi_ge(bsi_build('{1,2,3,4}','{2,4,4,8}'),4));
{2,3,4}

bsi_gt

bsi, bigint [, bytea]

roaringbitmap

查詢BSI的value大於bigint的部分,返回對應ebm組成的roaringbitmap。

如果有第三入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再進行比較查詢。

SELECT rb_to_array(bsi_gt(bsi_build('{1,2,3,4}','{2,4,4,8}'),4));
{4}

bsi_le

bsi, bigint [, bytea]

roaringbitmap

查詢BSI的value小於等於bigint的部分,返回對應ebm組成的roaringbitmap。

如果有第三入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再進行比較查詢。

SELECT rb_to_array(bsi_le(bsi_build('{1,2,3,4}','{2,4,4,8}'),4));
{1,2,3}

bsi_lt

bsi, bigint [, bytea]

roaringbitmap

查詢BSI的value小於bigint的部分,返回對應ebm組成的roaringbitmap。

如果有第三入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再進行比較查詢。

SELECT rb_to_array(bsi_lt(bsi_build('{1,2,3,4}','{2,4,4,8}'),4));
{1}

bsi_neq

bsi, bigint [, bytea]

roaringbitmap

查詢BSI的value不等於bigint的部分,返回對應ebm組成的roaringbitmap。

如果有第三入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再進行比較查詢。

SELECT rb_to_array(bsi_neq(bsi_build('{1,2,3,4}','{2,4,4,8}'),4));
{1,4}

bsi_range

bsi, bigint, bigint [, bytea]

roaringbitmap

查詢BSI的value介於兩個bigint之間(兩端閉區間)的部分,返回對應ebm組成的roaringbitmap。

如果有第三入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再進行比較查詢。

SELECT rb_to_array(bsi_range(bsi_build('{1,2,3,4}','{2,4,4,8}'),3,5));
{2,3}

bsi_compare

text, bsi, [bytea,] bigint, bigint

roaringbitmap

對BSI進行比較過濾查詢。

  • text定義比較類型,支援LT/LE/GT/GE/EQ/NEQ/RANGE。

  • bytea(可選)用於對bsi進行過濾。

  • bigint定義用於比較的值,僅RANGE比較需要兩個bigint入參。

SELECT rb_to_array(bsi_compare('RANGE',bsi_build('{1,2,3,4}','{2,4,4,8}'),3,5));
{2,3}

BSI彙總分析函數

函數名

輸入

輸出

描述

樣本

返回結果

bsi_add

bsi, bsi

bsi

將兩個BSI相同ebm對應的value相加,返回新的BSI。

SELECT bsi_iterate(bsi_add(bsi_build('{1,2,3}','{2,4,6}'),bsi_build('{1,2}','{2,4}')));
{1,4}
{2,8}
{3,6}

bsi_add_agg

bsi

bsi

求和彙總計算。

SELECT bsi_iterate(bsi_add_agg(bsi_build('{1,2,3}','{2,4,6}')));
{1,2}
{2,4}
{3,6}

bsi_merge

bsi, bsi

bsi

將兩個BSI合并,要求兩個BSI的ebm沒有交集。

SELECT bsi_iterate(bsi_merge(bsi_build('{1,2}','{2,4}'),bsi_build('{3,4}','{6,8}')));
{1,2}
{2,4}
{3,6}
{4,8}

bsi_merge_agg

bsi

bsi

合并彙總計算,要求BSI的ebm沒有交集。

SELECT bsi_iterate(bsi_merge_agg(bsi_build('{1,2,3}','{2,4,6}')));
{1,2}
{2,4}
{3,6}

bsi_stat

bigint[], bsi/bytea [, bytea]

text

BSI value的分布統計。分布區間根據輸入的邊界值數組切分。

如果有第三入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再進行分布統計。

SELECT bsi_stat('{1,3,5}',bsi_build('{1,2,3,4}','{2,4,6,8}'));
(0,1]=0;(1,3]=1;(3,5]=1;(5,8]=2

bsi_sum

bsi/bytea [, bytea]

bigint[]

返回BSI value之和sum以及ebm基數cardinality組成的數組。

如果有第二入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再計算sum與基數。

SELECT bsi_sum(bsi_build('{1,2,3,4}','{2,4,6,8}'));
{20,4}

bsi_topk

bsi/bytea, [bytea, ] integer

roaringbitmap

返回BSI top k個最大value對應的ebm組成的roaringbitmap。

如果有第二入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再計算top K。

SELECT rb_to_array(bsi_topk(bsi_build('{1,2,3,4,5}','{2,4,6,8,10}'),3));
{3,4,5}

bsi_transpose

bsi/bytea [, bytea]

roaringbitmap

返回BSI的value轉置結果,即去重後組成的roaringbitmap。

如果有第二入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再計算轉置。

SELECT rb_to_array(bsi_transpose(bsi_build('{1,2,3,4,5}','{2,4,4,8,8}')));
{2,4,8}

bsi_transpose_with_count

bsi/bytea [, bytea]

bsi

將BSI的value轉置並統計次數,返回新的BSI。

如果有第二入參roaringbitmap類型序列化的bytea,則先查詢BSI的ebm和bytea的交集部分,再計算轉置並統計。

SELECT bsi_iterate(bsi_transpose_with_count(bsi_build('{1,2,3,4,5}','{2,4,4,8,8}')));
{2,1}
{4,2}
{8,2}