GaussDB(DWS)行执行引擎详解
GaussDB(DWS)行执行引擎详解
1.前言
GaussDB(DWS)包含三大引擎,一是SQL执行引擎,用来解析用户输入的SQL语句,生成执行计划,供执行引擎来执行;二是执行引擎,其中包含了行执行引擎和列执行引擎,执行引擎即查询的执行者,位于优化器和存储引擎之间,负责将数据从存储引擎中读取出来,并根据计划将数据处理加工后返回给客户端,执行引擎的目标是为了更好地利用计算资源,更快地完成计算。三是存储引擎,决定了数据库数据的存取方式,直接影响了数据库的读写性能。
其中行执行引擎应用于行存表中,传统的OLTP(OnLine Transaction Processsing 联机事务处理)场景与功能、业务强相关,数据需要进行频繁的增删改查,这时比较适合使用行存储式。行存储的优势主要有两个方面:首先是点查性能好,在点查场景下可以直接索引到某行数据的元组位置;其次就是更新效率高,行存储在实时并发入库,并发更新方面依然有着比较大的优势。行执行引擎的关键就是:一次处理一行数据,即一tuple,适合数据频繁更新,增删改操作多,且查询结果涉及表的多列的场景。
2.行执行引擎组成
2.1 行执行框架
行执行引擎的执行基本单位是算子,查询计划是以树的形式存在的,算子是执行树上的每个节点。每个算子需要经历初始化,执行,清理的生命周期,执行时包括递归遍历计划树的各个节点,从计划树根节点开始,递归到叶节点来获取一个tuple,经过逐层节点算子的处理,返回一个结果tuple,直到再无tuple。整体算子的执行采用Piepline模式,一次一tuple,控制流从上到下,数据流由下到上,图示实线为控制流,虚线为数据流,使用上层来驱动下层。
2.2 行执行引擎算子
算子总共分为四类,扫描算子,控制算子,物化算子,连接算子等。对于分布式系统而言,还包括着stream算子等。
2.2.1 扫描算子
扫描算子用来扫描表中的数据,每次获取一条元组作为上层节点的输入, 存在于查询计划树的叶子节点,它不仅可以扫描表,还可以扫描函数的结果集、链表结构、子查询结果集。一些比较常见的扫描算子如表所示。
算子 | 含义 | 出现场景 |
---|---|---|
SeqScan | 顺序扫描 | 最基本的扫描算子,用于扫描物理表(没有索引辅助的顺序扫描) |
IndexScan | 索引扫描 | 选择条件涉及的属性上建立了索引 |
IndexOnlyScan | 直接从索引返回元组 | 索引列完全覆盖结果集列 |
BitmapScan(BitmapIndexScan, BitmapHeapScan) | 利用Bitmap获取元组 | BitmapIndexScan利用属性上的索引进行扫描,返回结果为一个位图;BitmapHeapScan从BitmapIndexScan输出的位图中获取元组 |
TidScan | 通过元组tid获取元组 | 1.WHERE conditions(like CTID = tid or CTID IN (tid1, tid2, …)) ;2.UPDATE/DELETE … WHERE CURRENT OF cursor |
SubqueryScan | 子查询扫描 | 以另一个查询计划树(子计划)为扫描对象进行元组的扫描 |
FunctionScan | 函数扫描 | FROM function_name |
ValuesScan | 扫描values链表 | 对VALUES子句给出的元组集合进行扫描 |
ForeignScan | 外部表扫描 | 查询外部表 |
CteScan | CTE表扫描 | 扫描SELECT查询中用WITH子句定义的子查询 |
2.2.2 连接算子
连接算子对应了关系代数中的连接操作,以表 t1 join t2 为例,主要的集中连接类型如下:inner join、left join、right join、full join、semi join、 anti join,其实现方式包括Nestloop、HashJoin、MergeJoin;
算子 | 含义 | 出现场景 |
---|---|---|
NestLoop | 嵌套循环连接,暴力连接,对每一行都扫描内表 | Inner Join, Left Outer Join, Semi Join, Anti Join |
MergeJoin | 归并连接(输入有序),内外表排序,定位首尾两端,一次性连接元组。等值连接 | Inner Join, Left Outer Join, Right Outer Join, Full Outer Join, Semi Join, Anti Join |
HashJoin | 哈希连接,内外表使用join列的hash值建立hash表,相同值的必在同一个hash桶。等值连接 | Inner Join, Left Outer Join, Right Outer Join, Full Outer Join, Semi Join, Anti Join |
三类连接算子的实现方式特点:
算子类型 | NestLoop | HashJoin | MergeJoin |
---|---|---|---|
执行方式 | 对于外表每一行,嵌套扫描内表返回结果 | 内表根据join列散列建立hash表,外表使用相同hash值仅匹配相应hash桶 | 内外表均排序后,进行排序后的归并连接操作 |
限制 | 无 | 连接两端必须为类型相同的等值连接,且支持hash散列 | (1)等值连接(2)内外表有序 |
优势 | 当内表使用索引时,可以快速定位连接元组 | 通过哈希散列,一次性定位连接元组 | 通过归并连接,一次性定位连接元组 |
劣势 | 每个外表元组均需要重新执行内结点操作 | 内表在内存中放不下可能导致使用多轮hash,列重复值太多可能导致分桶 | 内外表需要有序,因此必须承受内外表Index Scan或Sort的代价 |
使用场景 | 外表结果集小 | 内表可在内存里放下,列重复值和倾斜不要太多 | 内外表已经有序,不需要重新排序 |
2.2.3 物化算子
物化算子是一类可缓存元组的节点。在执行过程中,很多扩展的物理操作符需要首先获取所有的元组才能进行操作(例如聚集函数操作、没有索引辅助的排序等),这是要用物化算子将元组缓存起来;
算子 | 含义 | 出现场景 |
---|---|---|
Material | 物化 | 缓存子节点结果 |
Sort | 排序 | ORDER BY子句,连接操作,分组操作,集合操作,配合Unique |
Group | 分组操作 | GROUP BY子句 |
Agg | 执行聚集函数 | 1. COUNT/SUM/AVG/MAX/MIN等聚集函数;2. DISTINCT子句;3. UNION去重;4. GROUP BY子句 |
WindowAgg | 窗口函数 | WINDOW子句 |
Unique | 去重(下层已排序) | 1. DISTINCT子句;2. UNION去重 |
Hash | HashJoin辅助节点 | 构造hash表,配合HashJoin |
SetOp | 处理集合操作 | INTERSECT/INTERSECT ALL, EXCEPT/EXCEPT ALL |
LockRows | 处理行级锁 | SELECT … FOR SHARE/UPDATE |
2.2.4 控制算子
控制算子是一类用于处理特殊情况的节点,用于实现特殊的执行流程。
算子 | 含义 | 出现场景 |
---|---|---|
Result | 直接进行计算 | 1. 不包含表扫描;2. INSERT语句中只有一个VALUES子句;3. 当 Append/MergeAppend为计划根节点(投影上推) |
ModifyTable | INSERT/UPDATE/DELETE上层节点 | INSERT/UPDATE/DELETE |
Append | 追加 | 1. UNION(ALL);2. 继承表 |
MergeAppend | 追加(输入有序) | 1. UNION(ALL);2. 继承表 |
RecursiveUnion | 处理WITH子句中递归定义的UNION子查询 | WITH RECURSIVE … SELECT … 语句 |
BitmapAnd | Bitmap逻辑与操作 | 多维索引扫描的BitmapScan |
BitmapOr | Bitmap逻辑或操作 | 多维索引扫描的BitmapScan |
Limit | 处理LIMIT子句 | OFFSET … LIMIT … |
2.2.5 其他算子
其他算子包括Stream算子,以及RemoteQuery等算子
Stream算子主要有三种类型:Gather stream、Broadcast stream、Redistribute stream
-
Gather算子: 每个源结点都将其数据发送给目标结点进行汇聚
-
Broadcast stream: 由一个源节点将其数据发给N个目标节点进行运算
-
Redistrubute stream: 每个源节点将其数据根据连接条件计算Hash值,根据重新计算的Hash值进行分布,发给对应的目标节点
算子 | 含义 | 出现场景 |
---|---|---|
Stream | 多节点数据交换 | 执行分布式查询计划,节点间存在数据交换 |
Partition Iterator | 分区迭代器 | 分区表扫描,迭代扫描每个分区 |
RowToVec | 行转列 | 行列混合场景 |
DfsScan / DfsIndexScan | HDFS表(索引)扫描 | HDFS表扫描 |
3. 执行框架总结
本文主要讲解了如下几个方面:
- 大致介绍了GaussDB(DWS)行执行引擎在整个数据库系统中的位置;
- 介绍了行执行引擎的框架;
- 最后介绍了一些常见和常用的行执行引擎相关的算子。
- 点赞
- 收藏
- 关注作者
评论(0)