在使用类似条件的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)
任何帮助。
答案 0 :(得分:5)
不幸的是,执行计划的生成并不像您期望的那样。
对于该单个查询,将创建单个计划。在创建该计划时,将选择并修复要使用的索引。无论您提供什么参数,始终使用相同的计划,相同的索引等都无关紧要。
otpimiser 尝试找到适合所有事件的最佳方案,但根据此类查询的性质,没有一个。计划产生的特征,你根本没有使用索引。
解决方案是使用动态SQL。这感觉不整洁,但如果您使用sp_executesql
的参数化查询,它实际上可以非常结构化,并且非常高效。
以下是关于此主题的非常有用的文章的链接:dynamic search
这是非常深入的,但 是解决此问题的一种非常强大的方法。
答案 1 :(得分: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博客文章中选择的,这可能是一个有趣的进一步阅读。
答案 2 :(得分:-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
答案 3 :(得分:-1)
尝试在所有where子句列上建立索引,并尝试使用更具结构化的查询,如下所示:
SELECT Col1, Col2 ...
FROM Table
WHERE Col1 = **COALESCE**(@col,Col1)
AND Col2 = **COALESCE**(@col2,Col2)
AND Col3 = **COALESCE**(@col3,Col3)
COALESCE()函数返回第一个非null参数,因此如果STATUS为NULL,它将返回''。