在SQL Server查询中UNION ALL vs OR条件

时间:2011-04-12 18:12:32

标签: sql sql-server

我必须根据表上的不存在条件选择一些行。如果我使用如下所示的union,它将在不到1秒的时间内执行。

SELECT 1 FROM dummyTable
WHERE NOT EXISTS
(

SELECT 1 FROM TABLE t
WHERE Data1 = t.Col1 AND Data2=t.Col2

UNION ALL

SELECT 1 FROM TABLE t
WHERE Data1 = t.Col2 AND Data2=t.Col1

)

但是如果我使用OR条件,则SQL服务器正在执行表惰性池时需要将近一分钟。有人可以解释一下吗?

SELECT 1 FROM dummyTable
WHERE NOT EXISTS
(

SELECT 1 FROM TABLE t
WHERE ( (Data1 = t.Col1 AND Data2=t.Col2) OR (Data1 = t.Col2 AND Data2=t.Col1))
)

3 个答案:

答案 0 :(得分:4)

问题在于您使用OR指定了两个适用于查询中单独表的条件。因此,非聚集索引查找必须返回大表中的大部分或全部行,因为OR逻辑意味着它们也可能匹配第二个表中的条件子句。

查看上面所有三个示例中的SQL执行计划,并注意从大表中查找非聚集索引的行数。最终结果可能只返回表中800,000行中的1,000或更少,但OR子句意味着该表的内容必须与第二个表中的条件交叉引用,因为OR表示最终可能需要它们查询输出。

根据您的执行计划,索引查找可能会拉出大表中的所有800,000行,因为它们也可能匹配第二个表中OR子句的条件。 UNION ALL是针对每个表的两个单独查询,因此索引查找只需输出可能与该查询条件匹配的较小结果集。

我希望这是有道理的。我在重构缓慢运行的SQL语句时遇到了相同的情况。

干杯,

安德烈拉尼瑞

答案 1 :(得分:2)

查询计划也受表中行数的影响。表t中有多少行?

您也可以尝试:

SELECT 1 FROM dummyTable
WHERE NOT EXISTS
(
  SELECT 1 FROM TABLE t
  WHERE Data1 = t.Col1 AND Data2=t.Col2
)
AND NOT EXISTS 
(    
  SELECT 1 FROM TABLE t
  WHERE Data1 = t.Col2 AND Data2=t.Col1    
)

或(针对SQL-Server更正)这将使用索引:

WITH tt AS                               <---- a temp table with 2 rows
( SELECT Data1 AS Col1, Data2 AS Col2
  UNION
  SELECT Data2 AS Col1, Data1 AS Col2
)
SELECT 1 FROM dummyTable
WHERE NOT EXISTS
(
  SELECT 1
  FROM TABLE t
    JOIN tt                      
      ON tt.Col1 = t.Col1 AND tt.Col2=t.Col2
)

答案 2 :(得分:1)

OR的使用可能导致查询优化器不再在第二个查询中使用索引。查看每个查询的说明,这将告诉您答案。