首页/数据/数仓建模速查/ClickHouse 分区设计:按月或按日
湖仓与引擎63 条

ClickHouse 分区设计:按月或按日

分区粒度影响合并与查询裁剪:常见按月分区,数据量大且按日查询时按天分区;分区过细会产生大量 part 拖慢合并。

数仓建模速查数据更新于 2026-10-13

分区粒度影响什么

ClickHouse 的 MergeTree 按分区键把数据切成一个个 part,查询时靠分区裁剪跳过无关数据,后台再把同分区的小 part 合并成大 part。分区太粗,单分区数据量大,裁剪效果差;分区太细,part 数量暴涨,合并与元数据开销吃掉查询收益。按月还是按天,取决于数据量与查询条件。

基本信息

常用做法PARTITION BY toYYYYMM(dt) 按月
按天场景数据量大且查询按天过滤时
主要风险分区过细导致 part 数量失控
监控方式观察 system.parts 里的 part 数量与分区分布
生命周期TTL 可自动删除过期分区

典型使用场景

  • 明细日志表:按月分区,查询多带时间范围条件
  • 高频日查询表:按天分区,让裁剪更精确
  • 冷热分离:TTL 把过期分区按规则下沉或删除
  • 批量导入:按分区组织批次,避免单个 part 过大
  • 容量规划:按分区统计磁盘占用,判断是否需要归档

分区与 TTL 示例

分区与 TTL 示例
CREATE TABLE dw.trade_order
(
    dt        Date,
    order_id  String,
    pay_amt   Decimal(18, 2)
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(dt)      -- 按月分区
ORDER BY (dt, order_id)        -- 排序键决定稀疏索引
TTL dt + INTERVAL 12 MONTH;    -- 超过一年自动删除

-- 观察 part 数量与分区分布
SELECT partition, count() AS parts FROM system.parts
WHERE table = 'trade_order' AND active GROUP BY partition ORDER BY partition;

分区键怎么选

分区键适用条件后果
toYYYYMM(dt)多数明细表分区数适中,裁剪有效
toDate(dt)日查询多、数据量大part 数量增加,需控制写入批次
高基数列(订单号)不应使用分区爆炸,写入与查询异常
单一枚举列基数低且查询常按它过滤需评估分区数量上限
不分区小表无裁剪收益,但结构简单

part 数量为什么关键

ClickHouse 每次查询都要为涉及的每个 part 建索引与读取线程,part 数量越多,固定开销越大。小批量写入是 part 膨胀的主要来源:每条记录单独插入一次,就会生成一个小 part,后台合并跟不上时,几周内就能累积出成千上万个。写入侧应攒批,并关注后台合并是否落后。

TTL 与分区是配套使用的:TTL 能按时间自动删除或移动过期数据,比手工写清理任务更省心,也避免了删除时长时间占用资源。
分区键选高基数列会导致分区数量随数据增长而爆炸,写入与查询都会出现异常;这类结构问题靠调参数救不回来,只能改表结构并重导数据。

易错点

  • 用高基数列做分区键,part 与分区数量失控,写入与查询双双变慢
  • 分区按月但查询全部带具体日期,裁剪颗粒度不足,扫描量偏大
  • 忽略后台合并进度,只看到磁盘占用上升却找不到原因
  • 不配 TTL,历史数据无限累积,最终磁盘告警被迫紧急清理

数据来源与参考

  • ClickHouse 官方文档:Custom Partitioning Key
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌