谓词下推是什么
谓词下推把过滤条件下推到数据扫描层,在读取阶段就跳过不可能满足条件的行甚至整个数据块,从而减少真正读入计算的数据量。列式格式在这里收益最大: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 外层。
下推的收益取决于统计信息的粒度:小文件的行组很小、统计范围很宽时效果有限,因此小文件治理与谓词下推往往要一起做。