1

在 WHERE 子句中使用像这样的条件 Table.Column = @Param OR @Param IS NULL 它不对列使用 INDEX。

是真的吗,如果是这样,那么如何编写这种也使用 INDEX 的查询

查询示例

SELECT Col1, Col2 ...
FROM Table
WHERE (Col1 = @col OR @col IS NULL)
AND   (Col2 = @col2 OR @col2 IS NULL)
AND   (Col3 = @col3 OR @col3 IS NULL)

任何帮助。

4

4 回答 4

5

不幸的是,执行计划的生成并不像您期望的那样。

对于该单个查询,将创建一个计划。在创建该计划时,选择并固定要使用的索引。始终使用相同的计划、相同的索引等参数并不重要。

优化者试图找到适合所有可能性的最佳计划,但由于这种查询的性质,没有一个。您根本没有使用索引的计划所产生的特征。


解决方案是使用动态 SQL。这感觉很不整洁,但是如果您使用带有 的参数化查询sp_executesql,它实际上可以非常结构化,并且非常高效。

这是关于该主题的一篇非常有用的文章的链接: 动态搜索

它非常深入,但它解决这个问题的一种非常健壮的方法。

于 2012-05-30T12:17:57.233 回答
0
SELECT Col1, Col2 ...
FROM Table
WHERE EXISTS(
    SELECT Col1, Col2, Col3
    INTERSECT
    SELECT @col, @col2, @col3)

直觉上,这似乎应该表现得很糟糕,但是 SQL Server 的查询优化器知道如何给予INTERSECT特殊处理,并在内部将其转换为(伪 SQL)

SELECT Col1, Col2 ...
FROM Table
WHERE (Col1, Col2, Col3) IS (@col, @col2, @col3)

正如您在查询计划中看到的那样。如果您在这些列上有索引,它们可以并且确实会被使用。

我最初是从 Paul White 的Undocumented Query Plans: Equality Comparisons博客文章中挑选出来的,这可能是一个有趣的进一步阅读。

于 2014-07-25T10:15:41.363 回答
-1

为什么不试试这个:

SELECT Col1, Col2 ...
FROM Table
WHERE Col1 = IsNull(@col,Col1)
AND Col2 = IsNull(@col2,Col2)
AND Col3 = IsNull(@col3,Col3)

关于您的问题:您的查询分析器说它不使用 column1,2,3 上的索引?您为所有 3 列创建了索引?然后它应该使用它而不管其他OR IS NULL

于 2012-05-30T12:17:18.073 回答
-1

尝试在所有 where 子句列上建立索引,并尝试使用更结构化的查询,如下所示:

SELECT Col1, Col2 ... 
FROM Table 
WHERE Col1 = **COALESCE**(@col,Col1)
AND Col2 = **COALESCE**(@col2,Col2)
AND Col3 = **COALESCE**(@col3,Col3)

COALESCE() 函数返回第一个非空参数,因此如果 STATUS 为 NULL,它将返回 ''。

于 2012-05-30T13:07:50.830 回答