本文为您介绍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保留
相关文档
关于Hologres内部表DDL语句的介绍详情,请参见: