Sunteți pe pagina 1din 4

Parameter sniffing

We can set off parameter sniffing at instance level with


A . From the code by adding some option
B. with the help of configuration manager (To enable trace flag - 7646)
SQL Server compiles the stored procedures using (sniffing) the parameters send
the first time the procedure is compiled and put it in plan cache. After that every
time the procedure executed again, SQL Server retrieves the execution plan from
the cache and uses it (unless there is a reason for recompilation). The potential
problem arises when the first time the stored procedure is executed, the set of
parameters generate an acceptable plan for that set of parameters but very bad for
other more common sets of parameters.

In the code itself we can setup parameter sniffing to off at instance


level for specific code
Options to overcome parameter sniffing
Workaround one add recompile

OPTION (RECOMPILE)

OPTION (OPTIMIZE FOR (@VARIABLE=VALUE))

OPTION (OPTIMIZE FOR (@VARIABLE UNKNOWN))

Use local variables

1.Workaround

: OPTION (Recompile)

- Every time the query or stored procedure is executed when it arrives to


the query marked with the OPTION(RECOMPILE), this query is recompiled using
the current parameters values.
- In this way the plan behaves well for any combination of parameters (is
statistics are good) but the overhead is recompilation of the query every
time
*/
--Alter SP
alter proc my_AddressSP (@city nvarchar(30))
as
select *
from Person.Address
where city=@city
option (recompile)
--Call it for "Seattle"
exec my_AddressSP 'Seattle'

--Call it for "Bothell"


exec my_AddressSP 'Bothell'

2. Workaround : OPTION (OPTIMIZE FOR (@VARIABLE=VALUE))

- Let's assume that this SP is called %99 percent for "Bothell" and only %1
percent for "Seattle"
- But if the first time it is called with "Seattle" paramater, after that all
"Bothell" queries run with undesired query plan
- If you have a workload like this, you can use OPTION (OPTIMIZE FOR
(@VARIABLE=VALUE)) workaround
- This option causes the compilation process to ignore the value for the specified
variable and use the specified value instead.
- Unlike the first workaround (Option(Recompile)), this option avoid the overhead
of recompiling the query every time.
*/
--Alter SP
Alter proc my_AddressSP (@city nvarchar(30))
as
select * from Person.Address
where city=@city
option (optimize for (@city='Bothell'))

Workaround : OPTION (OPTIMIZE FOR (@VARIABLE


UNKNOWN))
3.

- In this way SQL uses statistic densities instead of statistic histograms.


- So It estimates the same number of records for all paramaters
- The disadvantage is that some queries will use suboptimal plans because
densities are not precise enough as the statistic histogram.
*/ --Alter SP
Alter proc my_AddressSP (@city nvarchar(30))
as
select *

from Person.Address

where city=@city
option (optimize for (@city UNKNOWN))

--check the estimated number of rows. It's 34.1113 for every city
exec my_AddressSP 'Seattle'
exec my_AddressSP 'Bothell'

4. Workaround : Use local variable


- This workaround is very similar with previous one (OPTION (OPTIMIZE FOR
(@VARIABLE UNKNOWN)))
- when you assign the paramaters to local ones SQL Server uses statistic densities
instead of statistic histograms
- So It estimates the same number of records for all paramaters
- The disadvantage is that some queries will use suboptimal plans because
densities are not precise enough as the statistic histogram.
*/ --Alter SP
Alter proc my_AddressSP (@city nvarchar(30))
as
declare @city_x nvarchar(30)
set @city_x = @city
select *

from Person.Address

where city=@city_x

exec my_AddressSP 'Seattle'


exec my_AddressSP 'Bothell'

--drop sp
drop proc my_AddressSP

Parameter sniffing
Parameter sniffing can be set to off with help of trace flag.
We need to enable trace flag 7646
With DBCC trace on (7646)
And then we can verify with
Validate Trace Flag "7646" is ON -- DBCC TRACESTATUS (7646)

Setting Trace Flags Permanently in SQL Server?


We need to use SQL Server Trace Flag 7646 to help mitigate some full text blocking, but I was
dismayed to find that the trace flag "unset" itself, probably when the database server was rebooted.
I've used
DBCC TRACEON (7646, -1)

to set the trace flag and


DBCC TRACESTATUS

Or from Sqlserver configuration manager by adding -T 7646 in the


end of startup parameter
With this we can permanently OFF the parameter sniffing.

To show all trace flags, which told me that it wasn't set (after reboot, I guess). To set the trace flag
permanently, I did this:

went to SQL Server Configuration Manager

viewed properties for SQL Server service

visited the Advanced tab

edited the Startup Parameters option and added

;-T{tracenumber}

to the end, like so...


-dD:\MSSQL10.MSSQLSERVER\MSSQL\DATA\master.mdf;eD:\MSSQL10.MSSQLSERVER\MSSQL\Log\ERRORLOG;lD:\MSSQL10.MSSQLSERVER\MSSQL\DATA\mastlog.ldf;-T7646
Or from Sqlserver configuration manager by adding -T 7646 in the end
of startup parameter
With this we can permanently OFF the parameter sniffing.

S-ar putea să vă placă și