openGauss源码解析(100)
openGauss源码解析:SQL引擎源解析(15)
(2) match_unsorted_outer函数。
match_unsorted_outer函数大部分整体代码思路和sort_inner_and_outer一致,最主要的一点不同是sort_inner_and_outer是根据条件去推断出内外表的pathkey。而在match_unsorted_outer函数中,是假定外表路径是有序的,它是按照外表的pathkeys反过来排序连接条件的,也就是外表的pathkeys直接就可以作为outerkeys使用,查看连接条件中哪些是和当前的pathkeys匹配的并把匹配的连接条件筛选出来,最后再参照匹配出来的连接条件生成需要显示排序的innerkeys。
(3) hash_inner_and_outer函数。
顾名思义,hash_inner_and_outer函数的主要作用就是建立HashJoin的路径,在distribute_restrictinfo_to_rels函数中已经判断过一个约束条件是否适用于Hashjoin。因为Hashjoin要建立哈希表,至少有一个适用于Hashjoin的连接条件存在才能使用HashJoin,否则无法创建哈希表。
3) 路径筛选
至此为止已经生成了物理连接路径Hashjoin、NestLoop、MergeJoin,那么现在就是要根据他们生成过程中计算的代价去判断是否是一条值得保存的路径,因为在连接路径阶段会生成很多种路径,并会生成一些明显比较差的路径,这时候筛选可以帮助做一个基本的检查,能够节省生成计划的时间。因为如果生成计划的时间太长,即便选出了“很好”的执行计划,那么也是不能够接受的。
add_path为路径筛选主要函数。代码如下:
switch (costcmp) {
case COSTS_EQUAL:
outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
PATH_REQ_OUTER(old_path));
if (keyscmp == PATHKEYS_BETTER1) {
if ((outercmp == BMS_EQUAL || outercmp == BMS_SUBSET1) &&
new_path->rows <= old_path->rows)
//新路径代价和老路径相似,PathKeys要长,需要的参数更少
//结果集行数少,故接受新路径放弃旧路径
remove_old = true; /* new dominates old */
} else if (keyscmp == PATHKEYS_BETTER2) {
if ((outercmp == BMS_EQUAL || outercmp == BMS_SUBSET2) &&
new_path->rows >= old_path->rows)
//新路径代价和老路径相似,pathkeys要短,需要的参数更多
//结果集行数更多,不接受新路径保留旧路径
accept_new = false; /* old dominates new */
} else {
if (outercmp == BMS_EQUAL) {
//到这里,新旧路径的代价、pathkeys、路径参数均相同或者相似
//如果新路径返回的行数少,选择接受新路径,放弃旧路径
if (new_path->rows < old_path->rows)
remove_old = true; /* new dominates old */
//如果新路径返回行数多,选择不接受新路径,保留旧路径
else if (new_path->rows > old_path->rows)
accept_new = false; /* old dominates new */
//到这里,代价、pathkeys、路径参数、结果集行数均相似
//那么就严格规定代价判断的范围,如果新路径好,则采用新路径,放弃旧路径
else {
small_fuzzy_factor_is_used = true;
if (compare_path_costs_fuzzily(new_path, old_path, SMALL_FUZZY_FACTOR) ==
COSTS_BETTER1)
remove_old = true; /* new dominates old */
else
accept_new = false; /* old equals or
* dominates new */
}
//如果代价和pathkeys相似,则比较行数和参数,好则采用,否则放弃
} else if (outercmp == BMS_SUBSET1 &&
new_path->rows <= old_path->rows)
remove_old = true; /* new dominates old */
else if (outercmp == BMS_SUBSET2 &&
new_path->rows >= old_path->rows)
accept_new = false; /* old dominates new */
/* else different parameterizations, keep both */
}
break;
case COSTS_BETTER1:
//所有判断因为新路径均好于或者等于旧路径
//则接受新路径,放弃旧路径
if (keyscmp != PATHKEYS_BETTER2) {
outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
PATH_REQ_OUTER(old_path));
if ((outercmp == BMS_EQUAL || outercmp == BMS_SUBSET1) &&
new_path->rows <= old_path->rows)
remove_old = true; /* new dominates old */
}
break;
case COSTS_BETTER2:
//所有判断因素旧路径均差于或者等于新路径
//则不接受新路径,保留旧路径
if (keyscmp != PATHKEYS_BETTER1) {
outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
PATH_REQ_OUTER(old_path));
if ((outercmp == BMS_EQUAL || outercmp == BMS_SUBSET2) &&
new_path->rows >= old_path->rows)
accept_new = false; /* old dominates new */
}
break;
default:
/*
* can't get here, but keep this case to keep compiler
* quiet
*/
break;
}

浙公网安备 33010602011771号