使用哪种方法:JOINS的UNION vs LEFT JOINS

时间:2017-02-16 16:17:24

标签: sql oracle join left-join union

所以我目前有一个非常大的表,我需要经常查询。这个表有很多列和行,我需要根据放在2个虚拟表中的2个列表来过滤行,我希望结果与其中任何一个匹配

enter image description here

我正在执行一个获取结果的过程,但是我们的开发环境没有足够的样本大小来测试过程性能。所以现在我有两个选择。

  1. 使用LEFT JOINS执行此类操作

    SELECT GT.* FROM GiantTable GT 
        LEFT JOIN List1 L1 ON GT.X = L1.X 
        LEFT JOIN List2 L2 ON GT.Y = L2.Y 
    WHERE L1.X IS NOT NULL OR L2.Y IS NOT NULL
    
  2. 使用2个JOIN个查询和UNION结果

    SELECT GT.* FROM GiantTable GT JOIN List1 L1 ON GT.X = L1.X
    UNION
    SELECT GT.* FROM GiantTable GT JOIN List2 L2 ON GT.Y = L1.Y
    
  3. 我很确定第二名应该表现得更好但我想知道我是不是错了

2 个答案:

答案 0 :(得分:1)

UNION是有问题的,因为它需要从两个子查询的结果中过滤掉重复项。您应该能够使用EXISTS运算符和一对相关子查询获得不错的性能:

SELECT *
FROM GiantTable GT
WHERE (EXISTS (SELECT * FROM List1 L1 WHERE L1.X = GT.X))
   OR (EXISTS (SELECT * FROM List2 L2 WHERE L2.Y = GT.Y))

答案 1 :(得分:1)

你可以用

做得更好
select *
from   gianttable
where  x in (select x from L1) or y in (select y from L2)

修改

OP报告此版本比原始版本慢。这可能是真的,特别是如果xygianttable中编入索引(它们是各自列表中的主键,因此 在较小的列表中编入索引表)。阻碍OR条件中where运算符的因素 - 这意味着这两个条件都不能用作访问谓词。

还有一件事要尝试......索引应该真正有用。下面的查询等同于OP的首次尝试,也是我的第一次尝试(上图)和dasblinkenlight的解决方案。 (这是因为xy在各自的列表中都是PK,所以我们不需要在那里处理null。)

select * from gianttable where x in (select x from L1)
union all
select * from gianttable where y in (select y from L2) and x not in (select x from L1)