为什么多个 EXISTS 会破坏一个查询
Why do multiple EXISTS break a query
我正在尝试包含一个新的 table,其中包含需要检查并包含在存储过程中的值。语句 1 是需要检查的现有 table,而语句 2 是要检查的新 table。
我目前有 2 个 EXISTS
条件可以独立运行并产生我期望的结果。我的意思是,如果我注释掉声明 1,则声明 2 有效,反之亦然。当我将它们放在一起时,查询没有完成,没有错误,但它超时了,这是意外的,因为每个语句只需要几秒钟。
我知道可能有更好的方法来执行此操作,但在我这样做之前,我想知道为什么我似乎不能像这样执行多个 exists 语句? WHERE
子句中不应该有多个 EXISTS
条件吗?
SELECT *
FROM table1 S
WHERE
--Statement 1
EXISTS
(
SELECT 1
FROM table2 P WITH (NOLOCK)
INNER JOIN table3 SA ON SA.ID = P.ID
WHERE P.DATE = @Date AND P.OTHER_ID = S.ID
AND
(
SA.FILTER = ''
OR
(
SA.FILTER = 'bar'
AND
LOWER(S.OTHER) = 'foo'
)
)
)
OR
(
--Statement 2
EXISTS
(
SELECT 1
FROM table4 P WITH (NOLOCK)
INNER JOIN table5 SA ON SA.ID = P.ID
WHERE P.DATE = @Date
AND P.OTHER_ID = S.ID
AND LOWER(S.OTHER) = 'foo'
)
)
编辑: 我已经包含了查询详细信息。 Table 1-5代表不同的table,没有重复的table。
评论时间太长。
你写的查询似乎是正确的。超时只能从执行计划中解决,但这里有一些可能发生的事情,或者您可以从中受益。
@Date
上的参数嗅探。尝试硬编码这个值,看看你是否仍然得到同样的缓慢
P.OTHER_ID
或 P.DATE
或 P.ID
或 SA.ID
上没有覆盖索引,这将导致 table 扫描这些谓词
- 上述列的索引不是最佳的(包括太多列等)
- 您的查询是串行的,但它可能会受益于并行性。
- 在没有区分大小写排序规则的数据库上使用
LOWER
函数(大多数没有,尽管此函数不会减慢速度)
- 您在缓存中有一个错误的查询计划。尝试在底部添加
OPTION (RECOMPILE)
所以 you get a new query plan。在比较两个查询的速度时也会这样做,以确保它们没有使用缓存的计划,或者一个没有使用而另一个查询会扭曲结果。
由于您的查询超时,try including the estimated execution plan and post it for us at past the plan
我发现将 2 EXISTS
置于 WHERE
条件下会使整个过程花费更长的时间。我发现修复的是使用 UNION
并将 EXISTS
保留在单独的查询中。最终结果如下所示:
SELECT *
FROM table1 S
WHERE
--Statement 1
EXISTS
(
SELECT 1
FROM table2 P WITH (NOLOCK)
INNER JOIN table3 SA ON SA.ID = P.ID
WHERE P.DATE = @Date AND P.OTHER_ID = S.ID
AND
(
SA.FILTER = ''
OR
(
SA.FILTER = 'bar'
AND
LOWER(S.OTHER) = 'foo'
)
)
)
UNION
--Statement 2
SELECT *
FROM table1 S
WHERE
EXISTS
(
SELECT 1
FROM table4 P WITH (NOLOCK)
INNER JOIN table5 SA ON SA.ID = P.ID
WHERE P.DATE = @Date
AND P.OTHER_ID = S.ID
AND LOWER(S.OTHER) = 'foo'
)
我正在尝试包含一个新的 table,其中包含需要检查并包含在存储过程中的值。语句 1 是需要检查的现有 table,而语句 2 是要检查的新 table。
我目前有 2 个 EXISTS
条件可以独立运行并产生我期望的结果。我的意思是,如果我注释掉声明 1,则声明 2 有效,反之亦然。当我将它们放在一起时,查询没有完成,没有错误,但它超时了,这是意外的,因为每个语句只需要几秒钟。
我知道可能有更好的方法来执行此操作,但在我这样做之前,我想知道为什么我似乎不能像这样执行多个 exists 语句? WHERE
子句中不应该有多个 EXISTS
条件吗?
SELECT *
FROM table1 S
WHERE
--Statement 1
EXISTS
(
SELECT 1
FROM table2 P WITH (NOLOCK)
INNER JOIN table3 SA ON SA.ID = P.ID
WHERE P.DATE = @Date AND P.OTHER_ID = S.ID
AND
(
SA.FILTER = ''
OR
(
SA.FILTER = 'bar'
AND
LOWER(S.OTHER) = 'foo'
)
)
)
OR
(
--Statement 2
EXISTS
(
SELECT 1
FROM table4 P WITH (NOLOCK)
INNER JOIN table5 SA ON SA.ID = P.ID
WHERE P.DATE = @Date
AND P.OTHER_ID = S.ID
AND LOWER(S.OTHER) = 'foo'
)
)
编辑: 我已经包含了查询详细信息。 Table 1-5代表不同的table,没有重复的table。
评论时间太长。
你写的查询似乎是正确的。超时只能从执行计划中解决,但这里有一些可能发生的事情,或者您可以从中受益。
@Date
上的参数嗅探。尝试硬编码这个值,看看你是否仍然得到同样的缓慢P.OTHER_ID
或P.DATE
或P.ID
或SA.ID
上没有覆盖索引,这将导致 table 扫描这些谓词- 上述列的索引不是最佳的(包括太多列等)
- 您的查询是串行的,但它可能会受益于并行性。
- 在没有区分大小写排序规则的数据库上使用
LOWER
函数(大多数没有,尽管此函数不会减慢速度) - 您在缓存中有一个错误的查询计划。尝试在底部添加
OPTION (RECOMPILE)
所以 you get a new query plan。在比较两个查询的速度时也会这样做,以确保它们没有使用缓存的计划,或者一个没有使用而另一个查询会扭曲结果。
由于您的查询超时,try including the estimated execution plan and post it for us at past the plan
我发现将 2 EXISTS
置于 WHERE
条件下会使整个过程花费更长的时间。我发现修复的是使用 UNION
并将 EXISTS
保留在单独的查询中。最终结果如下所示:
SELECT *
FROM table1 S
WHERE
--Statement 1
EXISTS
(
SELECT 1
FROM table2 P WITH (NOLOCK)
INNER JOIN table3 SA ON SA.ID = P.ID
WHERE P.DATE = @Date AND P.OTHER_ID = S.ID
AND
(
SA.FILTER = ''
OR
(
SA.FILTER = 'bar'
AND
LOWER(S.OTHER) = 'foo'
)
)
)
UNION
--Statement 2
SELECT *
FROM table1 S
WHERE
EXISTS
(
SELECT 1
FROM table4 P WITH (NOLOCK)
INNER JOIN table5 SA ON SA.ID = P.ID
WHERE P.DATE = @Date
AND P.OTHER_ID = S.ID
AND LOWER(S.OTHER) = 'foo'
)