openGauss源码解析(113)
openGauss源码解析:执行器解析(6)
7.3 执行算子
执行算子模块包含多种计划执行算子,算子类型如表7-4所示,是计划执行的独立单元,用于实现具体的计划动作。执行计划包含4类算子,分别是控制算子、扫描算子、物化算子和连接算子,如表7-4所示。这些算子统一使用节点(node)表示,具有统一的接口,执行流程采用递归模式。整体执行流程是:首先根据计划节点的类型初始化状态节点(函数名为“ExecInit+算子名”),然后再回调执行函数(函数名为“Exec+算子名”),最后是清理状态节点(函数名为“ExecEnd+算子名”)。本节主要介绍行执行算子,面向列存储的算子在后续章节(向量化引擎)介绍。
表7-4 执行算子类型
算子类型 | 说明 |
|---|---|
控制算子 | 处理特殊执行流程,如Union语句 |
扫描算子 | 用于扫描表对象,从表中获取数据 |
物化算子 | 缓存中间执行结果到临时存储 |
连接算子 | 用于实现SQL中的各类join操作,通常包含nested loop join、hash join、merge-sort join等 |
7.3.1 控制算子
控制算子主要用于执行特殊流程,这类流程通常包含两个以上输入,如Union操作,需要把多个子结果(输入),合并成一个。控制算子有多种,如表7-5所示。
表7-5 控制算子
算子名称 | 说明 |
|---|---|
Result算子 | 处理只有一个结果或过滤条件是常量 |
Append算子 | 处理包含一个或多个子计划的链表 |
BitmapAnd算子 | 对结果做And位图运算 |
BitmapOr算子 | 对结果做Or位图运算 |
RecursionUnion算子 | 递归处理UNION语句 |
1. Result算子
Result算子对应的代码源文件是“nodeResult.cpp”,用于处理只有一个结果(如通过SELECT调用可执行函数或表达式,或者INSERT语句只包含Values字句)或者WHERE表达式中的结果是常量(如“SELECT * FROM emp WHERE 2 > 1”,过滤条件“2 > 1”是常量只需要计算一次即可)的流程。由于openGauss没有提供单独的投影算子(Projection)和选择算子(Selection),Result算子也可以起到类似的作用。
Result算子提供的主要函数如表7-6所示。
表7-6 Result算子主要函数
主要函数 | 说明 |
|---|---|
ExecInitResult | 初始化状态机 |
ExecResult | 迭代执行算子 |
ExecEndResult | 结束清理 |
ExecResultMarkPos | 标记扫描位置 |
ExecResultRestrPos | 重置扫描位置 |
ExecReScanResult | 重置执行计划 |
ExecInitResult函数初始化Result状态节点,主要执行流程如下。
(1) 构造状态节点,构造ResultState状态结构。
(2) 初始化元组表。
(3) 初始化子节点表达式(生成目标列表的表达式、过滤表达式和常量表达式)。
(4) 初始化左子节点(右子节点是空)。
(5) 初始化元组类型和投影信息。
ExecResult函数迭代输出元组,流程图如图7-6所示,主要执行流程如下。
(1) 检查是否需要做常量表达式计算,如果之前没有做常量表达式计算则需要计算表达式并设置检查标识(如果常量表达式计算结果为false,则设置约束检查标识位)。
(2) 判断是否需要做投影处理,如果返回结果是集合,则把投影结果直接返回。
(3) 执行元组获取。

图7-6 Result算子执行流程
ExecEndResult函数是在执行计划执行结束时调用,用于释放执行过程申请的资源(存储空间)。

浙公网安备 33010602011771号