分区裁剪的触发条件
分区裁剪的触发条件很硬:分区列必须直接出现在 WHERE 的过滤条件里。把分区列包进函数(例如 substr(dt,1,7)='2026-10' 或 date_format(dt,'yyyyMM')='202610'),优化器就无法把它映射到分区目录,裁剪完全失效,作业退化为扫描全部分区。正确做法是改写成范围条件,例如 dt BETWEEN '2026-10-01' AND '2026-10-31'。
基本信息
| 触发条件 | 分区列直接参与比较 |
|---|---|
| 失效写法 | 分区列被函数或类型转换包裹 |
| 替代写法 | 等值条件、范围条件或 IN 枚举 |
| 验证方法 | 看执行计划里实际扫描的分区数 |
| 高发位置 | 对账与巡检类脚本 |
典型使用场景
- 按月份取数:改写成起止日期范围,避免写成 substr(dt,1,7) 导致全分区扫描
- 对账脚本跨多年比对:分区条件必须保留原始分区列,否则每次扫全部分区
- 上游只传月份参数:在脚本里把月份展开成起止日期再传进 SQL
- 巡检与监控作业:分区条件由模板生成,模板里要保留原始分区列
- 迁移历史脚本:原库写法在 Hive 或 OLAP 上未必裁剪,需要逐条检查
裁剪写法对比
裁剪写法对比
-- 可裁剪:分区列直接参与比较
SELECT * FROM dwd_trade_order_di
WHERE dt BETWEEN '2026-10-01' AND '2026-10-31';
-- 不可裁剪:分区列被函数包裹,无法定位到分区目录
SELECT * FROM dwd_trade_order_di WHERE substr(dt,1,7)='2026-10';
-- 验证:查看执行计划里实际扫描的分区数
EXPLAIN SELECT count(1) FROM dwd_trade_order_di WHERE dt='2026-10-13';常见写法判定
| 写法 | 是否裁剪 | 说明 |
|---|---|---|
| dt='2026-10-13' | 裁剪 | 等值条件,只扫一个分区 |
| dt BETWEEN 'a' AND 'b' | 裁剪 | 范围条件,扫描区间内的分区 |
| dt IN ('2026-10-01','2026-10-02') | 裁剪 | 枚举值同样生效 |
| substr(dt,1,7)='2026-10' | 不裁剪 | 分区列被函数包裹,退化为全分区扫描 |
| cast(dt as date) >= '2026-10-01' | 不裁剪 | 类型转换同样让裁剪失效 |
对账与巡检类脚本尤其要检查这一点:这类脚本往往跨多年数据,一旦裁剪失效,每次执行都错扫全部分区,既慢又贵,而且因为结果正确,问题长期不会被发现。
判断裁剪是否生效最快的办法是在 SQL 前加 EXPLAIN,看实际扫描的分区数与文件数是否符合预期:不同引擎输出字段名略有差异,但都会给出实际读取的分区信息,比凭经验推测可靠。