SQL 执行引擎是 GaussDB 架构中占比很重的一部分,理解一条 SQL 从解析到执行的完整链路,是掌握性能优化和计划分析的基础。本文整理查询重写、路径搜索、执行器模块分工以及 PBE 执行模型相关的知识点。
一、SQL 引擎整体流程
一条 SQL 语句在 GaussDB 中大致经历四个阶段:
- 查询解析(词法分析 / 语法分析 / 语义分析)
- 查询重写
- 计划生成(路径搜索)
- 查询执行
SQL 是声明式语言,解析阶段处理的是 "What"(要什么),优化器处理的才是 "How"(怎么做)。
产物链大致为:SQL → Token → 语法树 → 查询树 → 重写后的查询树 → 路径 → 计划树。
二、查询重写
查询重写通常使用关系代数来规范化表示查询,并遵循两个基本原则:
- 等价性:重写前后的查询结果必须一致;
- 高效性:降低执行时间或资源消耗。
常见的重写方向包括:减少查询层次、消除冗余操作、选择下推、投影下推等。
一个重要的约束是:不能通过改变查询结果来换取速度。
三、自底向上的路径搜索
GaussDB 主要采用自底向上的路径搜索方式(结合随机搜索),其过程是:
- 先建立表的扫描算子;
- 再由扫描算子构成连接算子;
- 形成多个候选物理执行路径;
- 估算各路径代价,选择代价最低的执行计划。
记忆口诀 :先扫描,再连接,比代价,选最低。
四、执行器模块分工
执行器由三个核心模块分工协作:
| 模块 | 职责 |
|---|---|
| Portal | 根据解析结果选择处理策略和处理模块,负责分流 |
| Executor | 处理查询及增删改等 DML |
| ProcessUtility | 处理 DDL、游标、事务、表空间等实用语句 |
记忆口诀 :Portal 分流,Executor 做 DML,ProcessUtility 做 DDL。
执行器采用火山模型 ,算子抽象为 init() / get_next() / end() 三个接口,特点是控制流向下、数据流向上 ------上层算子通过 get_next() 驱动下层算子,底层 Scan 从存储层取数。
五、PBE 执行模型
PBE(Parse-Bind-Execute)是 GaussDB 执行 SQL 的重要模型,分为三个报文:
- Parse:解析 + 重写,结果存入计划缓存;
- Bind:生成定制计划(Cplan)或通用计划(Gplan),构造 Portal;
- Execute:执行。
关键参数 prepareThreshold 默认值为 5:同一 SQL 执行超过 5 次后,JDBC 不再发送 Parse 报文,直接复用服务端缓存的解析结果。
六、分布式执行
分布式架构下有一些特有的算子需要了解:
- Stream:分布式特有算子,负责节点间数据传输。
- Gather:N:1,把 DN 的结果汇总到 CN。
- Broadcast:1:N,把输入复制到所有节点。
两者不能混淆:Gather 是汇总,Broadcast 是广播复制。
小结
- 查询重写用关系代数,遵循等价性 + 高效性。
- 自底向上路径搜索:扫描 → 连接 → 最低代价。
- Portal 分流、Executor 做 DML、ProcessUtility 做 DDL。
- 火山模型控制流向下、数据流向上。
- PBE 中
prepareThreshold默认 5;Gather 汇总、Broadcast 广播、Stream 分布式特有。