暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 19C 一 连接分解 (改写 UNION ALL 中同一表张的重复的查询 )

原创 Asher.HU 2021-02-04
1925

5.11连接分解

在称为联接分解的基于成本的转换中,优化器可以分解UNION ALL查询分支中的常见计算


5.11.1连接分解的目的

UNION ALL 查询在数据库应用程序中很常见,尤其是在数据集成应用程序中。

通常,UNION ALL查询中的分支引用相同的基表如果没有UNION ALL联接分解,优化器将独立评估查询的每个分支,从而导致重复处理,包括数据访问和联接。

联接分解转换可以在UNION ALL分支之间共享通用计算避免对大的基表进行额外的扫描可以极大地提高性能。

 

5.11.2联接分解如何工作

连接分解可以分解多个表中的两个以上的UNION ALL分支。

通过示例可以最好地解释联接分解。

示例5-11 UNION ALL查询

下面的查询显示的四个表(查询t1t2t3,和t4)和两个UNION ALL分支:

SELECT t1.c1, t2.c2
FROM   t1, t2, t3
WHERE  t1.c1 = t2.c1 
AND    t1.c1 > 1
AND    t2.c2 = 2
AND    t2.c2 = t3.c2 
UNION ALL
SELECT t1.c1, t2.c2
FROM   t1, t2, t4
WHERE  t1.c1 = t2.c1 
AND    t1.c1 > 1
AND    t2.c3 = t4.c3

在前面的查询中,table t1出现在两个UNION ALL分支中,过滤谓词t1.c1 > 1和join谓词出现在两个分支中t1.c1 = t2.c1未经任何转换,数据库必须对表执行t1两次扫描和筛选,每个分支一次。

示例5-12因式查询

以下查询在示例5-11中使用联接分解对查询进行转换
SELECT t1.c1, VW_JF_1.item_2
FROM   t1, (SELECT t2.c1 item_1, t2.c2 item_2
            FROM   t2, t3
            WHERE  t2.c2 = t3.c2 
            AND    t2.c2 = 2                 
            UNION ALL
            SELECT t2.c1 item_1, t2.c2 item_2
            FROM   t2, t4 
            WHERE  t2.c3 = t4.c3) VW_JF_1
WHERE  t1.c1 = VW_JF_1.item_1 
AND    t1.c1 > 1

在这种情况下,由于表t1已分解,因此数据库仅执行一次表扫描和过滤t1如果t1很大,则该分解避免了t1两次扫描和过滤的巨大性能成本

注意:

如果UNION ALL查询中的分支具有使用该  DISTINCT   函数的子句,则联接分解无效。


5.11.3分解和联接顺序:方案

联接分解可以为联接订单创造更多可能性

示例5-13涉及五个表的查询

在以下查询中,视图V示例5-11中的查询相同

SELECT *
FROM   t5, (SELECT t1.c1, t2.c2
            FROM   t1, t2, t3
            WHERE  t1.c1 = t2.c1 
            AND    t1.c1 > 1 
            AND    t2.c2 = 2 
            AND    t2.c2 = t3.c2 
            UNION ALL
            SELECT t1.c1, t2.c2
            FROM   t1, t2, t4
            WHERE  t1.c1 = t2.c1 
            AND    t1.c1 > 1 
            AND    t2.c3 = t4.c3) V
WHERE  t5.c1 = V.c1
之前加入分解,数据库必须加入t1t2以及t3用加入他们之前t5

示例5-14从视图V分解t1

如果联接分解t1从视图中进行分解V,如以下查询所示,则数据库可以t1使用t5联接

SELECT *
FROM   t5, ( SELECT t1.c1, VW_JF_1.item_2
             FROM   t1, (SELECT t2.c1 item_1, t2.c2 item_2
                         FROM   t2, t3
                         WHERE  t2.c2 = t3.c2
                         AND    t2.c2 = 2
                         UNION ALL
                         SELECT t2.c1 item_1, t2.c2 item_2
                         FROM   t2, t4
                         WHERE  t2.c3 = t4.c3) VW_JF_1 
             WHERE  t1.c1 = VW_JF_1.item_1 
             AND    t1.c1 > 1 )
WHERE  t5.c1 = V.c1


前面的查询转换将打开新的联接顺序。但是,联接分解规定了特定的联接顺序。例如,在前面的查询中,表t2t3显示UNION ALL在view 查询的第一分支中VW_JF_1数据库必须先t2联接t3然后才能与t1联接,该VW_JF_1视图未在视图中定义施加的加入顺序可能不一定是最佳加入顺序。因此,优化器使用基于成本的转换框架执行联接分解。优化器计算带或不带联接分解的计划成本,然后选择最便宜的计划。

示例5-15删除了视图定义的视图V中t1的因式分解

以下查询与示例5-14中的查询相同,但是删除了视图定义,因此更易于查看因式分解:

SELECT *
FROM   t5, (SELECT t1.c1, VW_JF_1.item_2
            FROM   t1, VW_JF_1
            WHERE  t1.c1 = VW_JF_1.item_1
            AND    t1.c1 > 1)
WHERE  t5.c1 = V.c1


5.11.4外部联接的因式分解:方案

该数据库支持外部联接反联接半联接的联接分解,但仅适用于此类联接中的右边表(从表)

例如,加入分解可以将以下UNION ALL由上分解查询t2

SELECT t1.c2, t2.c2
FROM   t1, t2
WHERE  t1.c1 = t2.c1(+) 
AND    t1.c1 = 1
UNION ALL
SELECT t1.c2, t2.c2
FROM   t1, t2
WHERE  t1.c1 = t2.c1(+) 
AND    t1.c1 = 2

以下示例显示了转换。t2现在,不再出现在UNION ALL子查询分支中。

SELECT VW_JF_1.item_2, t2.c2
FROM   t2, (SELECT t1.c1 item_1, t1.c2 item_2
            FROM   t1
            WHERE  t1.c1 = 1
            UNION ALL
            SELECT t1.c1 item_1, t1.c2 item_2
            FROM   t1
            WHERE  t1.c1 = 2) VW_JF_1
WHERE  VW_JF_1.item_1 = t2.c1(+)

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论