索引、排序列和前缀索引

最近更新时间:2022-09-08 16:47:57

我的收藏

索引

Doris 支持比较丰富的索引结构来减少数据的扫描和提高查询效率,目前支持的索引类型有:
Sorted Compound Key Index,可以最多指定三个列组成复合排序键,通过该索引,能够有效进行数据裁剪,从而能够更好支持高并发的报表场景 。
Z-order Index :可以高效对数据模型中的任意字段组合进行范围查询。
Min/Max :有效过滤数值类型的等值和范围查询。
Bloom Filter :对高基数列的等值过滤裁剪非常有效。
Invert Index :能够对任意字段实现快速检索。
不同于传统的数据库设计,Doris 不支持在任意列上创建索引。Doris 这类 MPP 架构的 OLAP 数据库,通常都是通过提高并发来处理大量数据的。

排序列(Sort Key)

为了提高查询性能,Doris 优化了数据存储的组织结构。本质上,Doris 的数据存储在类似 SSTable(Sorted String Table)的数据结构中。该结构是一种有序的数据结构,可以按照指定的列进行排序存储(可以是一列或者多列),这些列即称为排序列。在这种数据结构上,以排序列作为条件进行查找,会非常的高效。
在 Aggregate、Unique 和 Duplicate 三种数据模型中。底层的数据存储,是按照各自建表语句中,AGGREGATE KEY、UNIQUE KEY 和 DUPLICATE KEY 中指定的列进行排序存储的。Rollup 可以指定自己的排序列,但排序列必须是 Rollup 列顺序的前缀。
注意
在建表语句中的列定义中,排序列的定义必须出现在其他列的定义之前。
排序列的顺序是由 create table 语句中的列顺序决定的。

前缀索引

即在排序的数据结构(SSTable)基础上,实现的一种根据给定前缀列,快速查询数据的索引方式。对于能使用上排序结构的查询,Doris 采用二分查找算法定位到目标数据的区间。但如果表中数据行数很多,直接对排序列进行二分查找需要把所有 filter 列的数据都加载到内存中,这会消耗大量内存空间。为优化这个细节,Doris 在 Sort Key 的基础上引入稀疏的 Shortkey Index(前缀索引),Sortkey Index 的内容会比数据量少1024倍(Doris 把每1024行数据组成一个逻辑数据块 (称作 Data Block),每个 Data Block 在前缀索引中存储一行索引),因此会全量缓存在内存中,实际查找的过程中可以有效加速查询。
当 Sort Key 列数非常多时,会占用大量内存,为了性能考虑,对前缀索引项做了限制:
最多可选取 3 列作为 Shortkey 列。
不能使用 FLOAT / DOUBLE 类型的列。
只能按排序键的顺序来构造前缀索引。
VARCHAR / CHAR 类型列只能出现一次,并且只能是最后位置。
所有列字节数不超过36字节,VARCHAR / CHAR 列按剩余字节数折断。
当用户在建表语句中指定 short_key 属性时,例如"short_key" = "4"指定4个列作为 short_key, 可突破上述限制。

示例

1. 以下表结构的前缀索引为 user_id(8 Bytes) + age(4 Bytes) + message(prefix 20 Bytes)。
ColumnName
Type
user_id
BIGINT
age
INT
message
VARCHAR(100)
max_dwell_time
DATETIME
min_dwell_time
DATETIME
2. 以下表结构的前缀索引为 user_name(20 Bytes)。即使没有达到 36 个字节,因为遇到 VARCHAR,所以直接截断,不再往后继续。
ColumnName
Type
user_name
VARCHAR(20)
age
INT
message
VARCHAR(100)
max_dwell_time
DATETIME
min_dwell_time
DATETIME
当我们的查询条件是前缀索引的前缀时,可以极大的加快查询速度。例如在第一个例子中,我们执行如下查询:
SELECT * FROM table WHERE user_id=1829239 and age=20
该查询的效率会远高于如下查询:
SELECT * FROM table WHERE age=20
所以在建表时,正确的选择列顺序,能够极大地提高查询效率

最佳实践

通过 ROLLUP 来调整前缀索引

因为建表时已经指定了列顺序,所以一个表只有一种前缀索引。这对于使用其他不能命中前缀索引的列作为条件进行的查询来说,效率上可能无法满足需求。因此,我们可以通过创建 ROLLUP 来人为的调整列顺序。

优化排序列的先后顺序来提高查询性能

当 Sort Key 涉及多个列的时候,需要注意先后顺序,区分度高、经常查询的列建议放在前面。
注意排序列的数量:
1. 如果选择了大量的列用于排序列,那么数据导入时排序的开销会增大整个导入过程的耗时。
2. 设计良好的少量排序列也能快速定位到数据行所在的位置,增加更多列进行排序也不会带来查询的提升。