代码之家  ›  专栏  ›  技术社区  ›  Alex

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

  •  -1
  • Alex  · 技术社区  · 7 年前

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

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

    存在 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表示不同的表,没有重复的表。

    2 回复  |  直到 7 年前
        1
  •  1
  •   S3S    7 年前

    太长了,无法评论。

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

    • 参数嗅探 @Date . 尝试对这个值进行编码,看看是否仍然得到相同的慢度
    • 没有覆盖指数 P.OTHER_ID P.DATE P.ID SA.ID 这将导致对这些谓词进行表扫描
    • 上述非最佳列的索引(包括太多列等)
    • 使用 LOWER 函数在没有区分大小写排序规则的数据库上运行(大多数数据库没有区分大小写排序规则,尽管此函数不会降低速度)
    • 缓存中的查询计划不正确。尝试添加 OPTION (RECOMPILE) 在底部,所以 you get a new query plan

    由于您的查询超时, try including the estimated execution plan 把它贴在 past the plan

        2
  •  0
  •   Alex    7 年前

    我发现放了2个球 EXISTS WHERE UNION 并保持 在单独的查询中。最终结果如下所示:

    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'
        )