Detecting Possible Parameter Sniffing Occurences with DMV
Hi All,
Parameter Sniffing is a scenario which most DBAs had to handle at some point. Usually the main challenge is to detect it, as the toolkit to address it is well known and documented. To help in the detection phase, here's a rather simple query that will just report queries which have a large gap between their minimum and maximum resource consumption values (100 by default). Although not guaranteed parameter sniffing occurences, the content of the short list the query will return should receive a quick review : that means that a given plan has been executed with massively different resource usage, and one could assume that one same plan shouldn't be optimal over that whole range of situation.
By enabling the filter for Duration and resource consumption (CPU, IO or both) one can filter out the impact of blocking (which doesn' t increase resource consumption).
Looking at resultset's rowcount variance is advised, but TOP and Aggregates queries will have a stable rowcount that may mask a vastly different amount of data accessed to produce the result, so a lack of difference is not a reliable indicator (a large difference, on the other hand, is a further confirmation).
The 100 factor can easily be tweaked for finer or coarser grain detection depending on environments.
declare @cpufactor int
declare @iofactor int
declare @durationfactor int
/* parameter sniffing will usually lead to large CPU, IO and Duration increases.
checking duration only might fail to distinguish it from blocking problems*/
set @cpufactor=100 /* 0 disables*/
set @iofactor=100 /* 0 disables*/
set @durationfactor = 100 /* 0 disables*/
select
SUBSTRING(ST.text, (QS.statement_start_offset/2) + 1,
((CASE statement_end_offset
WHEN -1 THEN DATALENGTH(ST.text)
ELSE QS.statement_end_offset END
- QS.statement_start_offset)/2) + 1) AS statement_text ,
ST.text as 'full batch',
query_hash,
query_plan_hash,
*
from sys.dm_exec_query_stats AS QS
CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle) as ST
where
/*'strictly smaller than' will rule out any 0 values from resultset*/
@cpufactor * min_worker_time < max_worker_time
and
@iofactor * min_logical_reads < max_logical_reads
and
@durationfactor * min_elapsed_time < max_elapsed_time
Thanks,
Guillaume Fourrat
Escalation Engineer
Comments
- Anonymous
September 09, 2016
Nice post! Thks!