土法炼钢兴趣小组的算法知识备份

【分布式 OLAP 查询引擎】Calcite 与规则/代价优化框架

文章导航

分类入口
databasedistributed
标签入口
#calcite#relnode#volcano-planner#cascades#query-optimizer#trino#rule-based#predicate-pushdown#cbo

目录

第 2 篇 的逻辑计划是 未优化或初建 的代数树。优化器通过 等价变换规则 缩小搜索空间、下推谓词与投影,再交给 代价模型 选物理实现(第 4–5 篇)。Apache Calcite 是工业界最常见的 独立优化器框架;Trino 使用 自研 planner,但在 Rel 代数、规则链思想上与 Calcite 同源借鉴不能把 Trino 等同于「跑 Calcite 的 fork」。

本文钉住 Calcite 的核心抽象,并说明 Trino 476+ 与 Spark 3.5+ Catalyst 在优化阶段的对应关系。不展开 Calcite 全 API;源码与文档为 A 级依据。

环境:本机无 JVM 优化器调试环境;Trino/Spark 行为以官方文档与标注版本为准。不粘贴未实测的 EXPLAIN 输出


一、为什么需要独立优化框架

flowchart TB
  FE["SQL Frontend<br/>many engines"]
  OPT["Optimizer<br/>rules + cost"]
  BE["Backends<br/>Trino / Spark / JDBC"]
  FE --> OPT --> BE
耦合方式 优点 缺点
优化与执行一体(早期单引擎) 实现快 难以复用、测试难
Calcite 式 IR + 规则 多后端、可测等价性 学习曲线、trait 设计

Flink Table、Hive、Dremio 等历史上均与 Calcite 有交集;Trino 选择 深度自研 以控制 MPP 分布式 trait 与 connector SPI(Trino Developer guide, Planner)。


二、RelNode:关系代数 IR

Calcite 中计划节点为 RelNode 子类,与 第 2 篇 LogicalPlan 一一对应:

RelNode 代数 关键属性
TableScan 基表 RelOptTable
LogicalFilter \(\sigma\) condition
LogicalProject \(\pi\) projects
LogicalJoin \(\bowtie\) joinType, condition
LogicalAggregate GROUP BY groupSet, aggCalls
LogicalSort sort collation, offset/fetch

表达式RexNode(row expression)中表示:列引用 InputRef、常量、函数调用。Constant folding 在 Rex 层完成。

Trino 内部使用 PlanNode 层次(TableScanNodeFilterNode…),概念同构,命名不同(A 级:Trino 源码 io.trino.sql.planner)。


三、Convention 与 Trait

物理计划需绑定 执行约定

概念 含义 示例
Convention 数据如何流动 NONE(逻辑)、ENUMERABLE(JVM 行迭代)、引擎自定义
Trait 物理属性 PHYSICALDISTRIBUTIONSORT

Implementation RuleLogicalJoin 转为带 Convention.TRINO(概念名)的 HashJoinNode,并声明 输出 trait(如 hash 分区 on join key)。

flowchart LR
  LJ["LogicalJoin<br/>Convention: NONE"]
  R["Rule: JoinToHashJoin"]
  PJ["Physical HashJoin<br/>+ DISTRIBUTION"]
  LJ --> R --> PJ

MPP 中 DISTRIBUTION trait 决定是否插入 Exchange第 11 篇):例如 probe 端需 HASH(custkey) 与 build 端一致。


四、Rule-based 优化:常见规则链

规则形式:Pattern → Transform,保持等价性。典型 logical rules(Calcite 与 Trino 均存在同类实现,名称各异):

规则意图 效果
Filter pushdown Filter 贴近 TableScan
Project merge / prune 去掉未引用列
Join pushdown Filter 穿过 Join(条件允许时)
Limit pushdown LIMIT 下推到 scan(connector 支持时)
Predicate simplify 布尔式化简、contradiction 检测
Join elimination 外键 join 维表可省

DuckDB 1.5.4 本机 实验SEQ_SCANFilters: o_orderdate>=...,即 filter into scan 的结果。

4.1 下推边界

并非所有谓词都能进 connector:

谓词类型 常可下推 常留上层
列 vs 常量 Parquet min/max、Iceberg partition
列 vs 列(同表) 部分引擎 复杂表达式
非确定性函数 now()rand()
UDF 视 connector 默认否

lakehouse/18四层漏斗 在引擎侧由 layout constraint + rule 共同触发(第 15 篇)。


五、VolcanoPlanner 与 Cascades

算法 特点 用途
Volcano / GPOPT 自顶向下,匹配规则,代价剪枝 Calcite VolcanoPlanner
Cascades Memo 结构、group 合并等价子计划 搜索空间大的 join reorder

Memo:同一逻辑表达式对应 Group,多种物理实现并存,Winner 由代价选优。

flowchart TB
  G1["Group: Scan orders"]
  G2["Group: Scan customer"]
  G3["Group: Join"]
  G1 --> G3
  G2 --> G3
  G3 --> G4["Group: Agg"]

Implementation rules 在 group 内展开 HashJoin vs MergeJoin;Exploration rules 做 join reorder(第 5 篇)。

Trino JoinOrderOptimizerdynamic programming / heuristic 边界见 Trino 文档 Join planning(476+);实现细节在源码,不在此篇臆测默认算法版本差异。


六、Trino 与 Calcite 的关系

问题 事实(A/B 级)
Trino 是否嵌入 Calcite runtime? (自研 planner;Presto 时代已如此)
是否借鉴 Rel 代数? (PlanNode ≈ RelNode)
SQL parser Trino 自有 SqlParser
代价 Trino CostCalculator + stats(第 4 篇

写作口径:说「Calcite 框架」或「与 Calcite 同类的 rule + cost 搜索」,不说「Trino 基于 Calcite 构建」。

Spark Catalyst 是另一套 Scala Tree + RuleExecutor(第 13 篇),阶段名 Optimizer / SparkPlanner,与 Calcite 无直接依赖,但 规则链思想平行


七、优化阶段流水线(Trino 概念)

flowchart LR
  LP["Logical plan"]
  LR["Logical rules"]
  SP["Stats + CBO"]
  PP["Physical rules"]
  DP["Distributed planning"]
  LP --> LR --> SP --> PP --> DP
阶段 输入/输出
Logical rules 下推、裁剪、简化
CBO 统计 → join order、join algo
Physical 具体算子、local exchange
Distributed Fragment、remote exchange、split

PostgreSQL 在 单进程 内完成类似链条(PG 第 10–11 篇),无 Distributed 层;parallel worker 是物理计划上的 partial path,不是 shuffle 网络。


八、Rule 调试与可观测

手段 引擎 说明
EXPLAIN (TYPE LOGICAL) Trino 逻辑层前后对比需版本支持的阶段日志
EXPLAIN (TYPE VALIDATE) Trino 计划合法性检查
Calcite RelMetadataQuery Calcite 系 开发时 row count 推导
DuckDB EXPLAIN DuckDB 直接看物理计划(含规则结果)

生产 Trino 调优常看 默认 EXPLAIN + EXPLAIN ANALYZE第 12 篇),而非逐条 rule trace。


九、与 columnar-engine 的衔接

columnar-engine存储层向量化读;优化器决定 读哪些列、哪些 granule/file。规则 Project prune 直接减少 ColumnHandle 数量;Filter pushdown 减少 row group / page 解码(columnar-engine 第 4 篇)。

执行层 向量化 batch 由 physical rule 选型(BatchScan + VectorizedFilter),属 第 7 篇


十、小结

Calcite 提供了 RelNode + RexNode + Rule + Trait/Convention + Volcano/Cascades 的完整叙事;Trino 在 自研 planner 中实现同类阶段,并扩展 分布式 trait 与 connector layout。理解规则链后,读 EXPLAIN 时能看到 Filter 是否在 Scan 下、Project 是否只剩必要列——这是下推与列裁剪是否生效的第一眼检查。

下一篇进入 统计信息与代价模型:NDV、histogram、connector stats 如何进入 CostCalculator


参考资料

  1. Apache Calcite Documentation, Algebra / Rules / Cost-based optimization
  2. Trino Documentation, Developer guide / Cost-based optimizations(476+)。
  3. Graefe, The Volcano Optimizer Generator(经典,规则与 extensibility)。
  4. 第 2 篇(LogicalPlan)。
  5. postgresql-kernel 第 10 篇(PG 统计对照)。
  6. Apache Spark Documentation, Catalyst Optimizer(3.5+)。

返回 系列目录 | 上一篇:逻辑计划 | 下一篇:统计与代价模型

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-07-07 · database / distributed

【分布式 OLAP 查询引擎】Trino · Spark · DuckDB · 优化与 MPP 执行

闭合数据平台栈最后一块:从 SQL 解析与 Calcite 式优化,到 Volcano/向量化执行、Trino Coordinator/Worker 与 shuffle,再到 Iceberg connector 下推与生产排查。承接 lakehouse 第 18 章读湖视角,补全「谁在做 planning」的引擎内核层。

2026-07-07 · database / distributed

【分布式 OLAP 查询引擎】统计信息与代价模型

Table/column 统计、NDV 与 histogram、Iceberg Puffin/manifest 统计来源;Trino CostCalculator 与 CPU/IO/network 权重;统计过期导致全表扫与 join 中间结果膨胀;对照 PostgreSQL pg_statistic。


By .