首页/数据/数据工程与 ETL 速查/谓词下推 Predicate Pushdown
管道基础52 条

谓词下推 Predicate Pushdown

把过滤条件下推到扫描层,在读数据时就跳过不满足条件的行或数据块;Parquet/ORC 依靠列统计(min/max)跳过 row group,显著减少 IO。

谓词下推是什么

谓词下推把过滤条件下推到数据扫描层,在读取阶段就跳过不可能满足条件的行甚至整个数据块,从而减少真正读入计算的数据量。列式格式在这里收益最大:Parquet、ORC 会在每个行组(或条带)里保存列的统计信息(最小值、最大值、空值计数),扫描时先看统计信息,范围之外的行组直接跳过,文件都不用完整解码。

基本信息

原理过滤条件在读取阶段生效,减少进入计算的数据
依赖条件列式格式的统计信息与引擎可下推的表达式
验证方式EXPLAIN 里查看 PushedFilters
相关机制分区裁剪、列裁剪、行组统计跳过
适用格式Parquet、ORC 等带统计信息的列存
受益前提数据写入时大致有序,统计范围收窄

查看下推情况

查看下推情况
EXPLAIN EXTENDED
SELECT order_id, amount FROM dwd_order
WHERE dt = '2026-10-11' AND amount > 100;   -- 关注 PushedFilters 行

-- 对比:先转换再过滤,统计信息难以匹配
-- WHERE CAST(amount AS STRING) > '100'      -- 不推荐

典型使用场景

  • 大表范围查询:按时间或金额过滤时只读相关行组,扫描量成倍下降
  • 分区表查询:分区列上的等值过滤直接裁剪目录,是最有效的一层
  • 窄列查询:只取少数几列,配合列裁剪减少解码与 IO
  • 排查查询变慢:用 EXPLAIN 确认过滤是否真的下推了
  • 优化写入布局:按查询常用的列排序写入,让统计信息范围更窄

生效与失效对照

写法是否下推原因
WHERE dt = '2026-10-11'是分区列直接裁剪
WHERE amount > 100是列统计可判断范围
WHERE CAST(amount AS STRING) > '100'通常否表达式无法匹配统计
WHERE lower(name) = 'x'通常否函数包裹后无法下推
WHERE dt IN (...)是多值等值仍可裁剪
UDF 包装过的条件、隐式类型转换通常无法下推;把可以下推的原始条件保留在 WHERE 外层。
下推的收益取决于统计信息的粒度:小文件的行组很小、统计范围很宽时效果有限,因此小文件治理与谓词下推往往要一起做。

易错点

  • 对同一列先 cast 再过滤,会破坏统计信息匹配,尽量让类型一致
  • 小文件里的统计信息粒度差,下推收益打折,要配合合并小文件
  • 分区列被函数包裹(如日期格式化),分区裁剪完全失效
  • 数据写入顺序完全随机,单列统计范围覆盖全表,行组跳过形同虚设
  • 只看执行时间不看 EXPLAIN,误以为过滤条件已经下推

数据来源与参考

  • Apache Spark 官方文档:Parquet Filters / Predicate Pushdown
  • Apache ORC 官方文档:Indexes
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌