SQL中的条件WHERE语句使用索引扫描而不是索引查找

SQL中的条件WHERE语句使用索引扫描而不是索引查找,sql,sql-server,indexing,conditional,Sql,Sql Server,Indexing,Conditional,考虑以下代码: DECLARE @TaskId int; SET @TaskId = 594725; SELECT Report.Amount FROM Report WHERE Report.TaskId = @TaskId; SELECT Report.Amount FROM Report WHERE (@TaskId = -1 OR Report.TaskId = @TaskId); 我在表报表上有一个非聚集索引,其列TaskId已索引。 第一个选择使用带有索引搜索的索引,但由于@T

考虑以下代码:

DECLARE @TaskId int;
SET @TaskId = 594725;

SELECT Report.Amount FROM Report WHERE Report.TaskId = @TaskId;

SELECT Report.Amount FROM Report WHERE (@TaskId = -1 OR Report.TaskId = @TaskId);
我在表报表上有一个非聚集索引,其列TaskId已索引。 第一个选择使用带有索引搜索的索引,但由于@TaskId变量的条件检查,第二个选择返回到索引扫描。有没有办法进行条件检查(例如,@TaskId是一个过滤器,-1应该返回所有行),并且仍然让查询使用索引查找

尝试:

IF (@TaskId = -1)
    SELECT Report.Amount FROM Report
ELSE
    SELECT Report.Amount FROM Report WHERE Report.TaskId = @TaskId
当@TaskId=-1时,它当然不会进行索引查找,因为它只会读取所有数据

更新:
查看此页面-动态搜索是常见的情况。
您应该注意的是执行计划缓存,因为当您从一组“可选”参数切换到另一组参数时,您可能会遇到性能不佳的问题—因此,您可能最终使用了较差的执行计划,从而导致性能不佳。在这种情况下,您需要考虑使用选项(重新编译)提示,以便每次生成新的计划,这将是该特定参数集的最佳方案。不过,请完整地查看这篇文章。

试试:

IF (@TaskId = -1)
    SELECT Report.Amount FROM Report
ELSE
    SELECT Report.Amount FROM Report WHERE Report.TaskId = @TaskId
当@TaskId=-1时,它当然不会进行索引查找,因为它只会读取所有数据

更新:
查看此页面-动态搜索是常见的情况。

您应该注意的是执行计划缓存,因为当您从一组“可选”参数切换到另一组参数时,您可能会遇到性能不佳的问题—因此,您可能最终使用了较差的执行计划,从而导致性能不佳。在这种情况下,您需要考虑使用选项(重新编译)提示,以便每次生成新的计划,这将是该特定参数集的最佳方案。不过,请完整查看这篇文章。

谢谢,是的,这很有效。但是如果我有10个变量都需要条件检查(例如,一个带有过滤器的报表作为存储过程),那么代码就会失控。@brunsbe-请参阅我的编辑中的链接。值得一读。是的,很有趣的文章!但是重写使用动态sql的过程是一项相当艰巨的工作-(更好的解决方案(SQL Server似乎理解条件部分)在SQL2005中不起作用,因为选项(重新编译)提示未正确实现。谢谢,是的,可以。但是如果我有10个变量,所有这些变量都需要条件检查(例如,将筛选器作为存储过程的报告)然后代码就失去了控制。@Brunsbe-请参阅我的编辑中的链接。这很值得一读。是的,这篇文章很有趣!但是重写使用动态sql的过程是一项相当艰巨的工作。:-(更好的解决方案(sql Server似乎理解条件部分)在SQL2005中不起作用,因为有一个选项(重新编译)提示未正确实现。