使用可能为空的变量进行过滤时未使用索引

时间:2014-07-22 09:43:22

标签: sql-server indexing null

请考虑以下问题:

Declare @ResourceId int, @AssetId int, @Start datetime, @Stop datetime

SELECT someFields FROM History
WHERE History.DateEvent BETWEEN @Start AND @Stop
AND (@ResourceId IS NULL OR History.ResourceId = @ResourceId)
AND (@AssetId IS NULL OR History.AssetId = @AssetId)

此查询仅使用有效的@ResourceId或有效的@AssetId调用,而不是两者都调用。

History上,ResourceId + DateEvent上有一个索引,AssetId + DateEvent上有另一个索引。

问题是即使@ResourceId是Null,sql server会尝试运行OR之后的内容,因此,当我检查执行计划时,我的索引都没有被使用。

我尝试将OR替换为:

AND ResourceId=coalesce(@ResourceId, ResourceId)

甚至:

AND ResourceId=CASE WHEN @ResourceId IS NULL THEN ResourceId ELSE @ResourceId END

但无济于事。我能想到的唯一方法就是使用正确的索引:

  • 使用AND ResourceId=@ResourceIdAND AssetId=@AssetId构建查询字符串,具体取决于哪个变量为null。

  • 换行IF @ResourceId IS NULL BEGIN /* query 1 */ ELSE /* query 2 */ END

有没有其他方法SQL可以使用正确的索引,具体取决于哪个变量为NULL?

1 个答案:

答案 0 :(得分:0)

当您在where where条件下使用函数或大小写时,SQL Server不会使用索引。 SQL Server必须运行函数或计算的case语句,然后检查条件。

我建议为ResourceId,AssetId和DateEvent列创建一个索引。