首页/数据/NoSQL 速查/PARTITION BY 分区设计与裁剪
ClickHouse56 条

PARTITION BY 分区设计与裁剪

分区键把数据切成独立目录,便于按月/天批量删除、移动冷数据;查询里对分区键的过滤可以整块跳过分区,是运维与查询双层优化的关键。

NoSQL 速查数据更新于 2026-10-13

分区键决定什么

分区键把数据切成互相独立的目录:同一个分区的数据单独存放,删除与移动都以分区为单位。查询时对分区键的过滤可以整块跳过分区,日常运维也能用一条 DROP PARTITION 秒级清掉历史数据,因此分区设计同时影响查询效率与运维成本。

基本信息

常用写法toYYYYMM(ts) 按月、toDate(ts) 按天、tuple(region, toYYYYMM(ts)) 组合
收益分区裁剪减少扫描,DROP PARTITION 可秒级清理历史数据
代价分区数量过多会让元数据、合并与查询开销一起上升
分区键类型表达式结果最好是整数或日期,避免浮点与 Nullable
查看方式system.parts 按 partition 分组统计行数与体积

典型使用场景

  • 按时间清理:用 DROP PARTITION 替代逐行删除
  • 冷热分层:按分区把老数据整体搬到冷存储
  • 查询加速:时间过滤直接跳过分区目录
  • 数据重算:只对有问题的分区重新导入
  • 容量分析:按分区看数据量与增长趋势

常用操作

常用操作
-- 建表时按月分区
CREATE TABLE events
(
    ts      DateTime,
    user_id UInt64,
    action  LowCardinality(String)
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(ts)
ORDER BY (user_id, ts);

-- 查看分区及大小
SELECT partition, rows, formatReadableSize(bytes_on_disk) AS size
FROM system.parts
WHERE table = 'events' AND active
ORDER BY partition;

-- 按分区删除历史数据,远比 DELETE 快
ALTER TABLE events DROP PARTITION '202301';

-- 用执行计划确认过滤是否触发了分区裁剪
EXPLAIN indexes = 1 SELECT count() FROM events WHERE toYYYYMM(ts) = 202610;

分区粒度对照

分区键粒度适用
toYYYYMM(ts)按月保留期长、数据量中等的表
toDate(ts)按天保留期短、需要按天重算的表
tuple(region, toYYYYMM(ts))组合按地域与月份双维度管理
按秒或按高基数列过细分区数量失控,合并与元数据开销激增
按月分区适合保留期长的表,按天分区适合保留期短或需要按天重算的表,两者也可以组合成 tuple 键;关键是让分区总数维持在可维护的量级。
对分区表达式直接过滤(例如 toYYYYMM(ts) = 202610)最容易命中裁剪;写成时间范围的形式通常也能裁剪,不确定时用 EXPLAIN indexes = 1 看一眼实际跳过情况。

易错点

  • 分区粒度选得过细(按秒或按高基数列分区)会让分区数量失控,元数据、合并与查询开销一起上升
  • 分区键使用 Nullable 或浮点列时行为不易预期,优先选择确定性的整数或日期表达式
  • 把 DROP PARTITION 当成按条件删除数据的手段:它只能整分区删除,条件删除仍需 ALTER DELETE,两者代价差别很大
  • 分区键在表建好之后几乎无法平滑调整,改分区方式基本等于重建表,设计时要按保留期与重算周期提前规划

数据来源与参考

  • ClickHouse Docs: Custom partitioning key
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌