深度解析JQuick-SQL 谓词下推与投影下推优化机制
Meta 描述:本文基于jquick-sql架构原理解读Predicate Pushdown、Projection Pushdown与Limit Pushdown在逻辑计划中的作用,说明过滤、列选择和行数限制如何靠近数据扫描,并关联Java分布式SQL引擎架构、SQL查询优化原理与gRPC分布式数据交换中的传输成本控制。
标签:jquick-sql架构原理、Predicate Pushdown、Projection Pushdown、Limit Pushdown、SQL查询优化原理、Table Scan
官网示例:
- FORMULAS 示例页:https://www.jquick.org/jquick-sql
- github 地址:https://github.com/paohaijiao/jquick-sql
前言
谓词下推(Predicate Pushdown)与投影下推(Projection Pushdown)解决的不是 SQL 结果正确性,而是"尽量少处理无用数据"。在 JQuick-SQL 中,它们是 JQuickLogicalPlanOptimizer 默认注册的真实逻辑规则;Limit Pushdown 同样被注册,用于将行数约束尽可能前移到合适的计划位置。
三者共同服务一个方向:让过滤更早发生、让扫描只关注必要列、让后续算子面对更少行。对于 Java分布式SQL引擎架构,这也意味着更少的聚合输入、更低的 Join 压力和潜在更小的 gRPC 分布式数据交换量。
Predicate Pushdown:让Filter靠近来源
AST 到逻辑计划时,WHERE 会形成 JQuickFilterNode(predicate, root);普通表来源则形成 JQuickTableScanNode。谓词下推规则的目标是在不改变语义的前提下,调整 Filter 与可下推子节点的相对位置,使过滤尽量接近扫描或适合承接条件的算子。
这样做并不意味着所有条件都能直接写入底层数据源。项目逻辑节点中的 Table Scan 本身具有 filterPredicate 字段,Physical Generator 创建 JQuickTableScanPhysicalNode 时也会传递 required columns 与 filter predicate;但具体条件能否继续推到外部系统,取决于数据源与计划形态,不能把"必然下推到数据库"写成既定事实。
Projection Pushdown:减少列宽
投影下推处理的是 SELECT 所需列与表达式所依赖列。逻辑扫描节点持有 requiredColumns,物理生成时会将其传入:
java
new JQuickTableScanPhysicalNode(
node.getTableName(),
node.getAlias(),
node.getRequiredColumns(),
node.getFilterPredicate()
);
这说明投影需求可以沿计划传递到 Scan 的物理表示。与 SELECT * 相比,显式选择 id, name 更利于优化器确认需要的列范围。投影下推也与 Projection Merge 配合:当计划中连续出现可合并 Project,合并规则能减少中间节点。
Limit Pushdown与TopN衔接
JQuickLogicalPlanOptimizer 注册了 JQuickLimitPushdownRule。其职责位于逻辑层,即让 Limit 在语义安全时更靠近数据处理前端。物理层还有一个已确认的进一步优化:如果 JQuickLimitPhysicalNode 的 child 是 JQuickSortPhysicalNode,JQuickPhysicalPlanOptimizer 会构造 JQuickTopNPhysicalNode。
因此应区分两件事:Limit Pushdown 是逻辑规则;Sort + Limit → TopN 是物理计划改写。二者都能减少不必要的结果处理,但发生在不同阶段。
text
TableScan → Filter → Project → Sort → Limit
↓ ↓ ↓
尽早过滤 减少行数 减少列宽
↓
Physical阶段可识别TopN
实操代码案例
README 的真实查询示例正好体现了过滤、列选择、排序与限制可表达的结构:
java
JQuickDataSet result = sql.execute(
"SELECT id, name, age FROM users " +
"WHERE age >= 25 ORDER BY age DESC"
);
若再加入 LIMIT,AST 会形成 Limit 子句,逻辑计划会出现 JQuickLimitNode。这里的重点不是承诺某个外部存储一定执行下推,而是说明 JQuick-SQL 会在计划层提供可优化的 Filter、Project、Limit 结构。
常见问题
WHERE与HAVING都能做谓词下推吗?
二者语义不同。WHERE 作用于聚合前行;HAVING 依赖分组或聚合结果,不能简单等同处理。
Projection Pushdown是否等于默认列剪枝?
不要混淆。源码中独立的 ColumnPruningRule 注册被注释;当前应以已注册的 Projection Pushdown 规则和 Scan 的 required columns 表示为准。
Limit一定能越过Sort或Join吗?
不能一概而论。下推必须保持语义,具体规则只会在满足条件时改写计划。
总结与拓展
Predicate、Projection 与 Limit 下推让 JQuick-SQL 从逻辑层减少行数、列宽和后续算子负担。再结合 Filter Merge、Projection Merge 与物理阶段的 TopN,这些规则构成 SQL查询优化原理中最直接的"少读、少算、少传"路径。
Core Advantage
Pushdown rules reduce work before expensive operators and distributed boundaries.
Applicable Scenarios
Selective queries, wide tables, sorted top-N requests, and distributed plan cost reduction.