StarRocks有前缀索引、Ordinal 索引、ZoneMap 索引这些内置的索引, 同时也支持用户手动创建索引,包括 Bitmap 索引和、Bloom filter 索引、N-gram bloom filter索引、全文倒排索引和向量索引。本文介绍这些手动创建索引的设计策略。
一、Bitmap索引
1. 简介
Bitmap 索引是一种使用 bitmap 的特殊数据库索引。bitmap 即为一个 bit 数组,一个 bit 的取值有两种:0 或 1。每一个 bit 对应数据表中的一行,并根据该行的取值情况来决定 bit 的取值是 0 还是 1。
如果查询的过滤条件命中前缀索引,可以显著提高查询效率,快速返回结果。但是一个表只能有一个前缀索引,如果查询的过滤条件没有包含前缀索引的前缀,则为了提高这类查询的效率可以为该列创建 Bitmap 索引。
2. Bitmap索引创建
2.1 语句
CREATE TABLE `lineorder_partial` (
`lo_orderkey` int(11) NOT NULL COMMENT "",
`lo_orderdate` int(11) NOT NULL COMMENT "",
`lo_orderpriority` varchar(16) NOT NULL COMMENT "",
`lo_quantity` int(11) NOT NULL COMMENT "",
`lo_revenue` int(11) NOT NULL COMMENT "",
INDEX lo_orderdate_index (lo_orderdate) USING BITMAP
) ENGINE=OLAP
DUPLICATE KEY(`lo_orderkey`)
DISTRIBUTED BY HASH(`lo_orderkey`);
2.2 优势
能够快速定位查询的列值所在的数据行号,适用于点查或是小范围查询。 适用于交并集运算(OR 和 AND 运算),可以优化多维查询。
2.3 注意事项
(1)主键表和明细表中所有列都可以创建 Bitmap 索引;聚合表和更新表中,只有 Key 列支持创建 Bitmap 索引。 支持为如下类型的列创建 Bitmap 索引:
日期类型:DATE、DATETIME。
数值类型:TINYINT、SMALLINT、INT、BIGINT、LARGEINT、DECIMAL 和 BOOLEAN。
字符串类型:CHAR、STRING 和 VARCHAR。
其他类型:HLL。
(2)支持优化的查询
Bitmap 索引适用于优化等值 = 查询、[NOT] IN 范围查询、>,>=,<,<= 查询、 IS NULL 查询。不适用于优化 !=,[NOT] LIKE 查询。
3.合理设计Bitmap 索引
选择 Bitmap 索引的首要考虑因素是列的基数和 Bitmap 索引对查询的过滤效果。与普遍观念相反,Bitmap 索引比较适用于较高基数列的查询和多个低基数列的组合查询,此时 Bitmap 索引对查询的过滤效果比较好,至少可以过滤掉 999/1000 的数据,能够过滤较多的 Page 数据。
如果是单个低基数列的查询,那么 Bitmap 索引过滤效果不佳,待读取的数据行较多并且散落在较多 Page 中。
然而如果基数过于高,也会带来其他问题,比如占用较多的磁盘空间,并且因为需要导入时需要构建 Bitmap 索引,导入频繁时则导入性能会受影响。
并且还需要考虑查询时加载 Bitmap 索引的开销。因为查询时候只会按需加载 Bitmap 索引,即 查询条件涉及的列值数量/基数 x Bitmap 索引。这一值越大,则查询时加载的 Bitmap 索引开销也越大。
由于 StarRocks 本身对于查询有 Bitmap 索引的自适应选择机制,如果 Bitmap 索引不合适,则查询时不会使用 Bitmap 索引,所以查询性能也不会受到明显影响。
StarRocks 判断是否使用 Bitmap 索引的逻辑:因为一般情况下查询条件涉及的列值数量/列的基数,这一值越小,说明 Bitmap 索引过滤效果好。所以 StarRocks 采用 bitmap_max_filter_ratio/1000作为判断阈值,当过滤条件涉及比较值的数量 /列的基数 < bitmap_max_filter_ratio/1000 时才会用 Bitmap 索引。bitmap_max_filter_ratio 默认为 1。
二、Bloom filter 索引
1. 简介
Bloom filter 索引可以快速判断表的数据文件中是否可能包含要查询的数据,如果不包含就跳过,从而减少扫描的数据量。Bloom filter 索引空间效率高,适用于基数较高的列,如 ID 列。如果一个查询条件命中前缀索引列,StarRocks 会使用前缀索引快速返回查询结果。但是前缀索引的长度有限,如果想要快速查询一个非前缀索引列且该列基数较高,即可为这个列创建 Bloom filter 索引。
2. 索引创建
2.1 语句
CREATE TABLE table1 (
k1 BIGINT,
k2 LARGEINT,
v1 VARCHAR(2048) REPLACE,
v2 SMALLINT DEFAULT "10"
) ENGINE = olap
PRIMARY KEY(k1, k2)
DISTRIBUTED BY HASH (k1, k2)
PROPERTIES("bloom_filter_columns" = "k1,k2");
建表时,通过在 PROPERTIES 中指定 bloom_filter_columns 来创建索引。例如,如下语句为表 table1 的 k1 和 k2 列创建 Bloom filter 索引。
2.2 使用说明
-
键表和明细表中所有列都可以创建 Bloom filter 索引;聚合表和更新表中,只有维度列(即 Key 列)支持创建 Bloom filter 索引。
-
支持为如下类型的列创建 Bloom filter 索引。
数值类型:SMALLINT、INT、BIGINT 和 LARGEINT。
字符串类型:CHAR、STRING 和 VARCHAR。
日期类型:DATE、DATETIME。
-
Bloom filter 索引只能提高包含 in 和 = 过滤条件的查询效率,例如 Select xxx from table where xxx in () 和 Select xxx from table where column = xxx。
如要了解一个查询是否命中了 Bloom filter 索引,可查看该查询的 Profile 中的 BloomFilterFilterRows 字段。
三、N-gram bloom filter 索引
3.1 简介
N-gram bloom filter 索引是一种特殊的 Bloom filter 索引,通常用于加速 LIKE 查询以及 ngram_search 和 ngram_search_case_insensitive 函数的计算速度。
N-gram bloom filter 索引仅适用于字符串类型(STRING、CHAR 或 VARCHAR)的列。N-gram bloom filter 索引与 Bloom filter 索引的区别在于,N-gram bloom filter 索引首先对字符串进行分词,然后将生成的子字符串写入 Bloom filter 索引。例如,某个被索引的列值是字符串 Technical。对于传统的 Bloom filter 索引,整个字符串 Technical 将直接写入索引。然而,对于指定 gram_num 为 4 的 N-gram bloom filter 索引,字符串 Technical 将首先被分词为以下子字符串:"Tech", "echn", "chni", "hnic", "nica", "ical",然后将这六个子字符串分别写入 Bloom filter 索引。
3.2 语句
CREATE TABLE test.table1 (
k1 CHAR(10),
k2 CHAR(10),
v1 INT SUM,
INDEX index_name (k2) USING NGRAMBF ("gram_num" = "4","bloom_filter_fpp" = "0.05") COMMENT ''
) ENGINE = olap
AGGREGATE KEY(k1, k2)
DISTRIBUTED BY HASH(k1);
参数说明:
| 参数 | 必需 | 描述 |
| index_name | 是 | 索引的名称。索引名称在表内必须唯一。 |
| column_name | 是 | 创建索引的列名。只能指定一个列名。在上面的例子中,它是k2。 |
| gram_num | 否 | 被索引列中的字符串分词后的子字符串长度。默认值为 2。 |
| bloom_filter_fpp | 否 | Bloom filter 的误报率,范围从 0.0001 到 0.05。默认值为 0.05。较小的值提供更好的过滤效果,但会增加存储开销。 |
| case_sensitive | 否 | 此索引是否区分大小写。默认值为true。 |
| COMMENT | 否 | 索引注释。 |
3.3 使用说明
- 对于明细或主键表,可以为所有列(字符串类型)创建 N-gram bloom filter 索引。对于聚合表或更新表,只能在键列(字符串类型)上创建 N-gram bloom filter 索引。
- N-gram bloom filter 索引只能为字符串类型的列(CHAR、STRING 和 VARCHAR)创建。
- 要确定查询是否命中 N-gram bloom filter 索引,可以检查查询的 BloomFilterFilterRows 字段。
- 对于单个列,只能创建一种类型的索引(Bloom Filter 或 N-gram Bloom Filter)。
全文倒排索引和向量索引下一篇再介绍。