Usual suspects:
- constants in adhoc, parameters in code
- mismatch of data types in code
- parameter sniffing
Point 1: the optimiser can choose the best plan for the constants.
Change the constants = change the plan. A parametrised plen is resuable
Point 2 will introduce implicit conversions because of datatype precedence
eg varchar column compared to nvarchar parameter
Point 3: use parameter masking or OPTIMISE FOR UNKNOWN
Edit: To test: run stored proc, run sp_updatestats, run again. This will invalidate cached plans which is better then clearing plan cache
Edit: after jcolebrand's comment
You can disable sniffing several ways. The main 3 are
- RECOMPILE. This is silly IMO.
- OPTIMIZE (sic) FOR UNKNOWN
- Parameter masking
Parameter masking:
DECLARE @MaskedParam varchar(10)
SELECT @MaskedParam = @SignaureParam
SELECT...WHERE column = @MaskedParam
Masking and the OPTIMIZE hint have the same effect (maybe for different reasons). That is, the optimiser has to use statistics and data distribution (Note: still under testing by Mark Storey-Smith) evaluate the parameters on their own merits ? , rather than what they were last call. The optimiser can recompile or not. SQL Server 2005 added statement level recompilation so there was less impact
Now, why a plan with "sniffed" parameters is "sticky" compared to masked/"unknown" parameters, I'm not sure.
I've used parameter masking since SQL Server 2000 for all but the simplest code. I've noted that it is liable to happen with more complex code. And at my old job I has some report procs that I could change the plan parameter defaults. I reckon the "cargo cult" approach was easier than a support call.
Edit 2, 12 Oct 2011, after some chat
Parameter masking and OPTIMISE FOR UNKNOWN have the same effect as far as I can tell
The hint is cleaner than masking but was added with SQL Server 2008.
Parameter sniffing happens at compile time.
WITH RECOMPILE generates a new plan each execution. This means a poor choice of defaults will influence the plan. At my last job, I could demonstrate this easily with some report code: changing parameter defaults altered the plan regardless of supplied parameters.
This MS Connect article is interesting: Suboptimal index usage within stored procedure (mentioned in one of the SO answers below)
- Bob Beauchemin mentions it too
Outstanding issues
Does sniffing still apply with WITH RECOMPILE? That is, if the optimiser knows to discard the plan does it aim for re-use?
Why are sniffed plans "sticky"?
Links from SO:
This issue is called parameter sniffing.
Later versions of SQL Server give you more options in dealing with it such as OPTION (RECOMPILE)
or OPTIMIZE FOR
hints.
You might try declaring variables in the stored procedure, assigning the parameter values to the variables and using the variables in place of the parameters as it sounds as though most of the time you are getting a reasonably satisfactory plan.
Normally the most catastrophically bad plans are those compiled for parameters with very high selectivity but ran with parameters with low selectivity.
Assuming the plan generated is more robust with this approach and satisfactory for all parameter values then the advantage of this approach over that suggested by JNK is that it does not incur a compilation cost for every call.
The disadvantage is that for some executions run time might be greater than for a plan tailored specifically for those parameter values so it is a trade off of compile time vs execution time.
Best Answer
You have to refer to DMV's for extracting such information.
sys.dm_exec_cached_plans
,sys.dm_exec_sql_text
andsys.dm_exec_query_plan
are the ones to look into.Especially
sys.dm_exec_query_plan
DMF will return the plan for a given batch or procedure (along with the "subplans" for each query comprising the batch).Note: Restarting sql server will flush out all dmv data.
Example :
--- Check the DMV's for cached query plan
Note : You can do many cool things by digging into Plan cache as described by Jonathan here. Also refer to DMVs for Query Plan Metadata