与参数一起使用时如何优化"OR"子句的使用(SQL Server 2008)

Mey*_*sam 8 sql-server indexing performance clause

我想知道是否有任何明智的方法来重写以下查询,以便优化器使用列上的索引?

Create Procedure select_Proc1
    @Key1 int=0,
    @Key2 int=0
As
BEGIN
    Select key3
    From Or_Table
    Where (@key1 =0 OR Key1 =@Key1) AND
          (@key2 =0 OR Key2 =@Key2)
END
GO
Run Code Online (Sandbox Code Playgroud)

即使WHERE子句中的列被索引覆盖,SQL Server也无法使用这些索引.这提出了一个问题,即是否有任何东西"阻止"索引的使用.这个问题的答案是肯定的 - 罪魁祸首是参数和"或"条件.索引不包含这些参数,这意味着SQL Server无法使用任何索引来评估"@ key1 = 0"(同样适用于@ key2 = 0的条件).实际上,这意味着SQL Server无法使用索引来评估子句"@ key1 = 0 OR Key1 = @ key1"(因为"OR"子句是两个条件所涵盖的行的并集).同样的原则也适用于其他条款(re.key2).这导致SQL Server得出结论,没有索引可用于提取行,使SQL Server能够利用下一个最佳方法 - 聚簇索引扫描

如您所见,如果WHERE子句中的谓词为"OR",则SQL优化器将不使用列上的索引.针对此问题的一种解决方案是使用IF子句为所有可能的参数组合分隔查询.

请阅读这篇简短的文章,以便更好地了解问题:http://www.sql-server-performance.com/articles/per/optimize_or_clause_p1.aspx

现在我的问题是,如果可能的组合只有三到四个,我们该怎么办?为每个组合编写单独的查询似乎不是一个合理的解决方案.这个问题还有其他解决方法吗?

Qua*_*noi 12

SQL Server在优化OR谓词方面不是很好.

用这个:

SELECT  key3
FROM    or_table
WHERE   @key1 = 0
        AND @key2 = 0
UNION ALL
SELECT  key3
FROM    or_table
WHERE   @key1 = 0
        AND @key2 <> 0
        AND key2 = @key2
UNION ALL
SELECT  key3
FROM    or_table
WHERE   @key2 = 0
        AND @key1 <> 0
        AND key1 = @key1
UNION ALL
SELECT  key3
FROM    or_table
WHERE   @key1 <> 0
        AND @key2 <> 0
        AND key1 = @key1
        AND key2 = @key2
Run Code Online (Sandbox Code Playgroud)

SQL Server 将在执行查询之前查看变量的值,并优化冗余查询.

这意味着实际只会执行四个查询.

  • 这是唯一的方法吗?如果查询更复杂(涉及更多的OR子句),该怎么办? (2认同)

Dew*_*wfy 5

MSSQL 2008有条件简化的优化语法,这里是

 Where (@key1 =0 OR Key1 =@Key1) AND
      (@key2 =0 OR Key2 =@Key2) option(recompile)
Run Code Online (Sandbox Code Playgroud)

这将优化常量的使用