本文为您介绍Hologres中位图索引Bitmap的使用相关内容。
Bitmap介绍
在Hologres中,bitmap_columns
属性指定位图索引,是数据存储之外的独立索引结构,以位图向量结构加速等值比较场景,能够对文件块内的数据进行快速的等值过滤,适用于等值过滤查询的场景。使用语法如下。
-- Hologres V2.1版本起支持的语法
CREATE TABLE <table_name> (...) WITH (bitmap_columns = '[<columnName>{:[on|off]}[,...]]');
-- 所有版本支持的语法
CREATE TABLE <table_name> (...);
CALL set_table_property('<table_name>', 'bitmap_columns', '[<columnName>{:[on|off]}[,...]]');
参数 | 说明 |
table_name | 表名称。 |
columnName | 列名称。 |
on | 当前字段打开位图索引。 |
off | 当前字段关闭位图索引。 |
使用建议
适合将等值查询的列设置为Bitmap,能够快速定位到符合条件的数据所在的行号。但需要注意的是Bitmap对于基数比较高(重复数据较少)的列会有比较大的额外存储开销。
不建议为每一列都设置Bitmap,不仅会有额外存储开销,也会影响写入性能(因为要为每一列构造Bitmap)。
不建议为实际内容为JSON,但保存为text类型的列设置Bitmap。
使用限制
只有列存表和行列共存表支持设置Bitmap,行存表不支持设置。
Bitmap指定的列可以为空。
当前版本默认所有TEXT类型的列都会被隐式地设置为Bitmap。
设置位图索引命令可以在事务之外单独使用,表示修改位图索引列,修改之后非立即生效,比特编码构建和删除在后台异步执行,详情请参见ALTER TABLE。
bitmap_columns
属性仅支持设为on
或off
,Hologres V2.0版本起,不支持将bitmap_columns
属性设为auto
。
技术原理
Bitmap不同于Distribution Key和Clustering Key,Bitmap是数据存储之外的独立索引,设置了Bitmap索引之后,系统会将列对应的数值生成一个二进制字符串,用于表示取值所在位置的Bitmap,当查询命中Bitmap时,会快速定位到数据所在的行号(Row Number),从而快速过滤出数据。但Bitmap并不是没有开销的,对于以下场景需要注意事项如下:
列的基数较高(重复数据较少)场景:假如列的基数较高,那么就会为每一个值生成一个Bitmap,当非重复值很多的时候,就会形成稀疏数组,占用存储较多。
大宽表的每一列都设置为Bitmap场景:如果为大宽表的每一列都设置为Bitmap,那么在写入时每个值都需要构建成Bitmap,会有一定的系统开销,从而影响写入性能。
综上,Bitmap本质上是空间换时间的手段,对于数据分布比较均匀的列有比较高的性价比。
如下示例,可以通过explain SQL
查看是否命中Bitmap索引。在执行计划中,有Bitmap Filter
则说明命中Bitmap索引。
V2.1版本起支持的语法:
CREATE TABLE bitmap_test ( uid int NOT NULL, name text NOT NULL, gender text NOT NULL, class text NOT NULL, PRIMARY KEY (uid) ) WITH ( bitmap_columns = 'gender,class' ); INSERT INTO bitmap_test VALUES (1,'张三','男','一班'), (2,'李四','男','三班'), (3,'王五','女','二班'), (4,'赵六','女','二班'), (5,'孙七','男','二班'), (6,'周八','男','三班'), (7,'吴九','女','一班'); explain SELECT * FROM bitmap_test where gender='男' AND class='一班';
所有版本支持的语法:
begin; create table bitmap_test ( uid int not null, name text not null, gender text not null, class text not null, PRIMARY KEY (uid) ); call set_table_property('bitmap_test', 'bitmap_columns', 'gender,class'); commit; INSERT INTO bitmap_test VALUES (1,'张三','男','一班'), (2,'李四','男','三班'), (3,'王五','女','二班'), (4,'赵六','女','二班'), (5,'孙七','男','二班'), (6,'周八','男','三班'), (7,'吴九','女','一班'); explain SELECT * FROM bitmap_test where gender='男' AND class='一班';
如下所示执行计划结果中有Bitmap Filter
算子,说明命中Bitmap索引。
Bitmap和Clustering Key的区别
相同点:
Bitmap和Clustering Key都是文件内的数据过滤。
不同点:
Bitmap更适合等值查询,通过文件号定位到数据;Clustering Key是文件内的排序,因此更适合范围查询。
Clustering Key的优先级会比Bitmap更高,即如果为同一个字段设置了Clustering Key和Bitmap,那么优化器会优先使用Clustering Key去匹配文件,示例如下:
V2.1版本起支持的语法:
--设置uid,class,date 3列为clustering key,text列设置默认为bitmap CREATE TABLE ck_bit_test ( uid int NOT NULL, name text NOT NULL, class text NOT NULL, date text NOT NULL, PRIMARY KEY (uid) ) WITH ( clustering_key = 'uid,class,date', bitmap_columns = 'name,class,date' ); INSERT INTO ck_bit_test VALUES (1,'张三','1','2022-10-19'), (2,'李四','3','2022-10-19'), (3,'王五','2','2022-10-20'), (4,'赵六','2','2022-10-20'), (5,'孙七','2','2022-10-18'), (6,'周八','3','2022-10-17'), (7,'吴九','3','2022-10-20');
所有版本支持的语法:
--设置uid,class,date 3列为clustering key,text列设置默认为bitmap begin; create table ck_bit_test ( uid int not null, name text not null, class text not null, date text not null, PRIMARY KEY (uid) ); call set_table_property('ck_bit_test', 'clustering_key', 'uid,class,date'); call set_table_property('ck_bit_test', 'bitmap_columns', 'name,class,date'); commit; INSERT INTO ck_bit_test VALUES (1,'张三','1','2022-10-19'), (2,'李四','3','2022-10-19'), (3,'王五','2','2022-10-20'), (4,'赵六','2','2022-10-20'), (5,'孙七','2','2022-10-18'), (6,'周八','3','2022-10-17'), (7,'吴九','3','2022-10-20');
查询
uid,class,date
三列,SQL符合左匹配特征,都命中Clustering Key,即使是等值查询也走Clustering Key,而不是走Bitmap。SELECT * FROM clustering_test WHERE uid = '3' AND class ='2' AND date > '2022-10-17';
如下所示执行计划结果中有
Cluster Filter
算子,没有Bitmap Filter
算子,说明查询走Clustering Key,而不是走Bitmap。查询
uid,class,date
三列,但class
是范围查询,根据左匹配原则,SQL里匹配到>
或者<
则停止左匹配,那么date
因不满足左匹配原则,就不会命中Clustering Key。date
设置了Bitmap,则会使用Bitmap。SELECT * FROM clustering_test WHERE uid = '3' AND class >'2' AND date = '2022-10-17';
如下所示执行计划结果中有
Cluster Filter
算子,说明查询uid,class
走走Clustering Key;有Bitmap Filter
算子,说明查询date
走Bitmap。
使用示例
V2.1版本起支持的语法:
CREATE TABLE tbl ( a text NOT NULL, b text NOT NULL ) WITH ( bitmap_columns = 'a:on,b:off' ); -- 修改bitmap_columns ALTER TABLE tbl SET (bitmap_columns = 'a:off');--ALTER TABLE语法仅支持全量修改
所有版本支持的语法:
--创建tbl并设置bitmap索引 begin; create table tbl ( a text not null, b text not null ); call set_table_property('tbl', 'bitmap_columns', 'a:on,b:off'); commit; --修改bitmap索引 call set_table_property('tbl', 'bitmap_columns', 'a:off');--全量修改,将a字段的bitmap都关闭 call update_table_property('tbl', 'bitmap_columns', 'b:off');--增量修改,将b字段的bitmap关闭,a保留