tencent cloud

文档反馈

Bitmap 索引

最后更新时间:2024-06-27 11:10:40
    用户可以通过创建 bitmap index 加速查询。 本文档主要介绍如何创建 bitmap 索引,以及创建 bitmap 索引的一些注意事项和常见问题。

    名词解释

    bitmap 索引:用位图表示的索引,对索引列的每个键值建立一个位图。是一种快速数据结构,能够加快查询速度。 索引原理示意:
    

    原理介绍

    主要针对大量相同值的列而创建(例如:类别,操作员,部门 ID,库房 ID 等),索引块的一个索引行中存储键值和起止 Rowid,以及这些键值的位置编码,位置编码中的每一位表示键值对应的数据行的有无。一个块可能指向的是几十甚至成百上千行数据的位置。
    当根据键值查询时,可以根据起始 Rowid 和位图状态,快速定位数据。
    当根据键值做 and,or 或 in(x,y,..)查询时,直接用索引的位图进行位运算,快速得出结果行数据。
    当执行 select count(xx) 时,可以直接访问索引就快速得出统计数据。

    语法

    创建和删除本质上是一个 schema change 的作业,具体细节可以参照 Schema Change

    创建索引

    支持在创建表时就进行 Bitmap 索引指定。
    CREATE TABLE create_table_with_bitmap ( l_shipdate date NOT NULL, l_comment varchar(44) NOT NULL, INDEX shipdate_bm_index (l_shipdate) USING BITMAP COMMENT 'shipdate bitmap index' ) ENGINE=OLAP DUPLICATE KEY(l_shipdate) COMMENT 'OLAP' DISTRIBUTED BY HASH(l_shipdate) BUCKETS 96 PROPERTIES ( "replication_allocation" = "tag.location.default: 3", "in_memory" = "false", "storage_format" = "V2", "disable_auto_compaction" = "false" );
    也支持对现有的表进行修改增加某一列的 Bitmap 索引,例如在 table1 上为 siteid 创建 Bitmap 索引:
    CREATE INDEX [IF NOT EXISTS] index_name ON table1 (siteid) USING BITMAP COMMENT 'balabala';

    查看索引

    展示指定 table_name 的下索引:
    SHOW INDEX FROM example_db.table_name;

    删除索引

    删除指定 table_name 的下索引:
    DROP INDEX [IF EXISTS] index_name ON [db_name.]table_name;
    
    
    

    基本原理

    腾讯云数据仓库 TChouse-D 使用的是列存储, 在没有索引的情况下,要判断某列F是否与某个值 V 相等,只能遍历一整列所有的数据,才能得到与 V 相等的行号。Bitmap 索引为了避免检索时对所有数据进行遍历,在原来列存数据的基础上,顺序保存列所有的值(有序字典),以及每个值对应的行号。这样在检索时,就可以通过值,快速查找到等于这个值的所有行号。
    例如一列数据为[x, x, y, y, y, z, y, x, z, x],一共包含10行,则该列数据的 Bitmap 索引的有序字典为{x, y, z}, x、y、z对应的位图分别为:
    x的位图: [0, 1, 7, 9]
    y的位图: [2, 3, 4, 6]
    z的位图: [5, 8]
    

    注意事项

    目前索引命令([show | create | drop] index)仅支持 bitmap 类型的索引。
    bitmap 索引仅在单列上创建。
    bitmap 索引能够应用在 DuplicateUniq 数据模型的所有列和 Aggregate模型的 key 列上。
    bitmap 索引支持的数据类型如下:
    TINYINT
    SMALLINT
    INT
    BIGINT
    CHAR
    VARCHAR
    DATE
    DATETIME
    LARGEINT
    DECIMAL
    BOOL
    bitmap 索引仅在 Segment V2 下生效。当创建 index 时,表的存储格式将默认转换为 V2 格式(查看表的存储格式可通过 show create table table_name 命令)。

    bitmap 索引适用场景

    适用于低基数的列上,建议在100到100,000之间,如:职业、地市等。重复度过高则对比其他类型索引没有明显优势;重复度过低,则空间效率和性能会大大降低。
    特定类型的查询例如 count、or、and 等逻辑操作因为只需要进行位运算。如:通过多个条件组合查询,select count(*) from table where job = '医生' and phonetype = 'iphone' and gender ='男';类似这种场景,如果在每个查询条件列上都建立了 bitmap 索引,则数据库可以进行高效的位运算,精确定位到需要的数据,减少磁盘 IO。并且筛选出的结果集越小,bitmap 索引的优势越明显。
    适用于即席查询、多维分析等 OLAP 场景。如果有一张表有100列,用户会使用其中的20个列作为查询条件(任意使用这20个列上的N的列),几乎没有办法创建合适的 b-tree 索引。但是在这些列上创建20个 bitmap 索引,那么所有的查询都可以应用到索引。
    Bitmap索引支持等值查询和范围查找,支持= , < , <= ,> ,>= 表达式。

    bitmap 索引不适用场景

    值重复度低的列,如:身份证号、手机号码等。
    重复度过高的列,如:性别,可以建立 bitmap 索引,但不建议单独作为查询条件使用,建议与其他条件共同过滤。
    经常需要更新修改的列。

    最佳实践

    以下基于 TPCH 测试集的 lineitem 表(6亿条记录), 构建 Bitmap 索引和使用。
    enter image description here
    
    假设对于 lineitem 表,预期优化以下 sql,优化前耗时约为900ms。
    select l_quantity,l_returnflag,l_commitdate from lineitem where l_suppkey = 'xxx';

    分析是否适用 Bitmap 索引

    查询条件 l_suppkey,此时并不命中前缀索引也没有其他索引。l_suppkey 字段类型为INT ,为可以使用 Bitmap 索引的类型。
    查看 l_suppkey 这一列的取值基数,在6亿数据表上,l_suppkey 的取值为100W,取值基数并没有特别高,这里尝试使用 Bitmap 索引进行优化。
    enter image description here
    

    创建 Bitmap 和等待索引构建

    创建 Bitmap 索引:
    create index suppkey_bitmap_index on lineitem(l_suppkey) using bitmap comment 'test';
    通过 show alter table column 命令查看索引构建进度:
    
    enter image description here
    
    
    通过 show create table lineitem 命令查看 lineitem 表存在的索引:
    enter image description here
    

    对比优化前后效果

    优化后,耗时40ms。
    enter image description here
    
    优化前,耗时240ms(这里使用的 lineitem2 表是 lineitem 表的备份,数据量和表结构一致)。
    enter image description here
    

    常见问题

    select count(*) 对 Bitmap 索引列生效吗?

    生效,通过查看对 select count(*) from lineitem where l_suppkey = '388041'; 语句的profile,可以看到 RowsBitmapIndexFiltered 字段帮助过滤了大量数据。
    RowsBitmapIndexFiltered: 200.01525M (200015250)

    列的取值基数比较大,为什么不适合使用 bitmap 索引?

    实测对6亿记录的 lineitem 的 l_partkey 列(2000W取值)进行 bitmap 索引构建。优化前点查耗时600ms,优化后点查耗时为120ms。效率提升了5倍。可见对基数高的列建立索引,查询也能带来效率提升。
    但是存储消耗比较大。lineitem 表6亿数据3副本占用约62G存储,对 l_partkey 列构建完 bitmap 索引后,lineitem 表存储涨到95G。理论上,bitmap 索引构建增长的存储,在未压缩情况,为 2000W(取值)* 60000W(行数)bit。
    可见对高基数列构建 bitmap 索引,性价比并不高,这个时候更推荐 bloomfilter 索引。
    
    联系我们

    联系我们,为您的业务提供专属服务。

    技术支持

    如果你想寻求进一步的帮助,通过工单与我们进行联络。我们提供7x24的工单服务。

    7x24 电话支持