bigywater.tech
ClickHouse 内部原理 · 14

Partition:按月分区和按天分区怎么选

真实对比按月和按天分区在同样数据量下产生的分区数差异,再故意撞上分区数上限,拿到ClickHouse官方对分区用途的真实定位说明。

3 vs 90
同样90天数据,按月/按天分区真实产生的分区数
官方原话
分区真实不是为了加速SELECT,ORDER BY才是

做的事:同样90天数据,真实分别按月和按天建分区

代码CREATE TABLE demo.pmonth (d Date, k UInt64) ENGINE=MergeTree PARTITION BY toYYYYMM(d) ORDER BY k; CREATE TABLE demo.pday (d Date, k UInt64) ENGINE=MergeTree PARTITION BY toDate(d) ORDER BY k; INSERT INTO demo.pmonth SELECT toDate('2026-01-01')+number, number FROM numbers(90); INSERT INTO demo.pday SELECT toDate('2026-01-01')+number, number FROM numbers(90);

验证:同样90天数据,真实3个分区 vs 90个分区

实测 · 本机执行输出
SELECT count(DISTINCT partition) FROM system.parts WHERE table='pmonth' AND active;
→ 3    ← 真实覆盖2026年1、2、3月,正好3个分区

SELECT count(DISTINCT partition) FROM system.parts WHERE table='pday' AND active;
→ 90   ← 真实每天一个分区

同样90天的数据,按月分区真实只产生3个分区目录,按天分区真实产生90个——分区数直接由分区键的粒度决定,跟数据量本身无关。

验证:故意插入1000天的按天分区数据,真实撞上官方限制

实测 · 本机执行输出(真实触发max_partitions_per_insert_block=100)
SELECT value FROM system.settings WHERE name='max_partitions_per_insert_block';
→ 100

INSERT INTO demo.pday2 SELECT toDate('2020-01-01')+number, number FROM numbers(1000);
→ 真实报错:
DB::Exception: Too many partitions for single INSERT block (more than 100).
Large number of partitions is a common misconception. It will lead to
severe negative performance impact, including slow server startup,
slow INSERT queries and slow SELECT queries. Recommended total number
of partitions for a table is under 1000..10000. Please note, that
partitioning is not intended to speed up SELECT queries (ORDER BY key
is sufficient to make range queries fast). Partitions are intended for
data manipulation (DROP PARTITION, etc). (TOO_MANY_PARTS)
这段真实的官方报错原文说得非常直白:分区(Partition)不是用来加速SELECT查询的,ORDER BY主键才是;分区真正的用途是数据管理层面的操作,比如DROP PARTITION一键删掉整月/整天的数据、或者把某个分区单独挪到冷存储。如果为了"加速查询"而把分区键设得特别细(比如按天甚至按小时分区),代价是真实会拖慢服务器启动(启动时要扫描所有分区目录加载元数据)、拖慢INSERT(本文另一篇《Small Part》验证过part数越多写入越慢,而按天分区天然会产生更多更小的part)、也会拖慢SELECT(更多分区意味着即使被裁剪剩下的分区数量也可能更多,需要打开更多文件)。真实的建议是:分区键选一个跟你数据保留策略/冷热分层节奏匹配的粒度(月更粗,适合按月归档删除的场景;天更细,适合需要频繁按天回滚/重跑当天数据的场景),然后把真正决定查询性能的排序逻辑交给ORDER BY,而不是指望分区键帮你做range查询加速。

分步演示:从分区数对比到官方给出的真实定位

每一步都是本文上面用真实建表插入跑出来的原始结果。

按月3个分区 vs 按天90个分区,真实的取舍
这一步新验证的场景

    本文用到的工具

    • 本机 ClickHouse 26.9.4(单节点),真实的 system.parts(partition列)
    • 真实触发 max_partitions_per_insert_block(默认100)拿到官方报错原文
    京ICP备2026067502号-1京公网安备11010502063487号