openGauss数据库源码解析系列文章——SQL引擎源码解析(二)
(4) 提升子链接:子链接出现在WHERE/ON等约束条件中,通常伴随着ANY/ALL/IN/EXISTS/SOME等谓词同时出现。虽然子链接从语句的逻辑层次上是清晰的,但是效率有高有低,比如相关子链接,其执行结果和父查询相关,即父查询的每一条元组都对应着子链接的重新求值,此情况下可通过提升子链接提高效率。在该部分数据库主要针对ANY和EXISTS两种类型的子链接尝试进行提升,提升为Semi Join或者Anti-SemiJoin,实现函数为pull_up_sublinks。
(5) 减少ORDER BY:由于在父查询中可能需要对数据库的记录进行重新排序,故减少子查询中的ORDER BY语句以进行链接可提高效率,实现函数为reduce_orderby。
(6) 删除NotNullTest:即删除相关的非NULL Test以提高效率,实现函数为removeNotNullTest。
(7) Lazy Agg重写:顾名思义,即“懒聚集”,目的在于减少聚集次数,实现函数为lazyagg_main。
(8) 对连接操作的优化做了很多工作,可能获得更好的执行计划,实现函数为pull_up_subqueries。
(9) UNION ALL优化:对顶层的UNION ALL进行处理,目的是将UNION ALL这种集合操作的形式转换为AppendRelInfo的形式,实现函数为flatten_simple_union_all。
(10) 展开继承表:如果在查询语句执行的过程中使用了继承表,那么继承表是以父表的形式存在的,需要将父表展开成为多个继承表,实现函数为expand_inherited_tables。,实现函数为expand_inherited_tables。
(11)预处理表达式:该模块是对查询树中的表达式进行规范整理的过程,包括对链接产生的别名Var进行替换、对常量表达式求值、对约束条件进行拉平、为子链接生成执行计划等,实现函数为preprocess_expression。
(12) 处理HAVING子句:在Having子句中,有些约束条件是可以转变为过滤条件的(对应WHERE),这里对Having子句中的约束条件进行拆分,以提高效率。
(13) 外连接消除:目的在于将外连接转换为内连接,以简化查询优化过程,实现函数为reduce_outer_join函数。
(14) 全连接full join重写:对全连接函数进行重写,以完善其功能。比如对于语句SELECT * FROM t1 FULL JOIN t2 ON TRUE可以将其转换为:SELECT * FROM t1 LEFT JOIN t2 ON TRUE UNION ALL (SELECT * FROM t1 RIGHT ANTI FULL JOIN t2 ON TRUE),实现函数为reduce_inequality_fulljoins。
下面以子链接提升为例,介绍openGauss中一种最重要的子查询优化。所谓子链接(SubLink)是子查询的一种特殊情况,由于子链接出现在WHERE/ON等约束条件中,因此经常伴随ANY/EXISTS/ALL/IN/SOME等谓词出现,openGauss数据库为不同的谓词设置了不同的SUBLINK类型。代码如下:
Typedef enum SubLinkType {
EXISTS_SUBLINK,
ALL_SUBLINK,
ANY_SUBLINK,
ROWCOMPARE_SUBLINK,
EXPR_SUBLINK,
ARRAY_SUBLINK,
CTE_SUBLINK
} SubLinkType;