首页/数据/数仓建模速查/分区字段位置与分区裁剪
分层与规范64 条

分区字段位置与分区裁剪

分区字段必须出现在 WHERE 中才能触发裁剪;把分区条件包在函数里(如 substr(dt,1,7))会失效,应改用范围条件。

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

分区裁剪的触发条件

分区裁剪的触发条件很硬:分区列必须直接出现在 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,看实际扫描的分区数与文件数是否符合预期:不同引擎输出字段名略有差异,但都会给出实际读取的分区信息,比凭经验推测可靠。

易错点

  • 分区列上套函数:裁剪完全失效,退化为全分区扫描
  • 为了省事用字符串截取匹配月份:单次查询扫描量放大十几倍
  • 模板拼接分区条件时丢掉原始列名:生成的条件无法参与裁剪
  • 只看结果正确不查执行计划:数据没问题,但成本持续升高
  • 对分区列做类型转换:cast(dt as date) 这类写法同样让裁剪失效

数据来源与参考

  • Hive 官方文档:LanguageManual DML
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌