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

cod*_*net 11 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

)
Run Code Online (Sandbox Code Playgroud)

但是如果我使用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))
)
Run Code Online (Sandbox Code Playgroud)

use*_*721 6

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

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

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

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

干杯,

安德烈·拉涅利


ype*_*eᵀᴹ 3

查询计划还受到表中行数的影响。表中有多少行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    
)
Run Code Online (Sandbox Code Playgroud)

或(针对 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
)
Run Code Online (Sandbox Code Playgroud)