<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblogcasts.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>SQL and the like</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/default.aspx</link><description>Dave Ballantyne&amp;#39;s blog.  Freelance SQL Server database designer and developer at &lt;a href="http://www.clearskysql.co.uk"&gt;Clear Sky SQL&lt;/a&gt;</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>“Query cost (relative to the batch)” &lt;&gt; Query cost relative to batch</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/05/10/query-cost-relative-to-the-batch-lt-gt-query-cost-relative-to-batch.aspx</link><pubDate>Thu, 10 May 2012 10:19:17 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:16203</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=16203</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/05/10/query-cost-relative-to-the-batch-lt-gt-query-cost-relative-to-batch.aspx#comments</comments><description>&lt;p&gt;OK, so that is quite a contradictory title, but unfortunately it is true that a common misconception is that the query with the highest percentage relative to batch is the worst performing.&amp;#160; Simply put, it is a lie, or more accurately we dont understand what these figures mean.&lt;/p&gt;  &lt;p&gt;Consider the two below simple queries:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; * &lt;span class="kwrd"&gt;FROM&lt;/span&gt; Person.BusinessEntity
&lt;span class="kwrd"&gt;JOIN&lt;/span&gt; Person.BusinessEntityAddress
&lt;span class="kwrd"&gt;ON&lt;/span&gt; Person.BusinessEntity.BusinessEntityID = Person.BusinessEntityAddress.BusinessEntityID
&lt;span class="kwrd"&gt;go&lt;/span&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; * &lt;span class="kwrd"&gt;FROM&lt;/span&gt; Sales.SalesOrderDetail
&lt;span class="kwrd"&gt;JOIN&lt;/span&gt; Sales.SalesOrderHeader
&lt;span class="kwrd"&gt;ON&lt;/span&gt; Sales.SalesOrderDetail.SalesOrderID = Sales.SalesOrderHeader.SalesOrderID&lt;/pre&gt;

&lt;p&gt;After executing these and looking at the plans, I see this :&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_725069FC.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_38CD5A05.png" width="663" height="182" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, a 13% / 87% split ,&amp;#160; but 13% / 87% of WHAT ? CPU ? Duration ? Reads ? Writes ? or some magical weighted algorithm ?&amp;#160; &lt;/p&gt;

&lt;p&gt;In a Profiler trace of the two we can find the metrics we are interested in.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_1126DDDB.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_65E246D3.png" width="660" height="48" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CPU and duration are well out but what about reads (210 and 1935)? To save you doing the maths, though you are more than welcome to, that’s a 90.2% / 9.8% split.&amp;#160; Close, but no cigar.&lt;/p&gt;

&lt;p&gt;Lets try a different tact.&amp;#160; Looking at the execution plan the “Estimated Subtree cost” of query 1 is 0.29449 and query 2 its 1.96596.&amp;#160; Again to save you the maths that works out to 13.03% and 86.97%, round those and thats the figures we are after.&amp;#160; But, what is the worrying word there ? “Estimated”.&amp;#160; &lt;/p&gt;

&lt;p&gt;So these are not “actual”&amp;#160; execution costs,&amp;#160; but what’s the problem in comparing the estimated costs to derive a meaning of “Most Costly”.&amp;#160; Well, in the case of simple queries such as the above , probably not a lot.&amp;#160; In more complicated queries , a fair bit.&lt;/p&gt;

&lt;p&gt;By modifying the second query to also show the total number of lines on each order&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; *,&lt;span class="kwrd"&gt;COUNT&lt;/span&gt;(*) &lt;span class="kwrd"&gt;OVER&lt;/span&gt; (PARTITION &lt;span class="kwrd"&gt;BY&lt;/span&gt; Sales.SalesOrderDetail.SalesOrderID)
 &lt;span class="kwrd"&gt;FROM&lt;/span&gt; Sales.SalesOrderDetail
&lt;span class="kwrd"&gt;JOIN&lt;/span&gt; Sales.SalesOrderHeader
&lt;span class="kwrd"&gt;ON&lt;/span&gt; Sales.SalesOrderDetail.SalesOrderID = Sales.SalesOrderHeader.SalesOrderID&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;font face="Tahoma"&gt;The split in percentages is now 6% / 94% and the profiler metrics are :&lt;/font&gt;&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_10BAAAE6.png"&gt;&lt;font face="Tahoma"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_1E8CF0E1.png" width="657" height="47" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;/pre&gt;

&lt;p&gt;Even more of a discrepancy. &lt;/p&gt;

&lt;p&gt;Estimates can be out with actuals for a whole host of reasons,&amp;#160; scalar UDF’s are a particular bug bear of mine and in-fact the cost of a udf call is entirely hidden inside the execution plan.&amp;#160; It always estimates to 0 (well, a very small number).&lt;/p&gt;

&lt;p&gt;Take for instance the following udf&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Create&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; dbo.udfSumSalesForCustomer(@CustomerId &lt;span class="kwrd"&gt;integer&lt;/span&gt;)
&lt;span class="kwrd"&gt;returns&lt;/span&gt; money
&lt;span class="kwrd"&gt;as&lt;/span&gt;
&lt;span class="kwrd"&gt;begin&lt;/span&gt;
   &lt;span class="kwrd"&gt;Declare&lt;/span&gt; @&lt;span class="kwrd"&gt;Sum&lt;/span&gt; money
   &lt;span class="kwrd"&gt;Select&lt;/span&gt; @&lt;span class="kwrd"&gt;Sum&lt;/span&gt;= &lt;span class="kwrd"&gt;SUM&lt;/span&gt;(SalesOrderHeader.TotalDue)
     &lt;span class="kwrd"&gt;from&lt;/span&gt; Sales.SalesOrderHeader
    &lt;span class="kwrd"&gt;where&lt;/span&gt; CustomerID = @CustomerId
   &lt;span class="kwrd"&gt;return&lt;/span&gt; @&lt;span class="kwrd"&gt;Sum&lt;/span&gt;
end&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;font face="Tahoma"&gt;If we have two statements , one that fires the udf and another that doesn&amp;#39;t:&lt;/font&gt;&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Select&lt;/span&gt; CustomerID
  &lt;span class="kwrd"&gt;from&lt;/span&gt; Sales.Customer
 &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; CustomerID
&lt;span class="kwrd"&gt;go&lt;/span&gt;
&lt;span class="kwrd"&gt;Select&lt;/span&gt; CustomerID,dbo.udfSumSalesForCustomer(Customer.CustomerID)
  &lt;span class="kwrd"&gt;from&lt;/span&gt; Sales.Customer
 &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; CustomerID&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;font face="Tahoma"&gt;The costs relative to batch is a 50/50 split, but the has to be an actual cost of firing the udf.  Indeed profiler shows us :&lt;/font&gt;&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_294A4836.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_092F3B79.png" width="664" height="54" /&gt;&lt;/a&gt;&lt;/pre&gt;

&lt;p&gt;&lt;font face="Tahoma"&gt;No where even remotely near 50/50!!!!&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face="Tahoma"&gt;Moving forward to window framing functionality in SQL Server 2012 the optimizer sees ROWS and RANGE ( see &lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/09/22/rows-or-range-what-s-the-difference.aspx"&gt;here&lt;/a&gt; for their functional differences) as the same ‘cost’ too&lt;/font&gt;&lt;/p&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; SalesOrderDetailID,SalesOrderId,
       &lt;span class="kwrd"&gt;SUM&lt;/span&gt;(LineTotal) &lt;span class="kwrd"&gt;OVER&lt;/span&gt;(PARTITION &lt;span class="kwrd"&gt;BY&lt;/span&gt; salesorderid 
         &lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Salesorderdetailid RANGE unbounded preceding)
&lt;span class="kwrd"&gt;from&lt;/span&gt; Sales.SalesOrderdetail
&lt;span class="kwrd"&gt;go&lt;/span&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; SalesOrderDetailID,SalesOrderId,
       &lt;span class="kwrd"&gt;SUM&lt;/span&gt;(LineTotal) &lt;span class="kwrd"&gt;OVER&lt;/span&gt;(PARTITION &lt;span class="kwrd"&gt;BY&lt;/span&gt; salesorderid 
       &lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Salesorderdetailid &lt;span class="kwrd"&gt;Rows&lt;/span&gt; unbounded preceding)
&lt;span class="kwrd"&gt;from&lt;/span&gt; Sales.SalesOrderdetail&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;font face="Tahoma"&gt;By now it wont be a great display to show you the Profiler trace reads a *tiny* bit different.&lt;/font&gt;&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_649DADF4.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_767A41C1.png" width="687" height="55" /&gt;&lt;/a&gt;&lt;/pre&gt;

&lt;p&gt;So moral of the story, Percentage relative to batch can give a rough ‘finger in the air’ measurement, but dont rely on it as fact.&lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=16203" width="1" height="1"&gt;</description></item><item><title>Offset without OFFSET</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/04/26/offset-without-offset.aspx</link><pubDate>Thu, 26 Apr 2012 10:34:00 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:16190</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=16190</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/04/26/offset-without-offset.aspx#comments</comments><description>&lt;p&gt;&lt;font size="2"&gt;A while ago Robert Cary posted an article on SQL Server Central entitled &lt;/font&gt;&lt;a href="http://www.sqlservercentral.com/articles/T-SQL/66030/"&gt;&lt;font size="2"&gt;2005 Paging – The Holy Grail&lt;/font&gt;&lt;/a&gt;&lt;font size="2"&gt; which is, as the title would suggest about paging in SQL Server.&amp;nbsp; This article provoked some really interesting chat around the subject and is well worth a read.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;This is now a lot easier in SQL Server 2012 with the introduction of the OFFSET extension to the ORDER BY clause,&amp;nbsp; but what is the most optimal method is you are not using 2012 ?&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;Well, whilst playing around by the OFFSET portion of my “What’s new in SQL Server 2012 – TSQL” presentation, I hit on a different method that I’ve not seen published before.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;Now whilst finding which rows are on which page is a problem, it is only &lt;em&gt;part &lt;/em&gt;of a much wider problem, that being that cost of the lookups to find other related data.&amp;nbsp; For example:&amp;nbsp; You have a list of people which you are paging through in the order of LastName,&amp;nbsp; but you also wish to display FirstName.&amp;nbsp; That is not in your index and so a key lookup occurs, &lt;em&gt;OK I could INCLUDE it in the index but im just simplifying the problem. &lt;/em&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;So, to demonstrate this I need to create an index on Person.Person in AdventureWorks.&lt;/font&gt;&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Create&lt;/span&gt; &lt;span class="kwrd"&gt;index&lt;/span&gt; idxLastName &lt;span class="kwrd"&gt;on&lt;/span&gt; Person.Person(LastName)&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;font face="Tahoma"&gt;The query for the “holy grail” method would look something like this :&lt;/font&gt;&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;with&lt;/span&gt; ctePaging
&lt;span class="kwrd"&gt;as&lt;/span&gt;
(
&lt;span class="kwrd"&gt;Select&lt;/span&gt; LastName,FirstName,
       row_number() &lt;span class="kwrd"&gt;over&lt;/span&gt; (&lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; LastName,BusinessEntityID)-1  &lt;span class="kwrd"&gt;as&lt;/span&gt; RowN
 &lt;span class="kwrd"&gt;from&lt;/span&gt;  Person.Person
)
&lt;span class="kwrd"&gt;Select&lt;/span&gt; * &lt;span class="kwrd"&gt;from&lt;/span&gt; ctePaging
&lt;span class="kwrd"&gt;where&lt;/span&gt; RowN &lt;span class="kwrd"&gt;between&lt;/span&gt; 20 &lt;span class="kwrd"&gt;and&lt;/span&gt; 39 
&lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; RowN;&lt;/pre&gt;

&lt;p&gt;The issue here is that SQL Server has initiated an index scan (against a different index than the one we created) and had to process all the rows in the table and then sort them.&amp;nbsp; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_25B3C980.png"&gt;&lt;img style="border-width:0px;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_5334E943.png" width="402" height="167" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We only want 20 rows returned so this is quite a lot of wasted effort on the engine&amp;#39;s part.&lt;/p&gt;

&lt;p&gt;OFFSET has been introduced in 2012 and running the equivalent query of :&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Select&lt;/span&gt; LastName,FirstName,BusinessEntityID
 &lt;span class="kwrd"&gt;from&lt;/span&gt;  Person.Person
 &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; LastName,BusinessEntityID
 offset 20 &lt;span class="kwrd"&gt;rows&lt;/span&gt; &lt;span class="kwrd"&gt;fetch&lt;/span&gt; &lt;span class="kwrd"&gt;next&lt;/span&gt; 20 &lt;span class="kwrd"&gt;rows&lt;/span&gt; &lt;span class="kwrd"&gt;only&lt;/span&gt;;&lt;/pre&gt;

&lt;p&gt;Gives us the query plan of :&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_65117D10.png"&gt;&lt;img style="border:0px currentColor;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_609AFC49.png" width="486" height="265" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even this is non-optimal though, as the key lookup has occurred 40 times , even though we only needed the data (in this case FirstName) for 20 rows.&lt;/p&gt;

&lt;p&gt;This can be resolved by doing the key lookup yourself.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;with&lt;/span&gt; cteKeySeek
&lt;span class="kwrd"&gt;as&lt;/span&gt;
(
&lt;span class="kwrd"&gt;Select&lt;/span&gt; LastName,BusinessEntityID
 &lt;span class="kwrd"&gt;from&lt;/span&gt;  Person.Person
 &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; LastName,BusinessEntityID
 offset 20 &lt;span class="kwrd"&gt;rows&lt;/span&gt; &lt;span class="kwrd"&gt;fetch&lt;/span&gt; &lt;span class="kwrd"&gt;next&lt;/span&gt; 20 &lt;span class="kwrd"&gt;rows&lt;/span&gt; &lt;span class="kwrd"&gt;only&lt;/span&gt;
)
&lt;span class="kwrd"&gt;Select&lt;/span&gt; cteKeySeek.LastName,
       FirstName,
       cteKeySeek.BusinessEntityID
 &lt;span class="kwrd"&gt;from&lt;/span&gt;  cteKeySeek
 &lt;span class="kwrd"&gt;inner&lt;/span&gt; &lt;span class="kwrd"&gt;join&lt;/span&gt;  Person.Person   
   &lt;span class="kwrd"&gt;on&lt;/span&gt;  cteKeySeek.BusinessEntityID =   Person.BusinessEntityID
&lt;span class="kwrd"&gt;order&lt;/span&gt;  &lt;span class="kwrd"&gt;by&lt;/span&gt; cteKeySeek.LastName,FirstName,cteKeySeek.BusinessEntityID;&lt;/pre&gt;

&lt;p&gt;Even though its longer, wordier and involves a join , it is more efficient as the join has replaced the key lookup and it is now only occurring on the 20 rows of data that we need&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_4B3D46E1.png"&gt;&lt;img style="border:0px currentColor;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_0B072D67.png" width="568" height="253" /&gt;&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Quite neat hey ? When using OFFSET it is important to remember that no magic is happening, SQL Server still has to ‘count’ and scan through the rows that are not to be processed before it can decide which ones it does need.&amp;nbsp; &lt;/p&gt;

&lt;p&gt;A comparable query for previous versions and taking the lead from the holy grail method would be :&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;with&lt;/span&gt; cteKeySeek
&lt;span class="kwrd"&gt;as&lt;/span&gt;
(
&lt;span class="kwrd"&gt;Select&lt;/span&gt; BusinessEntityID,LastName,
       row_number() &lt;span class="kwrd"&gt;over&lt;/span&gt; (&lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; LastName,BusinessEntityID)-1 
             &lt;span class="kwrd"&gt;as&lt;/span&gt; RowN
 &lt;span class="kwrd"&gt;from&lt;/span&gt;  Person.Person

)
&lt;span class="kwrd"&gt;Select&lt;/span&gt; cteKeySeek.LastName,FirstName,cteKeySeek.BusinessEntityID ,RowN
  &lt;span class="kwrd"&gt;from&lt;/span&gt; cteKeySeek
  &lt;span class="kwrd"&gt;inner&lt;/span&gt; loop &lt;span class="kwrd"&gt;join&lt;/span&gt;  Person.Person   
   &lt;span class="kwrd"&gt;on&lt;/span&gt;  cteKeySeek.BusinessEntityID =   Person.BusinessEntityID
&lt;span class="kwrd"&gt;where&lt;/span&gt; RowN &amp;gt;= 20 &lt;span class="kwrd"&gt;and&lt;/span&gt; rown&amp;lt;=39
&lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; LastName,BusinessEntityID;&lt;/pre&gt;

&lt;p&gt;Which does similarly filter the rows before doing the index lookup&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_1F8C7CE5.png"&gt;&lt;img style="border:0px currentColor;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_7132F737.png" width="673" height="232" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It does however still involve a scan of 19,972 rows of which 19,932 are irrelevant to our final result set.&amp;nbsp; You may of noticed in the OFFSET versions that the TOP operator is used to filter the data and ‘stop’ the scan once it has reached the last row that we are interested in.&amp;nbsp; What if we could do something similar.&lt;/p&gt;

&lt;p&gt;What about this ?:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;with&lt;/span&gt; cteKeySeek
&lt;span class="kwrd"&gt;as&lt;/span&gt;
(
&lt;span class="kwrd"&gt;Select&lt;/span&gt; BusinessEntityID,LastName,
       row_number() &lt;span class="kwrd"&gt;over&lt;/span&gt; (&lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; LastName,BusinessEntityID)-1 
             &lt;span class="kwrd"&gt;as&lt;/span&gt; RowN
 &lt;span class="kwrd"&gt;from&lt;/span&gt;  Person.Person

)
&lt;span class="kwrd"&gt;Select&lt;/span&gt; &lt;span class="kwrd"&gt;top&lt;/span&gt;(20) cteKeySeek.LastName,FirstName,cteKeySeek.BusinessEntityID ,RowN
  &lt;span class="kwrd"&gt;from&lt;/span&gt; cteKeySeek
  &lt;span class="kwrd"&gt;inner&lt;/span&gt; loop &lt;span class="kwrd"&gt;join&lt;/span&gt;  Person.Person   
   &lt;span class="kwrd"&gt;on&lt;/span&gt;  cteKeySeek.BusinessEntityID =   Person.BusinessEntityID
&lt;span class="kwrd"&gt;where&lt;/span&gt; RowN &amp;gt;= 20 &lt;span class="kwrd"&gt;and&lt;/span&gt; RowN&amp;lt;=39
&lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; LastName,BusinessEntityID;&lt;/pre&gt;

&lt;p&gt;That does have the rather interesting effect of doing exactly that:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_498C7B0D.png"&gt;&lt;img style="border-width:0px;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_16BC7499.png" width="764" height="238" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, this is looking (at least in-terms of rowcounts) very similar to the OFFSET functionality.&amp;nbsp; If we look for a page of data further on (rows 200 to 219) and look at an profiler trace we can see how the three type of query compare.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_1C971832.png"&gt;&lt;img style="border:0px currentColor;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_00865947.png" width="609" height="97" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So as you can see over a medium size (ish) dataset the fake and real offset are comparable in terms of IO.&lt;/p&gt;

&lt;p&gt;Hope this helps someone, who needs to do paging &lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=16190" width="1" height="1"&gt;</description></item><item><title>Parsing T-SQL – The easy way</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/03/13/parsing-t-sql-the-easy-way.aspx</link><pubDate>Tue, 13 Mar 2012 17:19:56 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:16142</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=16142</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/03/13/parsing-t-sql-the-easy-way.aspx#comments</comments><description>&lt;p&gt;Every once in a while, I hit an issue that would require me to interrogate/parse some T-SQL code.&amp;#160; Normally, I would shy away from this and attempt to solve the problem in some other way.&amp;#160; I have written parsers before in the the past using LEX and YACC, and as much fun and awesomeness that path is,&amp;#160; I couldnt justify the time it would take.&lt;/p&gt;  &lt;p&gt;However, this week I have been faced with just such an issue and at the back of my mind I can remember reading through the &lt;a href="http://www.microsoft.com/download/en/details.aspx?id=29065"&gt;SQLServer 2012 feature pack&lt;/a&gt; and seeing something called “Microsoft SQL Server 2012 Transact-SQL Language Service “.&amp;#160; This is described there as :&lt;/p&gt;  &lt;p&gt;“The SQL Server Transact-SQL Language Service is a component based on the .NET Framework which provides parsing validation and IntelliSense services for Transact-SQL for SQL Server 2012, SQL Server 2008 R2, and SQL Server 2008. “&lt;/p&gt;  &lt;p&gt;Sounds just what I was after.&amp;#160; Documentation is very scant on this so dont take what follows as best practice or best use, just &lt;em&gt;a&lt;/em&gt; practice and &lt;em&gt;a&lt;/em&gt; use.&lt;/p&gt;  &lt;p&gt;Knowing what I was sort of looking for &lt;em&gt;something,&lt;/em&gt; I found the relevant assembly in the gac which is the simply named ,’Microsoft.SqlServer.Management.SqlParser’.&lt;/p&gt;  &lt;p&gt;Even knowing that you wont find much in terms of documentation if you do a web-search, but you will find the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.sqlparser.parser.aspx"&gt;MSDN documentation&lt;/a&gt; that list the members and methods etc…&lt;/p&gt;  &lt;p&gt;The “scanner”&amp;#160; class sounded the most appropriate for my needs as that is described as “Scans Transact-SQL searching for individual units of code or tokens.”.&lt;/p&gt;  &lt;p&gt;After a bit of poking, around the code i ended up with was something like&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color:black;"&gt;[&lt;/span&gt;&lt;span style="color:teal;"&gt;System.Reflection.Assembly&lt;/span&gt;&lt;span style="color:black;"&gt;]::&lt;/span&gt;&lt;span style="color:#8b4513;"&gt;LoadWithPartialName&lt;/span&gt;&lt;span style="color:black;"&gt;(&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;Microsoft.SqlServer.Management.SqlParser&amp;quot;&lt;/span&gt;&lt;span style="color:black;"&gt;) | &lt;/span&gt;&lt;span style="color:#5f9ea0;"&gt;Out-Null
&lt;/span&gt;&lt;span style="color:purple;"&gt;$ParseOptions &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:#5f9ea0;"&gt;New-Object &lt;/span&gt;&lt;span style="color:maroon;"&gt;Microsoft.SqlServer.Management.SqlParser.Parser.ParseOptions
&lt;/span&gt;&lt;span style="color:purple;"&gt;$ParseOptions&lt;/span&gt;&lt;span style="color:black;"&gt;.&lt;/span&gt;&lt;span style="color:#8b4513;"&gt;BatchSeparator &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;#39;GO&amp;#39;

&lt;/span&gt;&lt;span style="color:purple;"&gt;$Parser &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:#5f9ea0;"&gt;new-object &lt;/span&gt;&lt;span style="color:maroon;"&gt;Microsoft.SqlServer.Management.SqlParser.Parser.Scanner&lt;/span&gt;&lt;span style="color:black;"&gt;(&lt;/span&gt;&lt;span style="color:purple;"&gt;$ParseOptions&lt;/span&gt;&lt;span style="color:black;"&gt;)
&lt;/span&gt;&lt;span style="color:purple;"&gt;$Sql &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;quot;Create Procedure MyProc as Select top(10) * from dbo.Table&amp;quot;
&lt;/span&gt;&lt;span style="color:purple;"&gt;$Parser&lt;/span&gt;&lt;span style="color:black;"&gt;.&lt;/span&gt;&lt;span style="color:#8b4513;"&gt;SetSource&lt;/span&gt;&lt;span style="color:black;"&gt;(&lt;/span&gt;&lt;span style="color:purple;"&gt;$Sql&lt;/span&gt;&lt;span style="color:black;"&gt;,0)
&lt;/span&gt;&lt;span style="color:purple;"&gt;$Token&lt;/span&gt;&lt;span style="color:black;"&gt;=[&lt;/span&gt;&lt;span style="color:teal;"&gt;Microsoft.SqlServer.Management.SqlParser.Parser.Tokens&lt;/span&gt;&lt;span style="color:black;"&gt;]::&lt;/span&gt;&lt;span style="color:#8b4513;"&gt;TOKEN_SET
&lt;/span&gt;&lt;span style="color:purple;"&gt;$Start &lt;/span&gt;&lt;span style="color:red;"&gt;=&lt;/span&gt;&lt;span style="color:black;"&gt;0
&lt;/span&gt;&lt;span style="color:purple;"&gt;$End &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;0
&lt;/span&gt;&lt;span style="color:purple;"&gt;$State &lt;/span&gt;&lt;span style="color:red;"&gt;=&lt;/span&gt;&lt;span style="color:black;"&gt;0 
&lt;/span&gt;&lt;span style="color:purple;"&gt;$IsEndOfBatch &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:purple;"&gt;$false
$IsMatched &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:purple;"&gt;$false
$IsExecAutoParamHelp &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:purple;"&gt;$false
&lt;/span&gt;&lt;span style="color:blue;"&gt;while&lt;/span&gt;&lt;span style="color:black;"&gt;((&lt;/span&gt;&lt;span style="color:purple;"&gt;$Token &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:purple;"&gt;$Parser&lt;/span&gt;&lt;span style="color:black;"&gt;.&lt;/span&gt;&lt;span style="color:#8b4513;"&gt;GetNext&lt;/span&gt;&lt;span style="color:black;"&gt;([&lt;/span&gt;&lt;span style="color:teal;"&gt;ref&lt;/span&gt;&lt;span style="color:black;"&gt;]&lt;/span&gt;&lt;span style="color:purple;"&gt;$State &lt;/span&gt;&lt;span style="color:black;"&gt;,[&lt;/span&gt;&lt;span style="color:teal;"&gt;ref&lt;/span&gt;&lt;span style="color:black;"&gt;]&lt;/span&gt;&lt;span style="color:purple;"&gt;$Start&lt;/span&gt;&lt;span style="color:black;"&gt;, [&lt;/span&gt;&lt;span style="color:teal;"&gt;ref&lt;/span&gt;&lt;span style="color:black;"&gt;]&lt;/span&gt;&lt;span style="color:purple;"&gt;$End&lt;/span&gt;&lt;span style="color:black;"&gt;, [&lt;/span&gt;&lt;span style="color:teal;"&gt;ref&lt;/span&gt;&lt;span style="color:black;"&gt;]&lt;/span&gt;&lt;span style="color:purple;"&gt;$IsMatched&lt;/span&gt;&lt;span style="color:black;"&gt;, [&lt;/span&gt;&lt;span style="color:teal;"&gt;ref&lt;/span&gt;&lt;span style="color:black;"&gt;]&lt;/span&gt;&lt;span style="color:purple;"&gt;$IsExecAutoParamHelp &lt;/span&gt;&lt;span style="color:black;"&gt;))&lt;/span&gt;&lt;span style="color:red;"&gt;-ne &lt;/span&gt;&lt;span style="color:black;"&gt;[&lt;/span&gt;&lt;span style="color:teal;"&gt;Microsoft.SqlServer.Management.SqlParser.Parser.Tokens&lt;/span&gt;&lt;span style="color:black;"&gt;]::&lt;/span&gt;&lt;span style="color:#8b4513;"&gt;EOF&lt;/span&gt;&lt;span style="color:black;"&gt;) {
    &lt;/span&gt;&lt;span style="color:blue;"&gt;try&lt;/span&gt;&lt;span style="color:black;"&gt;{
        (&lt;/span&gt;&lt;span style="color:purple;"&gt;$TokenPrs &lt;/span&gt;&lt;span style="color:black;"&gt;=[&lt;/span&gt;&lt;span style="color:teal;"&gt;Microsoft.SqlServer.Management.SqlParser.Parser.Tokens&lt;/span&gt;&lt;span style="color:black;"&gt;]&lt;/span&gt;&lt;span style="color:purple;"&gt;$Token&lt;/span&gt;&lt;span style="color:black;"&gt;) | &lt;/span&gt;&lt;span style="color:#5f9ea0;"&gt;Out-Null
        &lt;/span&gt;&lt;span style="color:purple;"&gt;$TokenPrs
        $Sql&lt;/span&gt;&lt;span style="color:black;"&gt;.&lt;/span&gt;&lt;span style="color:#8b4513;"&gt;Substring&lt;/span&gt;&lt;span style="color:black;"&gt;(&lt;/span&gt;&lt;span style="color:purple;"&gt;$Start&lt;/span&gt;&lt;span style="color:black;"&gt;,(&lt;/span&gt;&lt;span style="color:purple;"&gt;$end&lt;/span&gt;&lt;span style="color:red;"&gt;-&lt;/span&gt;&lt;span style="color:purple;"&gt;$Start&lt;/span&gt;&lt;span style="color:black;"&gt;)&lt;/span&gt;&lt;span style="color:red;"&gt;+&lt;/span&gt;&lt;span style="color:black;"&gt;1)
    }&lt;/span&gt;&lt;span style="color:blue;"&gt;catch&lt;/span&gt;&lt;span style="color:black;"&gt;{
        &lt;/span&gt;&lt;span style="color:purple;"&gt;$TokenPrs &lt;/span&gt;&lt;span style="color:red;"&gt;= &lt;/span&gt;&lt;span style="color:purple;"&gt;$null
    &lt;/span&gt;&lt;span style="color:black;"&gt;}    
}
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;As you can see , the $Sql variable holds the sql to be parsed , that is pushed into the $Parser object using SetSource,&amp;#160; and then we will use GetNext until the EOF token is returned.&amp;#160; GetNext will also return the Start and End character positions within the source string of the parsed text.&lt;/p&gt;

&lt;p&gt;This script’s output is :&lt;/p&gt;

&lt;p&gt;TOKEN_CREATE
  &lt;br /&gt;Create

  &lt;br /&gt;TOKEN_PROCEDURE

  &lt;br /&gt;Procedure

  &lt;br /&gt;TOKEN_ID

  &lt;br /&gt;MyProc

  &lt;br /&gt;TOKEN_AS

  &lt;br /&gt;as

  &lt;br /&gt;TOKEN_SELECT

  &lt;br /&gt;Select

  &lt;br /&gt;TOKEN_TOP

  &lt;br /&gt;top

  &lt;br /&gt;TOKEN_INTEGER

  &lt;br /&gt;10

  &lt;br /&gt;TOKEN_FROM

  &lt;br /&gt;from

  &lt;br /&gt;TOKEN_ID

  &lt;br /&gt;dbo

  &lt;br /&gt;TOKEN_TABLE

  &lt;br /&gt;Table

  &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;note that the ‘(‘, ‘)’&amp;#160; and ‘*’ characters have returned a token type that is not present in the Microsoft.SqlServer.Management.SqlParser.Parser.Tokens Enum that has caused an error which has been caught in the catch block.&amp;#160; &lt;/p&gt;

&lt;p&gt;Fun, Fun ,Fun , Simple T-SQL Parsing.&amp;#160; Hope this helps someone in the same position,&amp;#160; let me know how you get on.&lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=16142" width="1" height="1"&gt;</description></item><item><title>SQLMidlands &amp; SQLLunch</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/02/18/sqlmidlands-amp-sqllunch.aspx</link><pubDate>Sat, 18 Feb 2012 10:48:45 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:16119</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=16119</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/02/18/sqlmidlands-amp-sqllunch.aspx#comments</comments><description>&lt;p&gt;Many thanks to all those that turned out to see my presentation on Thursday (16th of Feb) of “Cursors are Evil” at SQLMidlands.&amp;#160; The scripts i used are here :&lt;/p&gt;  &lt;p&gt;&lt;a href="https://skydrive.live.com/?cid=4004b6a3bc887e2c&amp;amp;id=4004B6A3BC887E2C%21216"&gt;https://skydrive.live.com/?cid=4004b6a3bc887e2c&amp;amp;id=4004B6A3BC887E2C%21216&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You will need the AdventureWorks2008r2 release to run these, feel free to mail me (&lt;a href="mailto:dave.ballantyne@live.co.uk"&gt;dave.ballantyne@live.co.uk&lt;/a&gt;) with any questions.&amp;#160; They are based upon a series of articles I wrote for SQLServerCentral which can be found &lt;a href="http://www.sqlservercentral.com/articles/T-SQL/73887/"&gt;here&lt;/a&gt; and &lt;a href="http://www.sqlservercentral.com/articles/T-SQL/73889/"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Also I am starting ,or at least having an attempt at, a new user group in London.&amp;#160; This is &lt;a href="http://www.sqllunch.co.uk/"&gt;SQLLunch&lt;/a&gt;, meeting downstairs at The Golden Fleece , EC4N 1SP which is 2 minutes from Bank Tube , we will have a twice monthly meeting (2nd and 4th Tuesdays) for an ‘All Stuff, No Fluff’ event.&amp;#160; Put plainly, a quick hello followed by a 45 minute presentation , which will ,optimistically, have you there and back to your desk within a lunch hour.&lt;/p&gt;  &lt;p&gt;Registrations for the first series of dates are at &lt;a href="http://sqlserverfaq.com"&gt;sqlserverfaq.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If you would like to speak, then please get in touch.&lt;/p&gt;  &lt;p&gt;Hope to see you there.&amp;#160; &lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=16119" width="1" height="1"&gt;</description></item><item><title>[BUG] Inserts to tables with an index view can fail</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/01/06/bug-inserts-to-index-views-can-fail.aspx</link><pubDate>Fri, 06 Jan 2012 20:41:00 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:16067</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=16067</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/01/06/bug-inserts-to-index-views-can-fail.aspx#comments</comments><description>&lt;p&gt;Unfortunately some of the more troubling bugs can be very hard to reproduce succinctly.&amp;nbsp; Here is one that has been troubling me for a little while :&lt;/p&gt;
&lt;p&gt;The issue is using &lt;a href="http://msdn.microsoft.com/en-us/library/dd171921(v=SQL.100).aspx"&gt;indexed views&lt;/a&gt; with a calculated column. Indexed views, despite their restrictions, are a very handy addition to SQL Server and materializing views to be hard data can certainly improve performance.&amp;nbsp; So to demonstrate my issue we will need to build a table and create a view on it.&amp;nbsp; &lt;/p&gt;
&lt;div&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;table&lt;/span&gt; myTable&lt;br /&gt;(&lt;br /&gt;Id &lt;span style="COLOR:#0000ff;"&gt;integer&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;null&lt;/span&gt;,&lt;br /&gt;InView &lt;span style="COLOR:#0000ff;"&gt;char&lt;/span&gt;(1) &lt;span style="COLOR:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;null&lt;/span&gt;,&lt;br /&gt;SomeData &lt;span style="COLOR:#0000ff;"&gt;varchar&lt;/span&gt;(255) &lt;span style="COLOR:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;null&lt;/span&gt;&lt;br /&gt;)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;Create&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;view&lt;/span&gt; vwIxView&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;with&lt;/span&gt; schemabinding&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;as&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;Select&lt;/span&gt; ID,Somedata,&lt;span style="COLOR:#0000ff;"&gt;left&lt;/span&gt;(SomeData,CHARINDEX(&lt;span style="COLOR:#006080;"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;,SomeData)-1) &lt;span style="COLOR:#0000ff;"&gt;as&lt;/span&gt; leftfromx&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;from&lt;/span&gt; dbo.myTable&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;Where&lt;/span&gt; InView =&lt;span style="COLOR:#006080;"&gt;&amp;#39;Y&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;As you can see , the view is filtering the data for where InView =’Y’ and is adding a calculated column to do some manipulation of the column ‘SomeData’. This column ,leftfromx, is taking the characters up to and including the first ‘x’ from the ‘SomeData’ column. &lt;/div&gt;
&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;If we insert some data into the view with &lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;insert &lt;span style="COLOR:#0000ff;"&gt;into&lt;/span&gt; myTable(Id,InView,SomeData)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;select&lt;/span&gt; 1,&lt;span style="COLOR:#006080;"&gt;&amp;#39;N&amp;#39;&lt;/span&gt;,&lt;span style="COLOR:#006080;"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;unsurprisingly, if we look to the view then there will be no data in it.&lt;/p&gt;
&lt;p&gt;Now lets add an index to the view&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;unique&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;clustered&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;index&lt;/span&gt; pkvwIxView &lt;span style="COLOR:#0000ff;"&gt;on&lt;/span&gt; vwIxView(Id)&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;The data is now persisted.&lt;/p&gt;
&lt;p&gt;Lets now add some more data ,the same data, in a &lt;em&gt;ever so&lt;/em&gt; slightly different way.&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;declare&lt;/span&gt; @id &lt;span style="COLOR:#0000ff;"&gt;integer&lt;/span&gt;,&lt;br /&gt;        @inview &lt;span style="COLOR:#0000ff;"&gt;char&lt;/span&gt;(1),&lt;br /&gt;        @Somedata &lt;span style="COLOR:#0000ff;"&gt;char&lt;/span&gt;(50)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;select&lt;/span&gt; @id = 1, @inview = &lt;span style="COLOR:#006080;"&gt;&amp;#39;N&amp;#39;&lt;/span&gt;,@Somedata = &lt;span style="COLOR:#006080;"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;insert &lt;span style="COLOR:#0000ff;"&gt;into&lt;/span&gt; myTable(Id,InView,SomeData)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;select&lt;/span&gt; @id,@inview,@Somedata&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;What is the result ?&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_25AFD4DB.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_17715BEB.png" width="523" height="69" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Huh , well its kind of obvious which “LEFT or SUBSTRING function” has errored, but as inview = ‘N’ why should that piece of code even been executed ?&amp;nbsp; Looking at the estimated plan we can more easily see the flow of events.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_448648B9.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_5CA9B314.png" width="530" height="140" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The ‘compute scalar’ operation is where the LEFT is being executed. ,That is happening before the filter and as there is no ‘x’ in the ‘SomeData’ column , it is unsurprising that the function is erroring.&amp;nbsp; I have tested this on both 2008r2 and 2012 rc0.&lt;/p&gt;
&lt;p&gt;I have raised a connect item &lt;a href="https://connect.microsoft.com/SQLServer/feedback/details/717171/inserting-to-an-indexed-view-can-fail"&gt;here&lt;/a&gt;, if you want to upvote it. &lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=16067" width="1" height="1"&gt;</description></item><item><title>Book review - SQL Server Secret Diary (Know the unknown secrets of SQL Server)</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/12/31/book-review-sql-server-secret-diary-know-the-unknown-secrets-of-sql-server.aspx</link><pubDate>Sat, 31 Dec 2011 11:51:12 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:16046</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=16046</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/12/31/book-review-sql-server-secret-diary-know-the-unknown-secrets-of-sql-server.aspx#comments</comments><description>&lt;p&gt;Like a lot of people within the SQL community, I can never read enough on the subject.&amp;#160; Books, whitepapers, academic research and blogs can all be valuable source of information, so whilst browsing Amazon I found &lt;a href="http://www.amazon.co.uk/gp/product/B0056AH99E/ref=docs-os-doi_0"&gt;this book&lt;/a&gt; on a free kindle download.&amp;#160; The preface makes some bold claims indeed :&lt;/p&gt;  &lt;p&gt;“This book is for developers who already know SQL Server and want to gain more knowledge in SQL Server.&amp;#160; This book is not for starter who want to start from the beginning.&lt;/p&gt;  &lt;p&gt;The problem-solution approach will help you to understand and solve the real-time problems easily.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;This Book will teach you &lt;/u&gt;&lt;/strong&gt;&lt;em&gt;(their emphasis)&lt;/em&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;How to solve common real-time problems&lt;/li&gt;    &lt;li&gt;How to improve performance&lt;/li&gt;    &lt;li&gt;How to protect your data and code&lt;/li&gt;    &lt;li&gt;How to reduce your code&lt;/li&gt;    &lt;li&gt;How to use SQL Server efficiently&lt;/li&gt;    &lt;li&gt;Advanced topics with simple examples&lt;/li&gt;    &lt;li&gt;Tips and tricks with sample queries&lt;/li&gt;    &lt;li&gt;And also teach how to do in the better way.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;”&lt;/p&gt;  &lt;p&gt;The last bullet point, sets the tone of the quite appalling use of grammar (yes, yes , people in glass houses and all that.. ) contained throughout the entire book,&amp;#160; I get that the authors may use english as a second (or third) language,&amp;#160; but where are the proof readers ?&amp;#160; That i can live with though,&amp;#160; its the technical content i really have a problem with.&amp;#160; Here is just a small selection:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Q 2) How to use GO statement in SQL Server ?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;IMO,&amp;#160; the most important concept to understand about GO is that it is not a SQL Statement.&amp;#160; It is processed on the client (SSMS, ISQL etc) and splits the workload into separate batches.&amp;#160; This is not mentioned here,&amp;#160; though to be fair in Q3 (How to repeat the statements without using loops ?) the author notes “GO is a client command and not a T-SQL command&amp;quot;. So GO or GO &amp;lt;N&amp;gt; can only be used with Microsoft SQL Server client tools.”.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Q 5) How to use ORDER BY clause in view ?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Here the author spends a great deal of time and effort working around “As per RDBMS rule ORDER BY clause is not allowed in view”.&amp;#160; This section should be thrown away entirely,&amp;#160; if you are depending on the view ordering ( which is a contradiction in terms)&amp;#160; for your result set ordering you deserve all the law suits that are thrown at you.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Q 10) How to do case sensitive searches in SQL Server ?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The authors solution here is to cast a column as varbinary. OK, fair enough it works. Personally, i would have used COLLATE but lets not split hairs.&amp;#160; The biggest issue i have here is sargability is not mentioned,&amp;#160; we are introducing the possibility of a scan. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Q 12) How to solve server time out problem ?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The scenario presented here is that session #1 has updated some data that session #2 needs to read.&amp;#160; The author presents 2 solutions NOLOCK and READPAST and ,to be fair, does make an attempt at highlighting the dirty reads.&amp;#160; My issue here is that, once again, locking is seen as the enemy that must be worked around.&amp;#160; We should embrace locks, understand why they are happening and how they are protecting us.&amp;#160; The point is not raised that the fault here lies with the UPDATE’ing transaction not completing in a timely fashion, not that the reader cannot complete due to that. The consequences of reading and processing dirty data are not explored thoroughly enough and once again, NOLOCK is used as a “go faster” button.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Q 33 ) How to improve the performance of stored procedure ?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Here we have been given 11 bullet points by the authors , which I have copied verbatim below. My thoughts about each point are inlined in &lt;font color="#ff0000"&gt;red&lt;/font&gt;:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Use SET NOCOUNT ON to avoid sending row count information for every statement. &lt;font color="#ff0000"&gt;So, this can help, but will only have a measurable effect if you have many many statements,&amp;#160; but in that case you are coding sql wrong anyway.&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Always use the owner name or schema name before the object name to prevent recompilation of stored procedure.&amp;#160; &lt;font color="#ff0000"&gt;Does this mean that by not referencing the owner or schema (which one is it ?? ) objects will &lt;em&gt;always&lt;/em&gt; cause a recompile of the entire stored procedure ? No.&amp;#160; The statement not necessarily the stored procedure, will recompile if the user has a different default schema to the existing compiled statement.&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Avoid using DISTINCT &lt;font color="#ff0000"&gt;Just distinct ? Any thing else ? Unnecessary ORDER BY ?&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Minimize the number of columns in SELECT clause &lt;font color="#ff0000"&gt;So, Select Col1,Col2,Col3 is bad but Select Col1 +’ ‘+ Col2 +’ ‘+Col3 is ok ? Better wording here would be “Return only the data that is required by the application, nothing more, nothing less.”&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Use table variables instead temporary tables. &lt;font color="#ff0000"&gt;Seriously ! What ! Come again.&amp;#160; As a sweeping general statement wrong wrong wrong.&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Use the CTE ( Common Table BLOCKED EXPRESSION instead of derived tables and table variables as much as possible.&lt;font color="#ff0000"&gt; Again, massive over generalisation.&amp;#160; Horses for courses.&amp;#160; Also, didn&amp;#39;t you just say that i should use table variables.&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Avoid using cursors &lt;font color="#ff0000"&gt;Why ? and what should i do instead ?&amp;#160; I have to get the data out some how , what alternatives are there ?&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Don’t use duplicate codes, reuse the code by Views and UDF’s&lt;font color="#ff0000"&gt;&amp;#160; This section is about performance , right ? I would like to see one single instance where using a view ( presumably unindexed ) or a UDF (cough , splutter) improves performance.&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Begin and commit transactions immediately &lt;font color="#ff0000"&gt;Better wording would be “Keep transactions as short as possible, never leave a transaction open while waiting to user input.”&lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Avoid exclusive locks&lt;font color="#ff0000"&gt; Confusing,&amp;#160; in what context ? &lt;/font&gt;&lt;/li&gt;    &lt;li&gt;Use table hints &lt;font color="#ff0000"&gt;BwaaHaa,&amp;#160; this is really a pandora’s box best left by the audience of this book.&lt;/font&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;And so it continues.&amp;#160; I’m trying really hard to not be to scathing or nit-picky about this book, there is some good advice here, but SQL Server is full of caveats , confusing and contradictory best practices and ultimately 90% of the time you can state that “It depends”.&amp;#160; &lt;/p&gt;  &lt;p&gt;Questions are presented with solutions that &lt;em&gt;can&lt;/em&gt; work but are given as 100% solutions not with any degree of warning that that may not always be the case.&amp;#160; Even as a free download, it is way too expensive, and, remembering the target audience, could ultimately do more harm than good. &lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=16046" width="1" height="1"&gt;</description></item><item><title>Extended Events - inaccurate_cardinality_estimate</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/12/06/extended-events-inaccurate-cardinality-estimate.aspx</link><pubDate>Tue, 06 Dec 2011 09:30:00 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:15999</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=15999</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/12/06/extended-events-inaccurate-cardinality-estimate.aspx#comments</comments><description>&lt;p&gt;Extended events have been a bit of a personal “Elephant in the room” for me.&amp;nbsp; I know they are there and I should really get on a start using them but never *quite* have a compelling enough reason.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;So now i really do,&amp;nbsp; after comparing the events in sys.dm_xe_objects between 2008r2 and 2012 I found one that really peaked my interest,&amp;nbsp; inaccurate_cardinality_estimate.&amp;nbsp; This is described as “&lt;em&gt;Occurs when an operator outputs significantly more rows than estimated by the Query Optimizer. Use this event to identify queries that may be using sub-optimal plans due to cardinality estimate inaccuracy. Using this event can have a significant performance overhead so it should only be used when troubleshooting or monitoring specific problems for brief periods of time.&lt;/em&gt;”&lt;/p&gt;
&lt;p&gt;IMO cardinality estimation errors are the number one cause of performance problems.&amp;nbsp; If sqlserver deduces ( or even guesses) an incorrect row estimation then all bets are off,&amp;nbsp; if you get anything approaching a decent plan , its by luck not judgement.&lt;/p&gt;
&lt;p&gt;So, lets see what if we can cause this event to fire.&amp;nbsp; Firing up management studio, we have the new extended events manager,&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_31811C74.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_0A46D33F.png" width="211" height="170" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;which sounds like a fun tool to play with &lt;img style="BORDER-BOTTOM-STYLE:none;BORDER-LEFT-STYLE:none;BORDER-TOP-STYLE:none;BORDER-RIGHT-STYLE:none;" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://sqlblogcasts.com/blogs/sqlandthelike/wlEmoticon-smile_10F9DCC2.png" /&gt; So starting a new session and going to the events library&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_57E2FFBF.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_69BF938C.png" width="523" height="99" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;and filtering by ‘Card’ &lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_62A05714.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_096E6D55.png" width="527" height="96" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Oh , nothing found.&amp;nbsp; Its simply not there , &lt;a href="https://connect.microsoft.com/SQLServer/feedback/details/711792/inaccurate-cardinality-estimate-not-shown-in-extended-events-manager"&gt;here&lt;/a&gt; is a connect item for this issue.&lt;/p&gt;
&lt;p&gt;So , we will have to do this a more ‘manual’ way&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;CREATE&lt;/span&gt; EVENT &lt;span style="COLOR:#0000ff;"&gt;SESSION&lt;/span&gt; inaccurate_cardinality_estimate &lt;span style="COLOR:#0000ff;"&gt;ON&lt;/span&gt; SERVER&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;ADD&lt;/span&gt; EVENT sqlserver.inaccurate_cardinality_estimate&lt;br /&gt;  ( &lt;span style="COLOR:#0000ff;"&gt;ACTION&lt;/span&gt; (sqlserver.plan_handle, sqlserver.sql_text) )&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;ADD&lt;/span&gt; TARGET package0.asynchronous_file_target&lt;br /&gt;  ( &lt;span style="COLOR:#0000ff;"&gt;SET&lt;/span&gt; FILENAME  = N&lt;span style="COLOR:#006080;"&gt;&amp;#39;c:\temp\inaccurate_cardinality_estimate.xel&amp;#39;&lt;/span&gt;, &lt;br /&gt;    metadatafile  = N&lt;span style="COLOR:#006080;"&gt;&amp;#39;c:\temp\inaccurate_cardinality_estimate.xem&amp;#39;&lt;/span&gt; );&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Ok , session defined , lets start it.&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;ALTER&lt;/span&gt; EVENT &lt;span style="COLOR:#0000ff;"&gt;SESSION&lt;/span&gt; inaccurate_cardinality_estimate &lt;span style="COLOR:#0000ff;"&gt;ON&lt;/span&gt; SERVER &lt;span style="COLOR:#0000ff;"&gt;STATE&lt;/span&gt; = START&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;To demonstrate the actual event we need to create and populate a temporary table :&lt;/p&gt;
&lt;div&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;drop&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;table&lt;/span&gt; #newids&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;table&lt;/span&gt; #NewIds&lt;br /&gt;(&lt;br /&gt;id &lt;span style="COLOR:#0000ff;"&gt;char&lt;/span&gt;(36)&lt;br /&gt;)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;insert &lt;span style="COLOR:#0000ff;"&gt;into&lt;/span&gt; #NewIds&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;select&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;top&lt;/span&gt;(100) &lt;br /&gt;       &lt;span style="COLOR:#0000ff;"&gt;cast&lt;/span&gt;(newid() &lt;span style="COLOR:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;char&lt;/span&gt;(36))&lt;br /&gt;  &lt;span style="COLOR:#0000ff;"&gt;from&lt;/span&gt; sys.all_columns a &lt;span style="COLOR:#0000ff;"&gt;cross&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;join&lt;/span&gt; sys.all_columns b&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;If we now execute &lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;declare&lt;/span&gt; @v &lt;span style="COLOR:#0000ff;"&gt;varchar&lt;/span&gt;(10)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;Select&lt;/span&gt; @v=&lt;span style="COLOR:#006080;"&gt;&amp;#39;%XX%&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;select&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;COUNT&lt;/span&gt;(*) &lt;span style="COLOR:#0000ff;"&gt;from&lt;/span&gt; #NewIds &lt;span style="COLOR:#0000ff;"&gt;where&lt;/span&gt; id &lt;span style="COLOR:#0000ff;"&gt;like&lt;/span&gt; @v&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;We will get an estimated row count of 5.37528.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;I can control the exact actual row count by updating a number of rows to start ‘XX’ and thereby create a cardinality estimation error.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;For starters lets update all the rows ( Im wrapping the updates in a transaction and rolling back , for sake of brevity this is not shown)&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;update&lt;/span&gt; &lt;br /&gt; #NewIds&lt;br /&gt; &lt;span style="COLOR:#0000ff;"&gt;set&lt;/span&gt;  id = &lt;span style="COLOR:#006080;"&gt;&amp;#39;XX&amp;#39;&lt;/span&gt;+&lt;span style="COLOR:#0000ff;"&gt;left&lt;/span&gt;(id,20)&lt;br /&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;declare&lt;/span&gt; @v &lt;span style="COLOR:#0000ff;"&gt;varchar&lt;/span&gt;(10)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;Select&lt;/span&gt; @v=&lt;span style="COLOR:#006080;"&gt;&amp;#39;%XX%&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;select&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;COUNT&lt;/span&gt;(*) &lt;span style="COLOR:#0000ff;"&gt;from&lt;/span&gt; #NewIds &lt;span style="COLOR:#0000ff;"&gt;where&lt;/span&gt; id &lt;span style="COLOR:#0000ff;"&gt;like&lt;/span&gt; @v&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;Then plan for the select shows a cardinality error, as expected &lt;/div&gt;
&lt;div&gt;&lt;br /&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_024F30DD.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_3E0EC990.png" width="243" height="130" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;100 actual , 5.37528 expected.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Stop the extended events session&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;ALTER&lt;/span&gt; EVENT &lt;span style="COLOR:#0000ff;"&gt;SESSION&lt;/span&gt; inaccurate_cardinality_estimate &lt;span style="COLOR:#0000ff;"&gt;ON&lt;/span&gt; SERVER &lt;span style="COLOR:#0000ff;"&gt;STATE&lt;/span&gt; = STOP&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;and all being well , in the c:\temp folder you will see an extended event log file.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Open that in management studio &lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_68E72DA2.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_76B9739D.png" width="524" height="268" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;/div&gt;
&lt;p&gt;There is the event, nice.&amp;nbsp; But hold on one cotton picking minute, look at the row counts.&amp;nbsp; Estimated = 5 , actual = 26 !?!&lt;/p&gt;
&lt;p&gt;What happens if we repeat this operation but doubling the rows in the temp table&lt;/p&gt;
&lt;p&gt;If we double the amount of rows in our temp table to 200,&amp;nbsp; our estimate rows in the plan will show as 10.7506 and actual as 200. In the extended event we see :&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_2F641DAB.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_2844E133.png" width="520" height="275" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So the estimated count is shown as floor(row estimate) and the event is fired when the actual row count goes over 5*plan estimate, which is why actual is shown here as 53 not 200.&amp;nbsp; Notice that we also have the plan_handle and the node_id if we wish to tie this back to an exact operator in our system.&lt;/p&gt;
&lt;p&gt;Quite why this is an extended event and not a plan warning , i really have no idea,&amp;nbsp; still its nice to know its there. &lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=15999" width="1" height="1"&gt;</description><category domain="http://sqlblogcasts.com/blogs/sqlandthelike/archive/tags/Plan+Warnings/default.aspx">Plan Warnings</category></item><item><title>MythBusting–“Table variables have no statistics”</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/12/02/mythbusting-table-variables-have-no-statistics.aspx</link><pubDate>Fri, 02 Dec 2011 20:20:28 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:15998</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=15998</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/12/02/mythbusting-table-variables-have-no-statistics.aspx#comments</comments><description>&lt;p&gt;Ok, as myths go, its a pretty weak one.&amp;#160; In fact, it is true, &lt;a href="http://msdn.microsoft.com/en-us/library/dd535534(v=sql.100).aspx"&gt;this&lt;/a&gt; whitepaper explicitly states that.&amp;#160; But hand in hand with that statement goes another one, “Table variables will always estimate to one row”.&amp;#160; This is most definitely false,&amp;#160; if there are no statistics then sql server can, at times, default to its ‘guessing’ of distribution of data based upon row counts.&amp;#160; This behaviour can even further muddy the water of the old “Which is better, table variables or temp tables” argument.&lt;/p&gt;  &lt;p&gt;To demonstrate this, firstly we need to populate a numbers table&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;table&lt;/span&gt; numbers&lt;br /&gt;(&lt;br /&gt;Num &lt;span style="color:#0000ff;"&gt;integer&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;primary&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;key&lt;/span&gt;&lt;br /&gt;)&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;insert &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; numbers&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;top&lt;/span&gt;(1000) ROW_NUMBER() &lt;span style="color:#0000ff;"&gt;over&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;order&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;by&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;select&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;))&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;from&lt;/span&gt;   sys.columns a &lt;span style="color:#0000ff;"&gt;cross&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;join&lt;/span&gt; sys.columns b&lt;br /&gt;&lt;/pre&gt;

  &lt;br /&gt;&lt;/div&gt;



&lt;p&gt;Now we execute the following code&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippetWrapper"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;Declare&lt;/span&gt; @TableVar &lt;span style="color:#0000ff;"&gt;Table&lt;/span&gt;&lt;br /&gt;(&lt;br /&gt;ID &lt;span style="color:#0000ff;"&gt;integer&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;primary&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;key&lt;/span&gt;,&lt;br /&gt;Mod10 &lt;span style="color:#0000ff;"&gt;integer&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;insert &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @TableVar(ID,Mod10)&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;top&lt;/span&gt;(20) num,num%10 &lt;br /&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; numbers&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;order&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;by&lt;/span&gt; num&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Select&lt;/span&gt; tv.Id,num&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt;  @TableVar tv&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;join&lt;/span&gt;  numbers&lt;br /&gt;   &lt;span style="color:#0000ff;"&gt;on&lt;/span&gt;  tv.ID = num&lt;br /&gt;&lt;/pre&gt;

    &lt;br /&gt;&lt;/div&gt;

  &lt;div&gt;
    &lt;br /&gt;and looking at the execution plan, we see :&lt;/div&gt;

  &lt;div&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_66DDE082.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_0A97081D.png" width="226" height="88" /&gt;&lt;/a&gt;&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;1 Row estimated and 20 rows actual, as you may well expect.&amp;#160; Now add ‘OPTION(RECOMPILE)’&amp;#160; the plan is now different.&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_25632E29.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_1724B539.png" width="238" height="84" /&gt;&lt;/a&gt;&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;Look at that an accurate row estimation.&amp;#160; How about if we are filter to the statement say ‘Mod10=0’&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;
    &lt;br /&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_1CFF58D2.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_0EC0DFE2.png" width="244" height="84" /&gt;&lt;/a&gt;&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;Another different but wrong estimation.&amp;#160; This is because table variables dont have statistics, but we do have row counts.&amp;#160; It is worth pointing out at this point that these are the same numbers you will get if you did these operations on a normal ‘permanent’ table, but had turned off AUTO STATISTICS.&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;Obviously in a production environment, you would only be using RECOMPILE in ‘special’ circumstances, right ?&amp;#160; So, this isn&amp;#39;t an issue.&amp;#160; All your table variables will be estimating as one row.&amp;#160; Wrong,&amp;#160; I would be willing to bet that a surprisingly high number are estimating as something else.&amp;#160; If you are so inclined, so can probably find quite a few in the dmv sys.dm_exec_query_plan.&amp;#160; So, how does this happen ? Well,&amp;#160; in a way its nothing to do with table variables per se , but if you are joining to another table, then if (and when) that table has its stats updated then that will cause the statement to recompile and , surprise , surprise , you have a table variable with an estimate &amp;gt; 1.&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;OK…&amp;#160; So lets step through that.&amp;#160; Ignore the extra Select statement that counts from adventureworks,&amp;#160; its just there to create a more ‘complicated’ stored procedure and we get multiple statements cached in the plan.&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div id="codeSnippetWrapper"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;&lt;span style="color:#0000ff;"&gt;drop&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;table&lt;/span&gt; IDs&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;table&lt;/span&gt; IDs&lt;br /&gt;(&lt;br /&gt;Id &lt;span style="color:#0000ff;"&gt;integer&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;primary&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;key&lt;/span&gt;,padding &lt;span style="color:#0000ff;"&gt;char&lt;/span&gt;(255)&lt;br /&gt;)&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;insert &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; IDs(Id,padding)&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;top&lt;/span&gt;(1) num,&lt;span style="color:#006080;"&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; numbers&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;order&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;by&lt;/span&gt; num&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;drop&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;procedure&lt;/span&gt; TableVarTest&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;create&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;procedure&lt;/span&gt; TableVarTest&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;as&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;declare&lt;/span&gt; @TableVar &lt;span style="color:#0000ff;"&gt;Table&lt;/span&gt;&lt;br /&gt;(&lt;br /&gt;ID &lt;span style="color:#0000ff;"&gt;integer&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;,&lt;br /&gt;Mod10 &lt;span style="color:#0000ff;"&gt;integer&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;insert &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @TableVar(ID,Mod10)&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;top&lt;/span&gt;(20) num,num%10&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; numbers&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;order&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;by&lt;/span&gt; num&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;select&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;COUNT&lt;/span&gt;(*)&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt;  AdventureWorks2008r2.dbo.Customer C&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;join&lt;/span&gt;  AdventureWorks2008r2.dbo.CustomerOrders CO&lt;br /&gt;   &lt;span style="color:#0000ff;"&gt;on&lt;/span&gt;  C.CustomerId = CO.CustomerId&lt;br /&gt;   &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Select&lt;/span&gt; tv.Id,IDs.id&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt;  @TableVar tv&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;join&lt;/span&gt;  IDs&lt;br /&gt;   &lt;span style="color:#0000ff;"&gt;on&lt;/span&gt;  tv.ID = IDs.Id&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;where&lt;/span&gt;  mod10 =0&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;

    &lt;br /&gt;&lt;/div&gt;

  &lt;div&gt;On first execution the join of the table variable to IDs produces…&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_34B69038.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_26781748.png" width="237" height="92" /&gt;&lt;/a&gt;&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div&gt;Now, lets add some more data to ID’s and force a recompile just for good measure :&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;

  &lt;div id="codeSnippetWrapper"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;insert &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; IDs(Id,padding)&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Select&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;top&lt;/span&gt;(1000) num,&lt;span style="color:#006080;"&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; numbers&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;where&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;exists&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;select&lt;/span&gt; id &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; IDs &lt;span style="color:#0000ff;"&gt;where&lt;/span&gt; id = num )&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;order&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;by&lt;/span&gt; num&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;exec&lt;/span&gt; sp_recompile ids&lt;/pre&gt;

    &lt;br /&gt;&lt;/div&gt;
and then re-execute the stored procedure &lt;/div&gt;

&lt;div&gt;&amp;#160;&lt;/div&gt;

&lt;div&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_5A400D99.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_12EAB7A7.png" width="244" height="86" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div&gt;&amp;#160;&lt;/div&gt;

&lt;div&gt;So, one myth busted and one proved, not bad for one blog.&lt;/div&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=15998" width="1" height="1"&gt;</description></item><item><title>Execution plan warnings–The final chapter</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/11/29/execution-plan-warnings-the-final-chapter.aspx</link><pubDate>Tue, 29 Nov 2011 10:42:00 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:15985</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=15985</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/11/29/execution-plan-warnings-the-final-chapter.aspx#comments</comments><description>&lt;p&gt;In my previous posts (&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/10/17/implicit-conversions-warning.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/10/19/more-denali-execution-plan-warning-goodies.aspx"&gt;here&lt;/a&gt;), I showed examples of some of the execution plan warnings that have been added to SQL Server 2012.&amp;nbsp; There is one other warning that is of interest to me : “Unmatched Indexes”.&lt;/p&gt;
&lt;p&gt;Firstly, how do I know this is the final one ?&amp;nbsp; The plan is an XML document, right ? So that means that it can have an accompanying XSD.&amp;nbsp; As an XSD is a schema definition, we can poke around inside it to find interesting things that *could* be in the final XML file.&lt;/p&gt;
&lt;p&gt;The showplan schema is stored in the folder Microsoft SQL Server\110\Tools\Binn\schemas\sqlserver\2004\07\showplan and by comparing schemas over releases you can get a really good idea of any new functionality that has been added.&lt;/p&gt;
&lt;p&gt;Here is the section of the Sql Server 2012 showplan schema that has been interesting me so far :&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:complexType&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;AffectingConvertWarningType&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:annotation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:documentation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Warning information for plan-affecting type conversion&lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:documentation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:annotation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:sequence&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#008000;"&gt;&amp;lt;!-- Additional information may go here when available --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:sequence&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:attribute&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;ConvertIssue&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;use&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;required&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:simpleType&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:restriction&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;base&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;xsd:string&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:enumeration&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;value&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Cardinality Estimate&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:enumeration&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;value&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Seek Plan&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="COLOR:#008000;"&gt;&amp;lt;!-- to be extended here --&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:restriction&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:simpleType&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:attribute&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:attribute&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Expression&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;xsd:string&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;use&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;required&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:complexType&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:complexType&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;WarningsType&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:annotation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:documentation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;List of all possible iterator or query specific warnings (e.g. hash spilling, no join predicate)&lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:documentation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:annotation&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:choice&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;minOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;maxOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;unbounded&amp;quot;&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:element&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;ColumnsWithNoStatistics&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;shp:ColumnReferenceListType&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;minOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;maxOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:element&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;SpillToTempDb&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;shp:SpillToTempDbType&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;minOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;maxOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;unbounded&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:element&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;Wait&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;shp:WaitWarningType&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;minOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;maxOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;unbounded&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:element&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;PlanAffectingConvert&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;shp:AffectingConvertWarningType&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;minOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;maxOccurs&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;unbounded&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:choice&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:attribute&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;NoJoinPredicate&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;xsd:boolean&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;use&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;optional&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:attribute&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;SpatialGuess&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;xsd:boolean&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;use&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;optional&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:attribute&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;UnmatchedIndexes&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;xsd:boolean&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;use&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;optional&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:attribute&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;name&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;FullUpdateForOnlineIndexBuild&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;type&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;xsd:boolean&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#ff0000;"&gt;use&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;=&amp;quot;optional&amp;quot;&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#800000;"&gt;xsd:complexType&lt;/span&gt;&lt;span style="COLOR:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;I especially like the “to be extended here” comment,&amp;nbsp; high hopes that we will see more of these in the future.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;So “Unmatched Indexes” was a warning that I couldn’t get and many thanks must go to Fabiano Amorim (&lt;a href="http://blogfabiano.com/"&gt;b&lt;/a&gt;|&lt;a href="http://twitter.com/mcflyamorim"&gt;t&lt;/a&gt;) for showing me the way.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Filtered indexes were introduced in Sql Server 2008 and are really useful if you only need to index only a portion of the data within a table.&amp;nbsp; However,&amp;nbsp; if your SQL code uses a variable as a predicate on the filtered data that matches the filtered condition, then the filtered index cannot be used as, naturally,&amp;nbsp; the value in the variable may ( and probably will ) change and therefore will need to read data outside the index.&amp;nbsp; As an aside,&amp;nbsp; you could use option(recompile) here , in which case the optimizer will build a plan specific to the variable values and use the filtered index,&amp;nbsp; but that can bring about other problems.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;To demonstrate this warning, we need to generate some test data :&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;DROP&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;TABLE&lt;/span&gt; #TestTab1&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;CREATE&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;TABLE&lt;/span&gt; #TestTab1 (Col1     &lt;span style="COLOR:#0000ff;"&gt;Int&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;null&lt;/span&gt;,&lt;br /&gt;                       Col2     &lt;span style="COLOR:#0000ff;"&gt;Char&lt;/span&gt;(7500) &lt;span style="COLOR:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;null&lt;/span&gt;,&lt;br /&gt;                       Quantity &lt;span style="COLOR:#0000ff;"&gt;Int&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;not&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;INSERT &lt;span style="COLOR:#0000ff;"&gt;INTO&lt;/span&gt; #TestTab1 &lt;span style="COLOR:#0000ff;"&gt;VALUES&lt;/span&gt; (1,1,1),(1,2,5),(1,2,10),(1,3,20),&lt;br /&gt;                            (2,1,101),(2,2,105),(2,2,110),(2,3,120)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;and then add a filtered index&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;CREATE&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;INDEX&lt;/span&gt; ixFilter &lt;span style="COLOR:#0000ff;"&gt;ON&lt;/span&gt; #TestTab1 (Col1)&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;WHERE&lt;/span&gt; Quantity = 122&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Now if we execute&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;SELECT&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;COUNT&lt;/span&gt;(*) &lt;span style="COLOR:#0000ff;"&gt;FROM&lt;/span&gt; #TestTab1 &lt;span style="COLOR:#0000ff;"&gt;WHERE&lt;/span&gt; Quantity = 122&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;We will see the filtered index being scanned&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_29A99D1F.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_54820131.png" width="544" height="78" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But if we parameterize the query &lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE:none;TEXT-ALIGN:left;PADDING-BOTTOM:0px;LINE-HEIGHT:12pt;BACKGROUND-COLOR:#f4f4f4;MARGIN:0em;BORDER-LEFT-STYLE:none;PADDING-LEFT:0px;WIDTH:100%;PADDING-RIGHT:0px;FONT-FAMILY:&amp;#39;Courier New&amp;#39;, courier, monospace;DIRECTION:ltr;BORDER-TOP-STYLE:none;COLOR:black;BORDER-RIGHT-STYLE:none;FONT-SIZE:8pt;OVERFLOW:visible;PADDING-TOP:0px;" id="codeSnippet"&gt;&lt;span style="COLOR:#0000ff;"&gt;DECLARE&lt;/span&gt; @i &lt;span style="COLOR:#0000ff;"&gt;INT&lt;/span&gt; = 122&lt;br /&gt;&lt;span style="COLOR:#0000ff;"&gt;SELECT&lt;/span&gt; &lt;span style="COLOR:#0000ff;"&gt;COUNT&lt;/span&gt;(*) &lt;span style="COLOR:#0000ff;"&gt;FROM&lt;/span&gt; #TestTab1 &lt;span style="COLOR:#0000ff;"&gt;WHERE&lt;/span&gt; Quantity = @i&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;The plan is very different&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_144BE7B7.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_3B19FDF7.png" width="524" height="82" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;a table scan, as the value of the variable used in the predicate can change at run time, and also we see the familiar warning triangle.&lt;/p&gt;
&lt;p&gt;If we now look at the properties pane, we will see two pieces of information “Warnings” and “UnmatchedIndexes”.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblogcasts.com/blogs/sqlandthelike/image_28D13735.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="image" border="0" alt="image" src="http://sqlblogcasts.com/blogs/sqlandthelike/image_thumb_3AADCB02.png" width="365" height="174" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, handily, we are being told which filtered index is not being used due to parameterization.&lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=15985" width="1" height="1"&gt;</description><category domain="http://sqlblogcasts.com/blogs/sqlandthelike/archive/tags/Plan+Warnings/default.aspx">Plan Warnings</category></item><item><title>Blogging from 37,000ft</title><link>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/11/06/blogging-from-37-000ft.aspx</link><pubDate>Sun, 06 Nov 2011 15:23:42 GMT</pubDate><guid isPermaLink="false">fa8c4e8e-46a3-4193-8264-2c1a9cb3475d:15964</guid><dc:creator>Dave Ballantyne</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://sqlblogcasts.com/blogs/sqlandthelike/rsscomments.aspx?PostID=15964</wfw:commentRss><comments>http://sqlblogcasts.com/blogs/sqlandthelike/archive/2011/11/06/blogging-from-37-000ft.aspx#comments</comments><description>&lt;p&gt;Im currently on my way to Sql Rally nordic and looking forward to a few days of full on SQL geekery and “Unleashing my inner Viking”.&amp;#160; I shall be speaking on Wednesday afternoon on one of my favourite subjects “Cursors are Evil”.&amp;#160; Ok,&amp;#160; so lets put it into perspective, “Evil” is a bit dramatic , but “Often use inappropriately and can cause serious performance bottlenecks” didn&amp;#39;t have quite the same ring &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://sqlblogcasts.com/blogs/sqlandthelike/wlEmoticon-smile_72844F0D.png" /&gt;&lt;/p&gt;  &lt;p&gt;If you are not going to be at SQL Rally,&amp;#160; im going to be repeating it at the Leeds and Manchester user groups on the 23rd and 24th of November respectively.&amp;#160; Presenting with me on these nights will be James Boother, so make it along to those if you can.&amp;#160; I look forward to seeing you at one of these events.&lt;/p&gt;&lt;img src="http://sqlblogcasts.com/aggbug.aspx?PostID=15964" width="1" height="1"&gt;</description></item></channel></rss>
