分区裁剪是什么
分区裁剪(Partition Pruning)指查询只读取过滤条件命中的分区目录,跳过其余目录。它是数仓查询性能的第一前提:一张按天分区的表有上千个分区,一次只查一天的查询应该只扫一个目录,而不是全表。前提是过滤条件直接作用在分区列上。
什么写法会让裁剪失效
对分区列做函数变换是最常见的失效原因:把 dt 包进 substr、date_format、cast 之类的表达式后,引擎无法把条件映射到目录名,只能退化为扫描全部分区。类型不一致也会触发隐式转换,同样可能破坏裁剪。
基本信息
| 原理 | 按分区目录的统计信息跳过无关目录 |
|---|---|
| 前提 | WHERE 中直接出现分区列,使用等值、IN 或范围条件 |
| 失效原因 | 对分区列做函数变换、类型隐式转换 |
| 验证方式 | EXPLAIN 中查看扫描的分区数或分区过滤条件 |
| 相关优化 | 列式存储的列裁剪与统计信息跳过 |
分区列写法对错对照
| 写法 | 能否裁剪 | 说明 |
|---|---|---|
| WHERE dt = '2026-10-11' | 能 | 最理想,直接命中单个分区 |
| WHERE dt IN ('2026-10-10','2026-10-11') | 能 | 命中多个分区 |
| WHERE dt BETWEEN '2026-10-01' AND '2026-10-11' | 能 | 范围裁剪 |
| WHERE substr(dt,1,7) = '2026-10' | 不能 | 对分区列做函数运算,退化为全分区扫描 |
| WHERE dt = 20261011 | 可能不能 | 分区列为字符串而传入数字,隐式转换可能破坏裁剪 |
典型使用场景
- 报表查询:按业务日期过滤,只扫当天或当月的分区
- 补数任务:按区间重跑,精确命中受影响分区的集合
- 巡检核查:用 EXPLAIN 确认线上慢查询是否真的只扫了目标分区
- 分区设计:把最常用的过滤字段设计成分区列
- 性能对比:改动前后对比扫描分区数,量化优化效果
可裁剪与不可裁剪
可裁剪与不可裁剪
-- 可裁剪:分区列直接过滤
SELECT COUNT(*) FROM dwd_order WHERE dt = '2026-10-11';
-- 不可裁剪:对分区列做函数运算,退化为全分区扫描
SELECT COUNT(*) FROM dwd_order WHERE substr(dt, 1, 7) = '2026-10';
-- 改写方式:把函数移除,改成显式的范围条件,恢复分区裁剪
SELECT COUNT(*) FROM dwd_order
WHERE dt >= '2026-10-01' AND dt <= '2026-10-31';
-- 验证:EXPLAIN 中观察扫描的分区数量与分区过滤条件
EXPLAIN SELECT COUNT(*) FROM dwd_order WHERE dt = '2026-10-11';写 SQL 时保持分区列「裸用」是最省事的纪律:任何加工、格式化、类型转换都放到取数之后再做,既保证裁剪,也避免把格式差异带到下游。
动态分区写入未限制分区数可能一次产生大量小分区:任务本身能跑完,但元数据与后续查询规划都会明显变慢,应按数据量控制每次写入的分区数量。