计算下推是将过滤、聚合等计算逻辑下沉至存储层或执行引擎底层执行,以减少网络传输、内存占用和中间结果集;典型场景包括WHERE条件、聚合函数及UDF下推,ClickHouse、StarRocks等支持较好,需通过执行计划确认是否生效。

SQL数据库中的计算下推(Computation Pushdown)是一种优化技术,核心是把本该在应用层或数据库服务端内存中做的计算,尽可能提前到存储层或执行引擎底层完成,从而减少网络传输、内存占用和中间结果集大小。
什么是计算下推
传统SQL执行流程中,数据库先读取原始数据(比如全表扫描),再在服务端逐行做过滤、聚合、函数计算等操作,中间可能生成大量临时数据。而计算下推会把部分逻辑“下沉”到更靠近数据的地方执行——例如下推到存储引擎(如TiKV、Delta Lake)、列存格式解析层(如Parquet reader)、甚至磁盘I/O路径中。
典型场景包括:
• WHERE条件中的函数下推:如WHERE year(order_time) = 2024,若底层支持,可直接在扫描时跳过非2024年的数据块。
• 聚合函数下推:COUNT/SUM/AVG等在分区或文件级别预聚合,减少向上汇总的数据量。
• UDF(用户自定义函数)下推:某些引擎(如Trino+Iceberg、Spark on Delta)支持将轻量UDF编译后下发到读取端执行。
为什么能减少中间结果集
中间结果集变大,往往不是因为最终结果多,而是因为执行过程中保留了太多冗余行或列。计算下推通过“早筛早算”,从源头压缩数据流:
- 下推过滤条件 → 扫描阶段就丢弃不匹配的行,不进入内存迭代器
- 下推投影(SELECT列裁剪)→ 只读取需要的列,尤其对宽表效果显著
- 下推表达式计算(如
price * tax_rate)→ 在读取时完成运算,避免存储原始字段+额外计算两步开销 - 下推LIMIT/OFFSET → 存储层返回前N行,而非全量拉取再截断
哪些数据库/引擎支持较好
支持程度取决于存储格式、执行模型与优化器能力:
- ClickHouse:天然列存+向量化执行,几乎所有函数都默认下推,且支持谓词下推到稀疏索引和跳数索引
- StarRocks / Doris:谓词、投影、聚合、甚至部分窗口函数可下推至BE节点本地处理
- Trino/Presto + Iceberg/Hudi/Delta:依赖表格式元数据(如Iceberg的Snapshot、Partition Spec)实现分区裁剪与谓词下推;部分UDF可通过Connector插件下推
-
Spark SQL(配合Parquet/ORC):支持谓词下推、列裁剪、统计信息跳过(需开启
spark.sql.parquet.filterPushdown等配置) - PostgreSQL:有限下推(如索引条件下推),但多数计算仍在Executor层;FDW插件(如postgres_fdw)可将部分查询下推到远端库
如何确认是否发生下推
关键看执行计划中是否体现“pushed down”或类似语义:
- ClickHouse:用
EXPLAIN SYNTAX或EXPLAIN PIPELINE查看filter/project是否出现在ReadFromMergeTree阶段 - StarRocks:
EXPLAIN VERBOSE中观察Predicate是否标记为PushedDown - Trino:
EXPLAIN (TYPE DISTRIBUTED)里看TableScan节点的Filter和Layout字段是否含下推条件 - Spark:
EXPLAIN FORMATTED中查找PushedFilters和ReadSchema,确认列与过滤是否精简
如果执行计划显示“Filter: (col > 100)”出现在Scan节点内部,大概率已下推;若只在Exchange或HashAggregate之后出现,则未下推。
不复杂但容易忽略:写SQL时尽量让过滤条件干净(避免WHERE UPPER(name) = 'ABC'这种破坏索引/下推的写法),并确保统计信息及时更新——这是触发下推的前提。










