简体   繁体   中英

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. 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. 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 ?

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.

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. Check out the article in full though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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