Oracle SQL全外连接

4
我使用FULL OUTER JOIN连接了2个表格,这个操作花费了6分钟才能运行并输出结果。
SELECT * 
FROM tab1 FULL OUTER JOIN tab2
ON tab1.id = tab2.id
;

我使用左外连接和右外连接的UNION做了相同的事情。这只花了15秒钟。

SELECT *
FROM tab1, tab2
WHERE tab1.id (+) = tab2.id

UNION 

SELECT *
FROM tab1, tab2
WHERE tab1.id  = tab2.id (+)
;

有人知道这是为什么吗?


3
你是否已经检查了这两个查询的查询计划? - user359040
2
Oracle建议避免使用旧的(+)语法。使用ISO标准的LEFT / RIGHT JOIN语法,这种语法更为普遍理解,因此在像SO这样的论坛上更为适用。 - nvogel
4个回答

3

你可能在两个表中都有大量的行,共同的行数很少,并且相关列上没有索引。


2

检查执行计划。请记住,您指定的两个查询在逻辑上并不等价。第二个查询消除了重复行(UNION),但第一个查询没有。这可能是性能差异的部分解释。


实际上,两个结果集应该是相同的。全外连接不会返回重复项,因为每组连接行只会被找到一次。如果 OP 使用了 union all,则每组连接行将会被返回两次。 - Allan
1
@Allan:“两个结果集应该是相同的”。只有当两个表都没有重复行并且至少一个表中的id是唯一的时才成立。 - nvogel
好的,我可以看到那种情况是正确的。我猜,如果键不唯一,你需要使用union all和三个查询来准确地重新创建外连接(一个内连接和两个去除匹配集的外连接)。 - Allan

0

我在使用Oracle 9.2时遇到了这个问题。可以通过将FULL OUTER JOIN拆分为左外连接和右反连接(或其他方法)来解决它。

SELECT a.*, b.*
from tableA a
left outer join tableB b on (a.a = b.a)
union all
SELECT a.*, b.*
from tableA a
right outer join tableB b on (a.a = b.a)
where a.a is null

这基本上是您提供的查询,但使用 UNION ALL 并从查询的第二部分中删除重复项,而不是使用 UNION。有时我甚至无法获得性能,需要进一步拆分查询,但我不记得涉及什么了。

对我来说,情况似乎在 Oracle 10 中得到改善,但是 FULL OUTER JOIN 并不是我经常需要的东西,因此最近没有回过头去进行基准测试。


0

FULL OUTER JOIN与其他连接类型有所不同,因为无法选择单个主导表。

唯一能有效处理它的方法是使用MERGE JOIN,但是Oracle不会选择它。

Oracle为您的查询生成哪个计划?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接