Sql 为什么多个存在会打断一个查询

Sql 为什么多个存在会打断一个查询,sql,sql-server,exists,Sql,Sql Server,Exists,我试图包含一个新表,其中包含需要检查并包含在存储过程中的值。语句1是需要检查的现有表,而语句2是要检查的新表 我目前有2个存在条件,它们独立运行并产生我期望的结果。我的意思是,如果我把语句1注释掉,那么语句2就会起作用,反之亦然。当我把它们放在一起时,查询没有完成,没有错误,但它会超时,这是出乎意料的,因为每条语句只需要几秒钟 我知道可能有更好的方法来做这件事,但在我做之前,我想知道为什么我不能像这样做多个exists语句?在WHERE子句中是否不存在多个条件 SELECT * FROM tab

我试图包含一个新表,其中包含需要检查并包含在存储过程中的值。语句1是需要检查的现有表,而语句2是要检查的新表

我目前有2个
存在
条件,它们独立运行并产生我期望的结果。我的意思是,如果我把语句1注释掉,那么语句2就会起作用,反之亦然。当我把它们放在一起时,查询没有完成,没有错误,但它会超时,这是出乎意料的,因为每条语句只需要几秒钟

我知道可能有更好的方法来做这件事,但在我做之前,我想知道为什么我不能像这样做多个exists语句?在
WHERE
子句中是否不存在多个
条件

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'
    )
)
编辑:我已包含查询详细信息。表1-5表示不同的表,没有重复的表

太长,无法评论

你的书面询问似乎是正确的。超时只能从执行计划中产生问题,但这里有一些可能发生的事情,或者您可以从中受益

  • @Date
    上进行参数嗅探。尝试对这个值进行编码,看看是否仍然得到相同的慢度
  • P.OTHER_ID
    P.DATE
    P.ID
    SA.ID
    上没有覆盖索引,这将导致对这些谓词进行表扫描
  • 上述非最佳列的索引(包括太多列等)
  • 当查询可能受益于并行性时,它是串行的
  • 在没有区分大小写排序规则的数据库上使用
    LOWER
    函数(大多数数据库没有区分大小写排序规则,尽管此函数不会降低速度)
  • 缓存中的查询计划不正确。请尝试在底部添加
    选项(重新编译)
    ,以便重新编译。当比较两个查询的速度以确保它们不使用缓存计划时,或者当另一个查询使用缓存计划时,一个查询不使用缓存计划时,也会执行此操作,这会使结果产生偏差

由于您的查询正在超时,请将其发布到我们的上,我发现在
中放置2
会使整个过程花费更长的时间。我发现它的修复方法是使用
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'
    )

不是我的反对票,但如果你的查询超时,我会检查执行计划,看看是什么让你的查询膨胀。您只发布了伪代码,这使得这非常困难。@scsimon我很惊讶查询本身。我已经包括了细节。你是对的,执行计划隐藏了子树的成本。事实证明,将这两个“存在”放在一起会大大提高所需的处理能力,并使计划的完成时间延长近50倍。然后我只需将其中一个转换为临时值,然后再执行另一个或进行适当调整。我发布了此问题的答案,但我发现联合是最有效的解决方案,这是确保安全的一种方法