索引

索引是 Lakehouse 减少数据扫描量、提升查询性能的机制,在数据文件内记录额外元数据,让查询引擎在文件级别快速过滤,不改变数据的物理存储方式。

选型指南

索引类型对比

索引类型适用查询适用列类型典型场景
Bloomfilter 索引等值过滤(
=
=
IN
IN
高基数列(用户 ID、订单号、设备 ID)按 ID 点查,跳过不包含目标值的数据文件
倒排索引全文检索(
MATCH
MATCH
)、关键词匹配
文本列(STRING、VARCHAR)日志搜索、商品名称检索、JSON 字段过滤
向量索引近似最近邻检索(ANN)VECTOR 类型列语义搜索、图像相似度、RAG 召回

选型规则

  • ID 类字段、状态码,等值查询多 → Bloomfilter 索引
  • 文本内容,需要关键词或短语搜索 → 倒排索引
  • 向量嵌入,需要语义相似度检索 → 向量索引
  • 上述三类可以在同一张表上同时创建,互不冲突

核心机制

隐藏分区

Lakehouse 的分区类似 Apache Iceberg 的隐藏分区机制:

  • 分区信息存储在元数据中,不需要在 SQL 查询时手动指定分区条件
  • 支持转换分区函数(
    years
    years
    /
    months
    months
    /
    days
    days
    /
    hours
    hours
    /
    bucket
    bucket
    /
    truncate
    truncate
    ),按时间维度自动分区
  • 分区策略可以在不影响已有数据的情况下修改(Hive 的静态分区不支持这点)

Bloomfilter 工作原理

Bloomfilter 是一种概率数据结构,在数据文件级别记录列值的存在性:

  • 某个值不存在:100% 准确,直接跳过该文件
  • 某个值可能存在:需要实际读取验证(极低概率误判)

因此 Bloomfilter 只对等值查询有效,范围查询无法利用。

快速示例

-- 建表时同时创建分区 + 多种索引 CREATE TABLE events ( event_id BIGINT, user_id BIGINT, message STRING, event_time TIMESTAMP, INDEX idx_user (user_id) USING BLOOMFILTER, INDEX idx_msg (message) USING INVERTED ) PARTITIONED BY (days(event_time)); -- 插入数据(分区自动生成,无需手动指定) INSERT INTO events VALUES (1, 1001, 'user login failed', TIMESTAMP '2024-06-01 10:00:00'), (2, 1002, 'connection timeout', TIMESTAMP '2024-06-01 11:00:00'), (3, 1001, 'user login success', TIMESTAMP '2024-06-02 09:00:00'); -- 走分区裁剪:只扫描 2024-06-01 的数据文件 SELECT * FROM events WHERE event_time >= '2024-06-01' AND event_time < '2024-06-02'; -- 走 Bloomfilter 索引:跳过不含 user_id=1001 的文件 SELECT * FROM events WHERE user_id = 1001; -- 走倒排索引:全文检索 message 列 SELECT * FROM events WHERE match_any(message, 'login');

常见问题

常见问题 1:对低基数列建 Bloomfilter 索引

问题:在性别、状态、枚举类列上创建 Bloomfilter 索引。

症状:查询性能几乎没有提升,但索引数据占用了额外存储。

解决:Bloomfilter 索引只对高基数列有效(如用户 ID、订单号)。低基数列考虑分区(如按状态分区)或直接全表扫描。

对已有大表建索引需要先 BUILD

问题:对已有数据的表用

ALTER TABLE ... ADD INDEX
ALTER TABLE ... ADD INDEX
添加索引后,旧数据无索引覆盖。

解决:添加索引后需执行

BUILD INDEX
BUILD INDEX
对历史数据构建索引:

ALTER TABLE events ADD INDEX idx_new (user_id) USING BLOOMFILTER; -- 必须显式构建,否则旧数据不走索引 BUILD INDEX idx_new ON TABLE events;

常见问题 3:分区粒度过细导致小文件过多

问题:数据量不大,但按小时分区(

hours(event_time)
hours(event_time)
)。

症状:查询元数据开销大,

SHOW PARTITIONS
SHOW PARTITIONS
返回大量分区,反而拖慢查询。

解决:分区粒度与数据量匹配——日数据量 GB 级用

days
days
,TB 级可以考虑
hours
hours
。单个分区内数据量建议 128MB 以上。

成本影响

存储成本

  • 索引数据存储在独立文件中,额外占用存储空间
  • Bloomfilter 索引体积小(概率结构,通常 < 原数据 1%)
  • 倒排索引体积较大(分词后建立词典,通常是原列数据的 20%-100%)
  • 向量索引体积最大(HNSW 图结构,通常与原向量数据体积相当)

计算成本

  • BUILD INDEX
    BUILD INDEX
    消耗 VCluster CRU(一次性)
  • 索引构建完成后,查询时减少扫描量,降低 CRU 消耗
  • 分区不产生额外计算成本,通过元数据裁剪减少 I/O

本章内容

页面说明
索引概述三种索引类型对比与选型建议
Bloomfilter Index等值过滤加速,高基数列快速跳过文件
倒排索引全文检索加速,MATCH 查询
索引最佳实践多索引组合、AI 场景、运维建议

相关文档

文档说明
表设计分区和索引是建表时的核心设计决策
BUILD INDEX对历史数据构建索引
DROP INDEX删除索引
SHOW INDEX查看表上的索引
联系我们
预约咨询
微信咨询
电话咨询