跳到主要内容
版本:Latest-3.2

Bitmap 索引

本文介绍了如何创建和管理 bitmap(位图)索引,以及 Bitmap 索引的使用案例。

Bitmap 索引是一种使用 bitmap 的特殊数据库索引。bitmap 即为一个 bit 数组,一个 bit 的取值有两种:0 或 1。每一个 bit 对应数据表中的一行,并根据该行的取值情况来决定 bit 的取值是 0 还是 1。

Bitmap 索引能够提高指定列的查询效率。如果一个查询条件命中列,StarRocks 即可使用前缀索引提高查询效率,快速返回查询结果。但是前缀索引的长度有限,如果想要提高一个非前缀索引列的查询效率,即可以为这一列创建 Bitmap 索引。

Bitmap 索引一般适用于高基数列,基于列构建的 Bitmap 索引的选择性高,并且使用 Bitmap 索引后能筛选出较少数据行的场景。 ​ 在 StarRocks 中使用 SSB 100G 测试数据集验证 Bitmap 索引加速查询的效果,测试结果如下:

  • 只有为高基数列创建 Bitmap 索引,查询性能才会有比较明显的提升(在此测试数据集中,基数达到 100000 数量级可以看到比较明显的性能提升)。
  • 高基数列可以是高基数的单列,也可以是高基数的多列组合。
  • 为低基数列创建 Bitmap 索引,查询性能基本没有提升甚至会下降。

优势

  • Bitmap 索引所占的存储空间通常只有索引数据的一小部分,与其他索引技术相比,更节省存储空间。
  • 支持为多个列创建 Bitmap 索引,提高多列查询的效率,具体参见多列查询

使用说明

  • Bitmap 索引适用于可使用等值条件 (=) 查询或 [NOT] IN 范围查询的列。
  • 主键表和明细表中所有列都可以创建 Bitmap 索引;聚合表和更新表中,只有维度列(即 Key 列)支持创建 bitmap 索引。
  • 支持为如下类型的列创建 Bitmap 索引:
    • 日期类型:DATE、DATETIME。
    • 数值类型:TINYINT、SMALLINT、INT、BIGINT、LARGEINT、DECIMAL 和 BOOLEAN。
    • 字符串类型:CHAR、STRING 和 VARCHAR。
    • 其他类型:HLL。
  • 如要了解一个查询是否命中了 Bitmap 索引,可查看该查询的 Profile 中的 BitmapIndexFilterRows 字段。关于如何查看 Profile,参见分析查询

创建索引

  • 建表时创建 Bitmap 索引。

    CREATE TABLE d0.table_hash
    (
    k1 TINYINT,
    k2 DECIMAL(10, 2) DEFAULT "10.5",
    v1 CHAR(10) REPLACE,
    v2 INT SUM,
    INDEX index_name (column_name) [USING BITMAP] [COMMENT '']
    )
    ENGINE = olap
    AGGREGATE KEY(k1, k2)
    DISTRIBUTED BY HASH(k1)
    PROPERTIES ("storage_type" = "column");

    其中有关索引部分参数说明如下:

    参数必选说明
    index_nameBitmap 索引名称。命名要求参见系统限制。在同一张表中不能创建名称相同的索引。
    column_name创建 Bitmap 索引的列名。您可以指定多个列名,即在建表时可同时为多个列创建 Bitmap 索引。
    COMMENT索引备注。

    您可以指定多条 INDEX index_name (column_name) [USING BITMAP] [COMMENT ''] 命令同时为多个列创建 bitmap 索引,且多条命令之间用逗号(,)隔开。 关于建表的其他参数说明,参见 CREATE TABLE

  • 建表后使用 CREATE INDEX 创建 Bitmap 索引。详细参数说明和示例,参见 CREATE INDEX

    CREATE INDEX index_name ON table_name (column_name) [USING BITMAP] [COMMENT ''];

创建进度

创建 Bitmap 索引为异步过程,执行索引创建语句后可通过 SHOW ALTER TABLE 命令查看索引创建进度,当返回值中 State 字段显示为 FINISHED 时,即为创建成功。

SHOW ALTER TABLE COLUMN [FROM db_name];

说明:当前每张表只允许同时进行一个 Schema Change 任务,在一个 Bitmap 索引未异步创建完成前,无法进行新 Bitmap 索引的创建。

查看索引

查看指定表的所有 Bitmap 索引。详细参数和返回结果说明,参见 SHOW INDEX

SHOW { INDEX[ES] | KEY[S] } FROM [db_name.]table_name [FROM db_name];

说明

创建 Bitmap 索引为异步过程,使用如上语句只能查看到已经创建完成的索引。

删除索引

删除指定表的 Bitmap 索引。详细参数说明和示例,参见 DROP INDEX

DROP INDEX index_name ON [db_name.]table_name;

使用案例

例如,有表 employee,其包含了某公司的员工信息。如下展示了表 employee 的部分数据。

IDGenderPositionIncome_level
01femaleDeveloperlevel_1
02femaleAnalystlevel_2
03femaleSalesmanlevel_1
04maleAccountantlevel_3

单列查询

例如,要提高 Gender 列的查询效率,即可为该列创建 Bitmap 索引。

CREATE INDEX index1 ON employee (Gender) USING BITMAP COMMENT 'index1';

如上语句执行后,bitmap 索引生成的过程如下:

figure

  1. 构建字典:StarRocks 根据 Gender 列的取值构建一个字典,将 femalemale 分别映射为 INT 类型的编码值:01
  2. 生成 bitmap:StarRocks 根据字典的编码值生成 bitmap。因为 female 出现在前三行,所以 female 的 bitmap 是 1110male 出现在第 4 行,所以 male 的 bitmap 是 0001

如果想要查找该公司的男性员工,可执行如下语句。

SELECT * FROM employee WHERE Gender = male;

语句执行后,StarRocks 会先查找字典,得到 male 的编码值是 1,然后再去查找 bitmap,得到 male对应的 bitmap 是 0001,也就是说只有第 4 行数据符合查询条件。那么 StarRocks 就会跳过前 3 行,只读取第 4 行数据。

多列查询

例如,要提高 GenderIncome_level 列的查询效率,即可为这两列分别创建 Bitmap 索引。

  • Gender

    CREATE INDEX index1 ON employee (Gender) USING BITMAP COMMENT 'index1';
  • Income_level

    CREATE INDEX index2 ON employee (Income_level) USING BITMAP COMMENT 'index2';

如上两个语句执行后,Bitmap 索引生成的过程如下:

figure

StarRocks 会为 GenderIncome_level 列分别构建一个字典,然后再根据字典生成 bitmap。

  • Gender 列:female 的 bitmap 为 1110male 的 bitmap 为 0001
  • Income_level 列:level_1 的 bitmap 为 1010level_2 的 bitmap 为 0100level_3 的 bitmap 为 0001

如果想要查找工资范围在 level_1 的女性员工,可执行如下语句。

 SELECT * FROM employee 
WHERE Gender = female AND Income_level = level_1;

语句执行后,StarRocks 会同时查找 GenderIncome_level 列的字典,得到以下信息:

  • female的编码值为0,对应的 bitmap 为1110
  • level_1的编码值为0,对应的 bitmap 为1010

因为查询语句中 Gender = femaleIncome_level = Level_1 这两个条件是 AND 关系,所以 StarRocks 会对两个 bitmap 进行位运算 1110 & 1010,得到最终结果 1010。根据最终结果,StarRocks 只读取第 1 行和第 3 行数据,不会读取所有数据。