CodeWalk

ClickHouse MergeTree表引擎原理

作者:编译有声 · 2026-05-30 12:55

请详细介绍ClickHouse MergeTree表引擎的存储架构,包括数据分区/排序键/主键索引/跳数索引的工作机制。

回答

编译有声

MergeTree是ClickHouse最核心的引擎家族基础。

一、数据存储结构:

  1. 分区(Partition)

    • PARTITION BY指定分区键(如toYYYYMM(date)
    • 每个分区独立存储为目录partitionId_partNumber_minBlockNum_maxBlockNum_level
    • 分区可以提高查询裁剪效率
  2. 数据片段(Data Part)

    • 每个分区内数据按主键排序存储为多个Data Part
    • 后台自动合并(Merge)较小Part为大Part

二、索引机制:

1. 主键索引(稀疏索引):

ORDER BY (CounterID, Date)  -- 排序键=主键
  • 不是传统B-Tree,而是每N行(granularity)记录一行索引
  • index_granularity(默认8192行)控制索引粒度
  • 索引文件:primary.idx(主键值)

2. 跳数索引(Skip Index):

INDEX idx_name (CounterID) TYPE minmax GRANULARITY 5
  • 类型:minmax/set/bloom_filter/ngrambf_v1/tokenbf_v1
  • GRANULARITY 5指每5个粒度(5×8192行)构建一个索引
  • 查询时跳过不包含目标数据的Granule

三、写入流程:

  1. 数据写入先写入内存缓冲区(默认3s刷新)
  2. 生成新的Data Part(不可变)
  3. 后台Merge线程合并小Part
  4. 分区合并时删除旧Part

四、查询流程:

  1. 分区裁剪(WHERE条件过滤分区)
  2. 主键索引定位Granule范围
  3. 跳数索引进一步过滤Granule
  4. 读取匹配的列数据(列式读取)
  5. 合并/聚合执行

优点:

  • 写入吞吐极高(LSM-Tree风格)
  • 查询延迟低(稀疏索引+数据本地排序)
  • 压缩率高(列存+排序后相同值连续)