Oceanbase查询改写:全外连接改写

概述

通常情况下,执行引擎无法支持不含equal连接条件的全外连接查询。为此,Oceanbase中定义了全外连接改写规则,能够将上述查询转换成通过union all操作联合起来的两个子查询,为这类场景提供了支持。

基本原理

考虑如下情况:

SELECT t1.c2, t2.c2 FROM t1 FULL JOIN t2 ON t1.c1 != t2.c1

上述全连接查询的连接条件中不包含equal条件,可以将其分解由union all操作联合起来的外连接查询和反连接查询,如下所示:

(SELECT t1.c2, t2.c2 FROM t1 LEFT JOIN t2 ON t1.c1 != t2.c1) 
    UNION ALL (SELECT NULL, t2.c2 FROM t2 ANTI JOIN t1 ON t1.c1 != t2.c1) 
代码解析

全外连接改写规则的入口为ObTransformFullOuterJoin::transform_one_stmt,该函数会调用transform_full_outer_join函数执行改写。后者会遍历from子句中的表,然后对其中的join表调用recursively_eliminate_full_join递归地进行判断和改写,执行流程如下:

  1. 调用check_full_nl_valid函数检查当前层级是否可以进行改写,仅当连接条件中不包含由左右两表的列构成的equal条件时才执行改写。

  1. 调用create_view_for_full_nl_join函数将full join表转化为由union all语句构成的视图表。

  1. 调用update_stmt_exprs_for_view函数将父查询语句中的原full join表替换为视图表,并更新相关列依赖。

create_view_for_full_nl_join函数负责为能够改写的full join表创建对应的视图表,执行流程如下:

  1. 调用create_left_outer_join_stmt使用查询语句和full join表创建左连接查询语句,其中full join的左表作为外表,右表作为内表(即保持原顺序不变)。

  1. 调用create_left_anti_join_stmt使用前一步得到的左连接查询语句创建反连接查询语句,其中内表作为from表,外表作为anti join的右表(即左右顺序交换)。

  1. 使用前两步得到的语句创建一条union all查询语句,然后将其作为视图表添加到父查询中。

create_left_anti_join_stmt函数会调用switch_left_outer_to_semi_join函数将拷贝的左连接语句转换为反连接语句,后者会调用create_select_items_for_semi_join函数为其更新select列,对于原来左查询语句中属于外表部分的select列,需要使用null表达式替代(因为被转成了anti join的右表)。另外,对于原来左查询语句中的外表,如果其本身也是join表,则需要为其创建视图表,然后用视图表作为anti join的右表。如果连接条件中包含仅使用右表列的条件(如t1.c2 <> 0),则需要将其下推到右表视图中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值