简体   繁体   English

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

[英]Conditional WHERE statement in SQL uses Index Scan instead of Index Seek

Consider the following code: 考虑以下代码:

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);

I have a nonclustered index on the table Report with the column TaskId indexed. 我在表Report上有一个非聚集索引,其中TaskId列已建立索引。 The first SELECT uses the index with an INDEX SEEK but the second one falls back to an INDEX SCAN due to the conditional check of the @TaskId variable. 第一个SELECT使用带有INDEX SEEK的索引,但是第二个SELECT由于对@TaskId变量的条件检查而回退到INDEX SCAN Is there any way to have the conditional check (if eg the @TaskId is a filter and -1 should return all rows) and still get the query to use an INDEX SEEK ? 有什么方法可以进行条件检查(例如,如果@TaskId是过滤器,并且-1应该返回所有行),并且仍然使查询使用INDEX SEEK

Try: 尝试:

IF (@TaskId = -1)
    SELECT Report.Amount FROM Report
ELSE
    SELECT Report.Amount FROM Report WHERE Report.TaskId = @TaskId

When @TaskId = -1, of course it won't do an index seek as it will just be reading all the data. 当@TaskId = -1时,它当然不会执行索引查找,因为它将仅读取所有数据。

Update: 更新:
Check out this excellent article on this - dynamic search is a common scenario. 请查看这篇出色的文章 -动态搜索是一种常见的情况。
Something you should be aware of is execution plan caching as you could be experiencing bad performance when you switch from one set of "optional" parameters to another - hence you may end up using a poor execution plan, giving bad performance. 您应该意识到的是执行计划缓存,因为当您从一组“可选”参数切换到另一组“可选”参数时,您可能会遇到性能下降的情况-因此,您最终可能会使用较差的执行计划,从而导致性能下降。 In this case, you would want to consider using OPTION(RECOMPILE) hint so that it generates a plan fresh each time, which would be the best plan for that specific set of parameters. 在这种情况下,您可能要考虑使用OPTION(RECOMPILE)提示,以便它每次都会生成一个新鲜的计划,这将是针对该特定参数集的最佳计划。 Check out the article in full though. 不过,请查看全文。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM