<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results matching tags 'Performance', 'Optimization', and 'Parameter Sniffing'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Performance,Optimization,Parameter+Sniffing&amp;orTags=0</link><description>Search results matching tags 'Performance', 'Optimization', and 'Parameter Sniffing'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>The Query Optimizer and Parameter Sniffing</title><link>http://sqlblog.com/blogs/ben_nevarez/archive/2009/08/27/the-query-optimizer-and-parameter-sniffing.aspx</link><pubDate>Fri, 28 Aug 2009 02:42:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:16347</guid><dc:creator>Ben Nevarez</dc:creator><description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;As we all know, the SQL Server Query Optimizer uses statistics to estimate the cardinality and selectivity of predicates of a query to produce an optimal execution plan. The Query Optimizer accomplishes this by first inspecting the values of the query parameters. This behavior is called parameter sniffing and it is a good thing. Getting an execution plan tailored to the current parameters of a query improves the performance of your applications.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;We also know that the plan cache can store these execution plans so they can be reused the next time the same query needs to be executed again. This saves optimization time and CPU resources as the query does not need to be compiled again.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;However, although the Query Optimizer and the plan cache work fine together most of the times, occasionally some performance problems can appear. Since the Query Optimizer may produce different execution plans for the same query, depending on its parameters, caching and reusing only one of these plans may be a performance issue for some other instance of this query that could benefit from a better plan.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;This is a known problem with queries using explicit parameterization like in, for example, stored procedures. So let us see an example of what the problem is and a few recommendations on how to fix it.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;1) The problem&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Let us write a simple stored procedure using the Sales.SalesOrderDetail table on the AdventureWorks database&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;create&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:blue;"&gt;procedure&lt;/SPAN&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:blue;"&gt;int&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) 
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;as &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:gray;"&gt;*&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;from&lt;/SPAN&gt; Sales&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;SalesOrderDetail &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; ProductID &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; @pid &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Run this to display the amount of disk activity generated by the query&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;set&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:blue;"&gt;statistics&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;io&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;on 
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;and execute the stored procedure&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;exec&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 897 
&lt;P&gt;&lt;/SPAN&gt;The Query Optimizer estimates that only a few records will be returned by this query and decides to use an existing index, so if you look at the actual execution plan you will see an Index Seek and a Key Lookup operators. The I/O information will be similar to this&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:8pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;logical reads 10, physical reads 0, read-ahead reads 0&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:8pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Now clear the plan cache to remove this plan and run the stored procedure again using a new parameter (Note: Be careful not to clear the plan cache of a production environment)&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;dbcc&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; freeproccache 
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;exec&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 870 &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;This time you will get 4,688 rows and the execution plan will show a Clustered Index Scan. The I/O information will be similar to this&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:8pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;logical reads 1240, physical reads 0, read-ahead reads 0&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:8pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;In this example each execution created its own optimal execution plan. Now see what happen when the plan cache is not cleared before the second execution so they both use the same cached plan&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;dbcc&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; freeproccache 
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;exec&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 870 &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;exec&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 897 &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;This time the Query Optimizer will compile the first execution of the stored procedure and will create an optimal execution plan for the value 870. This will use a Clustered Index Scan and around 1,240 logical reads. Since this plan is cached, it will also be used for the second execution, using the value 897 and it will also show a Clustered Index Scan and around 1,240 logical reads. This second execution is using 124 times more reads than its optimal plan, as shown previously.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;You can try the other combination as well, clearing the plan cache, and running these two executions of the stored procedure, but this time using the value 897 on the first one and 870 on the second one.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;2) Optimize for a typical parameter&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;There might be cases when most of the executions of a stored procedure use the same execution plan and/or you want to avoid the optimization cost. For these cases you can use the OPTIMIZE FOR hint. Use this hint when an optimal plan is generated for the majority of values used for the parameter. Only the few executions using an atypical parameter will not have an optimal plan.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Suppose that almost all of the executions of our stored procedure would benefit from the previous plan using an Index Seek and a Key Lookup.&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;You could write the stored procedure this way&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;alter&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:blue;"&gt;procedure&lt;/SPAN&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:blue;"&gt;int&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) 
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;as &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:gray;"&gt;*&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;from&lt;/SPAN&gt; Sales&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;SalesOrderDetail &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; ProductID &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; @pid &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;option &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:gray;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;optimize &lt;SPAN style="COLOR:blue;"&gt;for &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 897&lt;SPAN style="COLOR:gray;"&gt;)) &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;When you run the stored procedure it will be optimized for the value 897, no matter what parameter value was specified for the execution. Test the following case&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;exec&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 870 
&lt;P&gt;&lt;/SPAN&gt;You can find this in the XML plan&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:#a31515;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;ParameterList&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&amp;gt; 
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:#a31515;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;ColumnReference&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:red;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;Column&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;"&lt;SPAN style="COLOR:blue;"&gt;@pid&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;ParameterCompiledValue&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt;(897)&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;ParameterRuntimeValue&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt;(870)&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt; /&amp;gt; &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:#a31515;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;ParameterList&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&amp;gt; &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;This clearly shows which value was used during optimization and which one during execution. In this case the stored procedure is optimized only once, and the plan is stored on the plan cache and reused as many times as needed. The benefit of using this hint is that you have total control on which plan is stored on the plan cache.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;3) Optimize on every execution&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;If you want the best performance for every query the solution might be to optimize for every execution. You will get an optimal plan on every execution but will pay for the optimization cost. To do this use the RECOMPILE hint as shown here.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;alter&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:blue;"&gt;procedure&lt;/SPAN&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:blue;"&gt;int&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) 
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;as &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:gray;"&gt;*&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;from&lt;/SPAN&gt; Sales&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;SalesOrderDetail &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; ProductID &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; @pid &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;option &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:gray;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;recompile&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:gray;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;) &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;The XML plan for this execution&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;exec&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; test&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;@pid &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 897 
&lt;P&gt;&lt;/SPAN&gt;will show&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:#a31515;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;ParameterList&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&amp;gt; 
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:#a31515;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;ColumnReference&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:red;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;Column&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;"&lt;SPAN style="COLOR:blue;"&gt;@pid&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;ParameterCompiledValue&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt;(897)&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;ParameterRuntimeValue&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt;(897)&lt;/SPAN&gt;"&lt;SPAN style="COLOR:blue;"&gt; /&amp;gt; &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:#a31515;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;ParameterList&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&amp;gt; &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Some other solution that has been traditionally implemented before has been using local variables but usually this is not a good idea. By doing this you are not only disabling parameter sniffing but also disabling the choice of the Query Optimizer to use the statistics histogram&amp;nbsp;to find an optimal plan for the query. This solution will use the same execution plan for all the executions but may not be the optimal plan for any of them.&lt;/P&gt;</description></item></channel></rss>