我必须根据表上的不存在条件选择一些行。如果我使用如下所示的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))
)
答案 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
的使用可能导致查询优化器不再在第二个查询中使用索引。查看每个查询的说明,这将告诉您答案。