sql - 简单的更改会导致 SQL 查询执行时间急剧增加

标签 sql sql-server tsql execution-time sql-execution-plan

我在我的 Microsoft SQL Server (2012 Express) 数据库上运行以下 SQL 查询,它运行良好,执行时间不到一秒:

SELECT
  StringValue, COUNT(StringValue)
FROM Attributes
WHERE
  Name = 'Windows OS Version'
  AND StringValue IS NOT NULL
  AND ProductAssociation IN (
    SELECT ID
    FROM ProductAssociations
    WHERE ProductCode = 'MyProductCode'
  )
GROUP BY StringValue

我在内部查询中添加了一个过滤器,它继续正常工作,返回的结果略少(如预期的那样)并且执行时间不到一秒。

SELECT
  StringValue, COUNT(StringValue)
FROM Attributes
WHERE
  Name = 'Windows OS Version'
  AND StringValue IS NOT NULL
  AND ProductAssociation IN (
    SELECT ID
    FROM ProductAssociations
    WHERE ProductCode = 'MyProductCode'
    AND ID IN (
      SELECT A2.ProductAssociation
      FROM Attributes A2
      WHERE A2.Name = 'Is test' AND A2.BooleanValue = 0
    )
  )
GROUP BY StringValue

但是当我添加一个标志变量使我能够在内部查询中“打开/关闭”过滤器,并将标志设置为零时,查询似乎无限期地执行(我离开了它运行了大约 5 分钟然后强制取消):

DECLARE @IsTestsIncluded bit
SET @IsTestsIncluded = 0

SELECT
  StringValue, COUNT(StringValue)
FROM Attributes
WHERE
  Name = 'Windows OS Version'
  AND StringValue IS NOT NULL
  AND ProductAssociation IN (
    SELECT ID
    FROM ProductAssociations
    WHERE ProductCode = 'MyProductCode'
    AND (
      @IsTestsIncluded = 1
      OR
      ID IN (
        SELECT A2.ProductAssociation
        FROM Attributes A2
        WHERE A2.Name = 'Is test' AND A2.BooleanValue = 0
      )
    )
  )
GROUP BY StringValue

为什么?我做错了什么?我发誓我过去使用过这种模式没有问题。

(当我在上面的最终查询中设置@IsTestsIncluded = 1时,过滤器被跳过并且执行时间正常 - 延迟仅发生在@IsTestsIncluded = 0)


编辑

根据 Joel 在评论中的要求,这是第一个查询的执行计划:

Execution plan for first query

这是第二个查询的执行计划:

enter image description here

(我无法发布第三个查询的执行计划,因为它永远不会完成 - 除非有另一种方法可以在 SSMS 中获取它?)

最佳答案

Why? What am I doing wrong?

您正在尝试根据变量编译需要满足多个不同条件的查询。优化器必须提出在两种 情况下都有效的一个计划。

尽量避免这种情况,就像避免瘟疫一样。只需发出两个查询,一个针对一个条件,一个针对另一个条件,这样优化器就可以自由地分别优化每个查询,并编译针对每种情况的最佳执行计划。

对该主题的长时间讨论,以及替代方案和利弊:Dynamic Search Conditions in T‑SQL

关于sql - 简单的更改会导致 SQL 查询执行时间急剧增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31346030/

相关文章:

sql-server - SQL Server Select 和 Update 在同一个语句中?

sql - 为什么 SQL Server 强制我删除表才能将字段从 DateTime 更改为 DateTime2(3)?

sql - 使用 SQL 拆分 URL 并添加到数据库

sql-server - SQL Server 存储过程返回表,每个用户的唯一性计数

php - 如何在 CodeIgniter 中执行我的 SQL 查询

php - 如何进行复杂的 SQL 查询

c# - Oracle 数据库 TNS 键 'data source' 的值长度超出了它的限制 '128'

sql - 检查数据库中的 NULL boolean 值

SQL - 两列不同,第三列汇总值

c# - 通过过程调用时 ADO.NET 中的整数输出参数空问题