Reputation: 3105
I have this query(of course with couple joins across tables and some views which I will call x for simplicity).
select * from x
-> returns in 10 sec, still acceptable,
fairly heavy on joins and lot of dataselect * from x where userid = 1
-> returns in 0-1 sec,
good enoughCase 3 : using SP : if @userid = -1 select * from x else select
from x where userid = @userid
-> now calling sp with paramenter userid 1 should return on 0-1 sec as it should be comparable to case 2 but in fact it returns in
10
sec.
Now, parameter masking OR WITH RECOMPILE on sp OR OPTION
(recompile) on query with where clause doesn't help, What makes the
SP run faster with userid = something
is putting OPTION(recompile)
on the first part of the SP ie on the query without where clause. :
if @userid = -1 select * from x option
(recompile) else select * from x where userid = @userid
Any explanation?
I can guess earlier it was using optimization based of query without where clause even for the query with where clause, but why is that?
Upvotes: 1
Views: 124
Reputation: 1269873
Stored procedures cache execution plans, so they don't have the overhead of recompiling a query every time the SP is called. This is particularly important when using stored procedures for transactions. It is much less important whent the queries are running for several seconds.
When a query takes parameters the stored procedure must decide what values to optimize for. I am guessing that your SQL Server recognizes the two queries as being identical, and is using the same cached plan for them. It is optimizing the plan based on the first query. This is speculation, but it would explain what you are seeing.
You can readily fix this with the following version of the query:
select *
from x
where @userid = -1 or userid = @userid
option (recompile)
Upvotes: 1