CodeWalk

ClickHouse MergeTree的Merge(合并)策略与参数调优

作者:小字辈 · 2026-05-30 12:55

ClickHouse MergeTree引擎的后台合并(Merge)过程如何工作?请解释Merge的触发条件(分区内Part数量/Part大小/等待时间)、合并算法(水平合并/垂直合并)、以及合并相关的调优参数(max_bytes_to_merge/merge_with_ttl_timeout/merge_tree.max_parts_in_total)。给出一个生产环境中根据写入量调整合并参数的案例。

回答

小字辈

ClickHouse Merge机制详解:

1. Merge触发条件

每写入一批数据生成一个新的Data Part
后台Merge线程持续检查:
  1. 分区内Part数量 > MergeTree调优策略阈值
  2. 或Part大小超过 max_bytes_to_merge 限制
  3. 或Part中存在可TTL清理的数据

2. 合并算法: | 类型 | 原理 | 适用 | |------|------|------| | 水平合并 | 读取多个Part行数据,排序后写入新Part(重排序)| 默认方式 | | 垂直合并 | 按列分组合并,降低排序开销 | 大Part、列数多的表 |

3. 核心调优参数

merge_tree:
  # Part合并策略
  max_bytes_to_merge: 20000000000        # 20GB,超过此大小的Part不参与merge
  max_bytes_to_merge_at_max_space: 200000000000  # 200GB(大Part合并不限制)
  min_bytes_for_wide_part: 10485760      # 10MB,超过此值使用wide格式(多文件)
  
  # 限制Part数量
  max_parts_in_total: 10000              # 全表Part总数上限,超过则阻塞写入
  max_part_loading_threads: 8            # 加载Part的线程数
  
  # TTL合并
  merge_with_ttl_timeout: 14400          # 4小时,TTL过期后最多等待时间
  
  # 合并调度的负载控制
  max_delay_to_insert: 10                # 写入延迟控制
  replicated_deduplication_window: 100   # 去重窗口

4. 生产调优案例

# 场景:每秒50万行写入,分区按天,高峰期Part数量激增

# 问题:写入高峰期Part数过多导致写入变慢
# 优化方案:

merge_tree:
  # 1. 增大Part合并不需等待的大小限制(加快合并节奏)
  max_bytes_to_merge_at_max_space_in_pool: 30000000000  # 30GB
  
  # 2. 增大最大Part数量限制(高峰期不阻塞写入)
  max_parts_in_total: 50000
  
  # 3. 增大后台合并线程
  background_pool_size: 64

  # 4. 减少Part生成速率(增大写入块大小)
  # max_insert_block_size: 1500000  # 写入端增大

5. 查看Merge状态

-- 当前正在合并的Part
SELECT * FROM system.merges ORDER BY elapsed DESC;
-- Part列表
SELECT database, table, count() AS parts, sum(bytes_on_disk) AS total_bytes
FROM system.parts
WHERE active = 1
GROUP BY database, table;