openGauss之 无用join消除
一. 前言
openGauss join消除是指部分场景下的left join是无实际意义的,直接去除后和去除前的sql是等价的。如下所示,select t1.* from test1 t1 left join test2 t2 on t1.c1 = t2.c1 可以等价成select t1.* from test1 t1 。
openGauss中,Join消除的入口在remove_useless_joins函数中,本文主要介绍在openGauss中是怎样实现无用join消除的。
二. 表join的无用join消除
join条件在满足如下条件后可以被消除,消除前后等价:
1. join为left join,
2. 内表的join中的on列组合满足唯一性约束,
3. 内表是单个表
4. 内表的列除了在on条件中外,无其他的场景使用到。
表join表的join消除代码如下所示:
remove_useless_joinsfor (lc = list_head(root->join_info_list); lc != NULL; lc = pnext) { // 对于所有的joinjoin_is_removable // 判断join能不能被消除if ((sjinfo->jointype != JOIN_LEFT && sjinfo->jointype != JOIN_LEFT_ANTI_FULL) || sjinfo->delay_upper_joins ||bms_membership(sjinfo->min_righthand) != BMS_SINGLETON)return false; // 必须要是left join和单表if (!rel_supports_distinctness(root, innerrel))return false; // 内表join列必须是唯一性,通过判断是否有唯一索引判断joinrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand); // join中所有引用到的列for (attroff = innerrel->max_attr - innerrel->min_attr; attroff >= 0; attroff--) {if (!bms_is_subset(innerrel->attr_needed[attroff], joinrelids)) // attr_needed为内表引用到的列,不属于joinrelids的话就是被join以外的地方使用到,比如output target, 那不可优化return false;}foreach (l, innerrel->joininfo) {if (!clause_sides_match_join(restrictinfo, sjinfo->min_lefthand, innerrel->relids))continue; /* 必须是外表 join 内表的形式 */}if (rel_is_distinct_for(root, innerrel, clause_list)) // 再次确认内表的join列具有唯一性relation_has_unique_index_for // 判断唯一性的列是否都在join的on条件中for (c = 0; c < ind->nkeycolumns; c++) {foreach (lc, restrictlist) {match_index_to_operand}}return true;// 需要移除的内表 innerrelid = bms_singleton_member(sjinfo->min_righthand);remove_rel_from_query // 从simple_rel_array_size中移除innerrelidremove_rel_from_joinlist // 从 joinlist中删除内表}
三. 子查询join的无用消除
subquery 和 table的区别的唯一区别在于判断on的条件是否能满足唯一性约束。如下场景中子查询都可以满足唯一性约束。
1. join的on条件的列都在distinct中。
2. join的on条件的列都在group by中。
3. 带聚合函数
4. union 不带all的场景
代码流程如下所示:
query_is_distinct_forif (query->distinctClause != NIL) {check_column_uniqueness // distinct的所有列都在join的on条件中,满足唯一性约束,可以被消除foreach (l, groupClause) {distinct_col_search // 能从join的on 条件中找到唯一索引列}}if (query->groupClause != NIL) {check_column_uniqueness(query->groupClause) // group by的所有列都在on条件中也能满足唯一性约束} else {if (query->hasAggs || query->havingQual)return true; // 带聚合函数也能满足唯一性约束}if (query->setOperations != NULL) {if (!topop->all) { // union 不包含allforeach (l, query->targetList) {distinct_col_search // union的所有targer都在join的on条件中}}}