请考虑以下问题:
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=@ResourceId
或AND AssetId=@AssetId
构建查询字符串,具体取决于哪个变量为null。 或
IF @ResourceId IS NULL BEGIN /* query 1 */ ELSE /* query 2 */ END
有没有其他方法SQL可以使用正确的索引,具体取决于哪个变量为NULL?
答案 0 :(得分:0)
当您在where where条件下使用函数或大小写时,SQL Server不会使用索引。 SQL Server必须运行函数或计算的case语句,然后检查条件。
我建议为ResourceId,AssetId和DateEvent列创建一个索引。