GaussDB(DWS)实践系列-RoaringBitmap替换方案
GaussDB(DWS)实践系列-RoaringBitmap替换方案
Roaring Bitmap(下文简称RBM)是一种高效优秀的位图压缩算法,通过位图能够快速定位一个数值是否在存在,适合大数据查询和关联计算,例如标签筛选、用户画像、去重等场景,目前也被广泛应用在部分大数据平台上。当前GaussDB(DWS)不支持,针对该场景可参考本文方法实现RoaringBitmap的场景替换,结合客户实际业务场景测试,性能也并不比RoaringBitmap差。
一、 RBM场景样例
原表如下,需要查询满足tag_code:tag_value 的值为TAC004:0.00 and TAC005:t and TAC006:abc TAC005:2021/09/08 and .....的god_id。
如果使用Roaring Bitmap插件实现,原表跑批加工为一张有bitmap字段类型的表(字段 tag_code,tag_value,user_bits(二进制类型)),通过Roaring bitmap的函数去查该表。
二、 替待方案
(一) 概念介绍
GaussDB(DWS)使用string_agg函数 + 全文检索替代 RoaringBitmap。
(1)String_agg的功能是将输入值连接成为一个字符串,用分隔符分开。返回类型和参数数据类型相同。例如SELECT string_agg(sr_item_sk, ',') FROM tpcds.store_returns where sr_item_sk < 3;
(2)全文检索可以对文档进行预处理,并且可以使后续的搜索更快速。数据类型tsvector用于存储预处理文档,tsquery用于存储查询条件。全文检索基于匹配算子@@,当一个tsvector(document)匹配到一个tsquery(query)时,则返回true。其中,tsvector(document)和tsquery(query)两种数据类型可以任意排序。例如:
查询结果: SELECT 'fat & cow'::tsquery @@ 'a fat cat sat on a mat and ate a fat rat'::tsvector AS RESULT; 查询结果: |
tsvector类型表示为文本搜索优化的文件格式,tsquery类型表示文本查询。tsvector类型表示一个检索单元,通常是一个数据库表中一行的文本字段或者这些字段的组合,tsvector类型的值是一个标准词位的有序列表,标准词位就是把同一个词的变型体都标准化相同的,在输入的同时会自动排序和消除重复。to_tsvector函数通常用于解析和标准化文档字符串。
tsquery类型表示一个检索条件,存储用于检索的词汇,并且使用布尔操作符&(AND),|(OR)和!(NOT)来组合他们,括号用来强调操作符的分组。to_tsquery函数及plainto_tsquery函数会将单词转换为tsquery类型前进行规范化处理。
(二) 实施方案
1. 创建目标表
其中数据类型tsvector用于存储预处理文档。
CREATE TABLE test_table ( god_id character varying , codevalue text, textsearchable_index_col tsvector ) WITH (orientation=row) DISTRIBUTE BY HASH(god_id); CREATE INDEX ON test_table USING gin (textsearchable_index_col); |
备注:相比于一个表达式索引,单独列(textsearchable_index_col)方法的一个优势是它没有必要在查询时明确指定分词器以便能使用索引,另一个优势是搜索比较快速,因为它没有必要重新利用to_tsvector调用来验证索引匹配。表达式索引方法更容易建立,且它需要较少的磁盘空间,因为tsvector形式没有明确存储。
2. 原表加工
原表加工后插入到目标表。
备注:tag_code||'-'||tag_value可以把字符'-'换成别的字符,但不能换成冒号':',冒号是tsvector专用的字符。
insert into test_table ( select god_id,codevalue,codevalue::tsvector from ( select god_id ,string_agg(tag_code||'-'||tag_value,' ') as codevalue from user_profile group by god_id )); |
3. 查询语句
查询1个标签
SELECT god_id, code_value FROM test_table WHERE textsearchable_index_col @@ 'TAC004-0.00' limit 200; 查询结果: select count(*) from (SELECT god_id FROM test_table WHERE textsearchable_index_col @@ 'TAC004-0.00') 查询结果: |
查询3个标签
SELECT god_id, code_value FROM test_table WHERE textsearchable_index_col @@ 'TAC004-0.00 & TAC004-abc' limit 200; 查询结果: SELECT god_id, code_value FROM test_table WHERE textsearchable_index_col @@ 'TAC004-0.00 | TAC005-abc' limit 200; 查询结果: select count(*) from (SELECT god_id, code_value FROM test_table WHERE textsearchable_index_col @@ 'TAC004-0.00 | TAC005-abc'); 查询结果: |
注意:
(1)对于to_tsvector('str1') @@ to_tsquery('str2'),to_tsvector会按照所有符号去分词,例如:
SELECT to_tsvector('fat tac01-01 2020-09-08') @@ to_tsquery('tac01-01') AS RESULT; 查询结果: |
可以修改为使用 ' str1'::tsvector @@ ' str2'
SELECT 'fat tac01-01 2020-09-08'::tsvector @@ 'tac01-01' AS RESULT; 查询结果: |
(2)因为$$在实际操作中使用有问题,需要进行语法替换,例如:
select $$a001 c1.09 d0.08 e01:20 TAC001:21 2021-09-08$$::tsvector; 需要替换成: select 'a001 c1.09 d0.08 e01:20 TAC001:21 2021-09-08'::tsvector; |
- 点赞
- 收藏
- 关注作者
评论(0)