Doris专题7- 索引
1. 索引概述与分类
1.1 索引分类体系
1.2 索引特性对比
索引类型 | 索引原理 | 适用场景 | 存储开销 | 管理方式 |
---|---|---|---|---|
前缀索引 | 排序键前36字节稀疏索引 | 等值、范围查询 | 极小 | 自动内置 |
倒排索引 | 值到行号的倒排表 | 全文检索、等值、范围查询 | 较大 | 手动创建 |
ZoneMap索引 | 列统计信息(最大/最小值) | 等值、范围、NULL查询 | 极小 | 自动内置 |
BloomFilter索引 | 布隆过滤器数据结构 | 等值查询(高基数列) | 中等 | 手动创建 |
NGram BloomFilter索引 | NGram分词+布隆过滤器 | LIKE模糊查询 | 中等 | 手动创建 |
2. 前缀索引 (Prefix Index)
2.1 核心原理
- 排序键(Sort Key):按照AGGREGATE/UNIQUE/DUPLICATE KEY指定的列排序存储
- 稀疏索引:每1024行数据创建一个索引项
- 索引内容:每个数据块第一行数据的排序列前缀(最多36字节)
-- 示例:前缀索引构成
-- 排序键:user_id(BIGINT-8B) + age(INT-4B) + message(VARCHAR-20B前缀)
-- 前缀索引 = user_id(8B) + age(4B) + message(20B前缀) = 32字节
2.2 使用建议
3. 倒排索引 (Inverted Index)
3.1 核心特性
- 文档模型:一行=一个文档,一列=文档字段
- 独立存储:索引文件与数据文件分离,管理开销低
- 功能全面:支持全文检索、等值、范围、逻辑组合查询
3.2 索引管理
-- 1. 建表时创建倒排索引
CREATE TABLE hackernews_1m (id BIGINT,comment STRING,author STRING,timestamp DATETIME,INDEX idx_comment(comment) USING INVERTED PROPERTIES("parser" = "english"),INDEX idx_author(author) USING INVERTED,INDEX idx_timestamp(timestamp) USING INVERTED
);-- 2. 已有表添加索引
ALTER TABLE hackernews_1m ADD INDEX idx_comment(comment) USING INVERTED PROPERTIES("parser" = "english");-- 3. 构建存量数据索引
BUILD INDEX idx_comment ON hackernews_1m;-- 4. 查看构建进度
SHOW BUILD INDEX;-- 5. 删除索引
DROP INDEX idx_comment ON hackernews_1m;
3.3 查询加速示例
-- 全文检索:性能提升9-13倍
-- LIKE查询: 0.18s → MATCH_ANY: 0.02s (9倍加速)
SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%'; -- 0.18s
SELECT count() FROM hackernews_1m WHERE comment MATCH_ANY 'OLAP'; -- 0.02s-- 多关键词AND: 0.13s → 0.01s (13倍加速)
SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%' AND comment LIKE '%OLTP%'; -- 0.13s
SELECT count() FROM hackernews_1m WHERE comment MATCH_ALL 'OLAP OLTP'; -- 0.01s-- 多关键词OR: 0.12s → 0.01s (12倍加速)
SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%' OR comment LIKE '%OLTP%'; -- 0.12s
SELECT count() FROM hackernews_1m WHERE comment MATCH_ANY 'OLAP OLTP'; -- 0.01s-- 短语匹配
SELECT * FROM table_name WHERE content MATCH_PHRASE 'keyword1 keyword2';
SELECT * FROM table_name WHERE content MATCH_PHRASE 'keyword1 keyword2 ~3'; -- 允许间隔3个词
SELECT * FROM table_name WHERE content MATCH_PHRASE 'keyword1 keyword2 ~3+'; -- 保持词序-- 前缀和正则匹配
SELECT * FROM table_name WHERE content MATCH_PHRASE_PREFIX 'keyword1 keyword2';
SELECT * FROM table_name WHERE content MATCH_REGEXP 'key.*';-- 多列检索
SELECT * FROM table_name WHERE multi_match(col1, col2, col3, 'any', 'keyword1');
SELECT * FROM table_name WHERE multi_match(col1, col2, col3, 'all', 'keyword1');
3.4 分词功能验证
-- 中文细粒度分词
SELECT TOKENIZE('武汉长江大桥', "parser"="chinese", "parser_mode"="fine_grained");
-- 结果: ["武汉", "武汉长江大桥", "长江", "长江大桥", "大桥"]-- 中文粗粒度分词
SELECT TOKENIZE('武汉市长江大桥', "parser"="chinese", "parser_mode"="coarse_grained");
-- 结果: ["武汉市", "长江大桥"]-- 英文分词
SELECT TOKENIZE('I love Doris', "parser"="english");
-- 结果: ["i", "love", "doris"]-- Unicode多语言分词
SELECT TOKENIZE('I love CHINA 我爱我的祖国', "parser"="unicode");
-- 结果: ["i", "love", "china", "我", "爱", "我", "的", "祖", "国"]
4. BloomFilter索引
4.1 核心原理
- 概率型数据结构:空间效率高,判断"可能存在"或"一定不存在"
- 假阳性特性:可能存在误判,但不会漏判
- 数据块级别:每个数据块(page)构建独立的BloomFilter
4.2 索引管理
-- 1. 建表时创建BloomFilter索引
CREATE TABLE sale_detail_bloom (sale_date DATE NOT NULL,customer_id INT NOT NULL,saler_id INT NOT NULL,sku_id INT NOT NULL,category_id INT NOT NULL
)
DISTRIBUTED BY HASH(saler_id) BUCKETS 10
PROPERTIES ("bloom_filter_columns" = "saler_id,category_id"
);-- 2. 已有表添加索引
ALTER TABLE table_name SET ("bloom_filter_columns" = "column1,column2,column3");-- 3. 删除索引
ALTER TABLE table_name SET ("bloom_filter_columns" = "column2,column3");
4.3 适用场景与限制
适用场景:
- 高基数字段的等值查询(如user_id等唯一ID)
- IN条件查询加速
限制条件:
- 不支持:!=, NOT IN, >, < 等非等值查询
- 不支持:Tinyint、Float、Double类型列
- 低基数字段效果有限(如性别字段)
5. NGram BloomFilter索引
5.1 核心原理
- NGram分词:将文本拆分成N个连续字符的词组
- BloomFilter存储:将分词结果存入BloomFilter
- LIKE模式匹配:对LIKE pattern同样分词后匹配
5.2 索引管理
-- 1. 创建NGram BloomFilter索引
CREATE TABLE amazon_reviews (review_body STRING,INDEX idx_ngram_body(review_body) USING NGRAM_BF PROPERTIES("gram_size" = "3", "bf_size" = "1024")
);-- 2. 已有表添加索引
ALTER TABLE amazon_reviews ADD INDEX idx_ngram_body(review_body)
USING NGRAM_BF PROPERTIES("gram_size" = "10", "bf_size" = "10240");-- 3. 查看索引
SHOW CREATE TABLE amazon_reviews;
SHOW INDEX FROM amazon_reviews;-- 4. 删除索引
ALTER TABLE amazon_reviews DROP INDEX idx_ngram_body;
5.3 性能提升示例
-- 无索引: 7.60s → 有索引: 0.93s (8倍性能提升)
SELECT product_id, any(product_title), AVG(stan_rating) AS rating, COUNT() AS count
FROM amazon_reviews
WHERE review_body LIKE '%is super awesome%'
GROUP BY product_id
ORDER BY count DESC, rating DESC, product_id
LIMIT 5;
6. 索引选择与设计指南
6.1 索引选择决策树
6.2 运算符支持矩阵
运算符 / 函数 | 前缀索引 | 倒排索引 | ZoneMap索引 | BloomFilter索引 | NGram BloomFilter索引 |
---|---|---|---|---|---|
=, IN | ✅ | ✅ | ✅ | ✅ | ❌ |
!=, NOT IN | ✅ | ✅ | ❌ | ❌ | ❌ |
>, >=, <, <= | ✅ | ✅ | ✅ | ❌ | ❌ |
IS NULL | ✅ | ✅ | ✅ | ❌ | ❌ |
IS NOT NULL | ✅ | ✅ | ❌ | ❌ | ❌ |
LIKE | ❌ | ❌ | ❌ | ❌ | ✅ |
MATCH_* | ❌ | ✅ | ❌ | ❌ | ❌ |
array_contains | ❌ | ✅ | ❌ | ❌ | ❌ |
6.3 最佳实践建议
-
优先使用前缀索引
- 将最频繁的过滤条件作为排序键
- 高频列放在排序键前面
-
倒排索引作为通用解决方案
- 非Key字段过滤加速首选
- 支持最全面的查询类型
- 可多条件逻辑组合
-
专用索引补充
- LIKE查询:NGram BloomFilter索引
- 高基数列等值查询:BloomFilter索引
- 存储空间敏感场景:BloomFilter替代倒排索引
-
性能监控与调优
-- 查询Profile分析 SET enable_profile = true;-- 关键指标监控 -- RowsBloomFilterFiltered: BloomFilter过滤行数 -- RowsInvertedIndexFiltered: 倒排索引过滤行数 -- RowsKeyRangeFiltered: 前缀索引过滤行数 -- BlockConditionsFilteredBloomFilterTime: BloomFilter处理时间 -- InvertedIndexFilterTime: 倒排索引处理时间