完整教程:Doris专题7- 索引

1. 索引概述与分类

1.1 索引分类体系

Apache Doris索引体系
点查索引
跳数索引
前缀索引
倒排索引
ZoneMap索引
BloomFilter索引
NGram BloomFilter索引
内置自动维护
用户手动创建
内置自动维护
用户手动创建
用户手动创建

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 使用建议

前缀索引设计
查询条件分析
识别最频繁的WHERE条件
将高频条件列作为排序键
高频列放在排序键前面
确保前缀索引命中率
成功-查询性能最佳
失败-考虑其他索引方案
创建倒排索引
创建物化视图调整列顺序

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
查询值
Hash函数计算
位数组偏移量
所有位都为1?
可能存在
一定不存在
读取数据块验证
跳过数据块

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同样分词后匹配
原始文本
NGram分词
词项1
词项2
词项N
LIKE Pattern
NGram分词
模式词项1
模式词项2
模式词项M
BloomFilter判断
词项存在性检查
所有模式词项都存在?
可能需要读取
跳过数据块

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 索引选择决策树

索引选择决策
查询类型
等值/范围查询
LIKE模糊查询
全文关键词检索
多条件组合查询
是否为排序键前缀?
使用前缀索引
是否为高基数列?
BloomFilter索引
倒排索引
NGram BloomFilter索引
倒排索引 + 分词器
倒排索引多条件组合
性能最佳
空间效率高
功能全面
LIKE专用
全文检索最优
灵活组合

6.2 运算符支持矩阵

运算符 / 函数前缀索引倒排索引ZoneMap索引BloomFilter索引NGram BloomFilter索引
=, IN
!=, NOT IN
>, >=, <, <=
IS NULL
IS NOT NULL
LIKE
MATCH_*
array_contains

6.3 最佳实践建议

  1. 优先使用前缀索引

    • 将最频繁的过滤条件作为排序键
    • 高频列放在排序键前面
  2. 倒排索引作为通用解决方案

    • 非Key字段过滤加速首选
    • 支持最全面的查询类型
    • 可多条件逻辑组合
  3. 专用索引补充

    • LIKE查询:NGram BloomFilter索引
    • 高基数列等值查询:BloomFilter索引
    • 存储空间敏感场景:BloomFilter替代倒排索引
  4. 性能监控与调优

    -- 查询Profile分析
    SET enable_profile = true;
    -- 关键指标监控
    -- RowsBloomFilterFiltered: BloomFilter过滤行数
    -- RowsInvertedIndexFiltered: 倒排索引过滤行数  
    -- RowsKeyRangeFiltered: 前缀索引过滤行数
    -- BlockConditionsFilteredBloomFilterTime: BloomFilter处理时间
    -- InvertedIndexFilterTime: 倒排索引处理时间

posted on 2025-11-05 09:50  slgkaifa  阅读(7)  评论(0)    收藏  举报

导航