2010-11-10 75 views
4

我使用FULL OUTER JOIN连接了2个表,这需要6分钟的时间运行并提供输出。Oracle SQL全外连接

SELECT * 
FROM tab1 FULL OUTER JOIN tab2 
ON tab1.id = tab2.id 
; 

我没有使用LEFT OUTER联盟JOIN和RIGHT OUTER JOIN同样的事情。这个只需要15秒

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

UNION 

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

有谁知道为什么发生这种情况?

+3

你是否检查过这两个查询的查询计划? – 2010-11-10 18:37:35

+2

Oracle建议应避免使用传统(+)语法。使用更通用的ISO标准LEFT/RIGHT JOIN语法,因此更适合SO等论坛。 – sqlvogel 2010-11-11 13:36:41

回答

3

您可能在两个表中都有很多行,很少有共同的行,并且在有问题的列上没有索引。

+0

@MacKay,我没有索引,但我没有很多共同的列... – mahen 2010-11-10 21:33:36

0

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

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

对于您的查询,哪个计划的收益是Oracle

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不是我经常需要的东西,所以最近还没有回到基准测试。

2

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

+0

其实,两个结果集应该是相同的。完整的外连接将不会返回重复项,因为每组连接行只能被找到一次。如果OP使用了union all,那么每组连接的行将被返回两次。 – Allan 2010-11-11 14:19:38

+1

@Allan:“两个结果集应该是相同的”。只有当两个表都没有任何重复的行时,AND ID在至少一个表中才是唯一的。 – sqlvogel 2010-11-11 14:37:19

+0

好的,我可以看到这种情况是真的。我想,如果键不唯一,你必须使用具有三个查询的'union all'来准确地重新创建外连接(内连接和两个外连接,其中匹配集被删除)。 – Allan 2010-11-11 14:50:17