<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	
	>
<channel>
	<title>
	Comments on: Covering Index because it’s Covering up the truth?	</title>
	<atom:link href="https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/feed/" rel="self" type="application/rss+xml" />
	<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/</link>
	<description></description>
	<lastBuildDate>Wed, 25 May 2011 16:35:11 +0000</lastBuildDate>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>
		By: Rob Farley		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1928</link>

		<dc:creator><![CDATA[Rob Farley]]></dc:creator>
		<pubDate>Wed, 25 May 2011 16:35:11 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1928</guid>

					<description><![CDATA[Hi Amit,
Not quite. There is nowhere that tells us how many rows are being satisfied by the Seek Predicate and then need to be checked by the Residual.
But for the mostpart, I agree with you wholeheartedly.
Thanks for the comment!]]></description>
			<content:encoded><![CDATA[<p>Hi Amit,<br />
Not quite. There is nowhere that tells us how many rows are being satisfied by the Seek Predicate and then need to be checked by the Residual.<br />
But for the mostpart, I agree with you wholeheartedly.<br />
Thanks for the comment!</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Amit Banerjee		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1927</link>

		<dc:creator><![CDATA[Amit Banerjee]]></dc:creator>
		<pubDate>Wed, 25 May 2011 16:20:31 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1927</guid>

					<description><![CDATA[The important point here is that consider the amount of rows being fetched and the number of executes involved in evaluating the join/filter condition in the plans. This is one of the reason I am still a fan of the text execution plan format. It lets me look at the operator, residuals, rows and executes along with the estimates. However, I am old school and people might differ with me on the use of text vs XML plans.
Just because it&#039;s a SEEK doesn&#039;t mean that you have the best plan! That is an urban-legend. :)]]></description>
			<content:encoded><![CDATA[<p>The important point here is that consider the amount of rows being fetched and the number of executes involved in evaluating the join/filter condition in the plans. This is one of the reason I am still a fan of the text execution plan format. It lets me look at the operator, residuals, rows and executes along with the estimates. However, I am old school and people might differ with me on the use of text vs XML plans.<br />
Just because it&#8217;s a SEEK doesn&#8217;t mean that you have the best plan! That is an urban-legend. 🙂</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Rob Farley		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1926</link>

		<dc:creator><![CDATA[Rob Farley]]></dc:creator>
		<pubDate>Wed, 25 May 2011 13:19:11 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1926</guid>

					<description><![CDATA[No problem, Robert. I figure there are scenarios where an Index Seek is in place, and people just assume it&#039;s ideal, because people just love Seeks and hate Scans.]]></description>
			<content:encoded><![CDATA[<p>No problem, Robert. I figure there are scenarios where an Index Seek is in place, and people just assume it&#8217;s ideal, because people just love Seeks and hate Scans.</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Robert L Davis		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1925</link>

		<dc:creator><![CDATA[Robert L Davis]]></dc:creator>
		<pubDate>Wed, 25 May 2011 04:03:16 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1925</guid>

					<description><![CDATA[Excellent point Rob. Having a 2nd inequality value in the index doesn&#039;t improve the usage. If anything, it will make the index a little bit bigger.
Anywho, I definitely agree with what you are saying here. I just got distracted by the fact that the covered index shouldn&#039;t have been used in the first place.]]></description>
			<content:encoded><![CDATA[<p>Excellent point Rob. Having a 2nd inequality value in the index doesn&#8217;t improve the usage. If anything, it will make the index a little bit bigger.<br />
Anywho, I definitely agree with what you are saying here. I just got distracted by the fact that the covered index shouldn&#8217;t have been used in the first place.</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Rob Farley		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1924</link>

		<dc:creator><![CDATA[Rob Farley]]></dc:creator>
		<pubDate>Wed, 25 May 2011 02:24:39 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1924</guid>

					<description><![CDATA[Indeed Paul. A filtered index is definitely better, and if it&#039;s covering as well, then great. A filtered index whose predicates match the query&#039;s predicates doesn&#039;t even need to check what&#039;s there, it just grabs all the rows. It&#039;s a thing of beauty, with no Residualicity.]]></description>
			<content:encoded><![CDATA[<p>Indeed Paul. A filtered index is definitely better, and if it&#8217;s covering as well, then great. A filtered index whose predicates match the query&#8217;s predicates doesn&#8217;t even need to check what&#8217;s there, it just grabs all the rows. It&#8217;s a thing of beauty, with no Residualicity.</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Paul White		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1923</link>

		<dc:creator><![CDATA[Paul White]]></dc:creator>
		<pubDate>Wed, 25 May 2011 02:18:34 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1923</guid>

					<description><![CDATA[Hi Rob,
Another important consideration people overlook with seeks is how it knows when to stop...
Just thought I&#039;d chip that in ;c)
Paul]]></description>
			<content:encoded><![CDATA[<p>Hi Rob,<br />
Another important consideration people overlook with seeks is how it knows when to stop&#8230;<br />
Just thought I&#8217;d chip that in ;c)<br />
Paul</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Rob Farley		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1922</link>

		<dc:creator><![CDATA[Rob Farley]]></dc:creator>
		<pubDate>Wed, 25 May 2011 02:10:17 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1922</guid>

					<description><![CDATA[Of course, Robert, the ideal index for this query is the filtered index that I put at the end of the original post (&lt;a href=&quot;http://blogs.lobsterpot.com.au/2011/05/19/covering-schmuvvering-when-a-covering-index-is-actually-rubbish/&quot; rel=&quot;nofollow ugc&quot;&gt;http://sqlblog.com/blogs/rob_farley/archive/2011/05/19/covering-schmuvvering-when-a-covering-index-is-actually-rubbish.aspx&lt;/a&gt;), which causes an Index Scan that doesn&#039;t check the predicates at all.]]></description>
			<content:encoded><![CDATA[<p>Of course, Robert, the ideal index for this query is the filtered index that I put at the end of the original post (<a href="http://blogs.lobsterpot.com.au/2011/05/19/covering-schmuvvering-when-a-covering-index-is-actually-rubbish/" rel="nofollow ugc">http://sqlblog.com/blogs/rob_farley/archive/2011/05/19/covering-schmuvvering-when-a-covering-index-is-actually-rubbish.aspx</a>), which causes an Index Scan that doesn&#8217;t check the predicates at all.</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Rob Farley		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1921</link>

		<dc:creator><![CDATA[Rob Farley]]></dc:creator>
		<pubDate>Wed, 25 May 2011 02:00:23 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1921</guid>

					<description><![CDATA[Hi Robert,
Thanks for your comment.
I agree that a better index could be used. But my point is that a Covering Index Seek hides a lot of the truth if you don&#039;t know to look at the Residual Predicate.
But tell me - why have you put ReorderPoint in as your third key? Can you explain why you consider this is better than having it in the Included list?
Rob]]></description>
			<content:encoded><![CDATA[<p>Hi Robert,<br />
Thanks for your comment.<br />
I agree that a better index could be used. But my point is that a Covering Index Seek hides a lot of the truth if you don&#8217;t know to look at the Residual Predicate.<br />
But tell me &#8211; why have you put ReorderPoint in as your third key? Can you explain why you consider this is better than having it in the Included list?<br />
Rob</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Robert L Davis		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1920</link>

		<dc:creator><![CDATA[Robert L Davis]]></dc:creator>
		<pubDate>Wed, 25 May 2011 00:58:20 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1920</guid>

					<description><![CDATA[Reading this for the first time today, and I agree with the sentiment, but disagree with the demo.
The &#034;Covering index&#034; created for the sample is not a true covering index. Columns that should be in the key of the index are in the Includes list.
I&#039;m assuming that this was contrived on purpose to demonstrate how a covering index seek may not be any better than a clustered scan. Let&#039;s skip the whole fill factor aspect of it for now. This was admittedly contrived to force the seek of the covering index to require more logical reads (16) than the clustered index scan (15). Setting fill factor to the default value (100) reduces the logical page reads to 7.
However, even more telling is that simply creating the correctcovering index reduces the page reads to 2.
Using your example, I created the 2 following indexes:
CREATE INDEX rf_ix_Covering ON Production.Product(DaysToManufacture) 
INCLUDE (Name, ProductNumber, Size, ReorderPoint, Color);
CREATE INDEX rf_ix_TrueCovering ON Production.Product(Color, DaysToManufacture, ReorderPoint) 
INCLUDE (Name, ProductNumber, Size) ;
Then I ran the following forms of the query forcing it to use your covering index, the clustered index, and allowing it to pick its own index (it uses the covering index I created). I also used the recompile option and enabled Statistics IO and actual execution plan settings:
SELECT Name, ProductNumber 
FROM Production.Product with(index(rf_ix_Covering))
WHERE DaysToManufacture &#060; 4 
AND ReorderPoint &#060; 100 
AND Color = &#039;Red&#039;
Option(recompile)
SELECT Name, ProductNumber 
FROM Production.Product with(index(1))
WHERE DaysToManufacture &#060; 4 
AND ReorderPoint &#060; 100 
AND Color = &#039;Red&#039;
Option(recompile)
SELECT Name, ProductNumber 
FROM Production.Product
WHERE DaysToManufacture &#060; 4 
AND ReorderPoint &#060; 100 
AND Color = &#039;Red&#039;
Option(recompile)
Statistics IO output (with row counts removed and LOB counts truncated) was:
Table &#039;Product&#039;. Scan count 1, logical reads 7, physical reads 0, read-ahead reads 0...
Table &#039;Product&#039;. Scan count 1, logical reads 15, physical reads 0, read-ahead reads 0...
Table &#039;Product&#039;. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0...
And the actual execution plans showed that the cost of the three queries when executed as a single batch are respectively 29%, 56%, and 15% of the total cost of the batch. This clearly demonstrates that the &#034;bad covering index&#034; is almost 50% the cost of the clustered index scan, and twice the cost of using the appropriate covering index.]]></description>
			<content:encoded><![CDATA[<p>Reading this for the first time today, and I agree with the sentiment, but disagree with the demo.<br />
The &quot;Covering index&quot; created for the sample is not a true covering index. Columns that should be in the key of the index are in the Includes list.<br />
I&#8217;m assuming that this was contrived on purpose to demonstrate how a covering index seek may not be any better than a clustered scan. Let&#8217;s skip the whole fill factor aspect of it for now. This was admittedly contrived to force the seek of the covering index to require more logical reads (16) than the clustered index scan (15). Setting fill factor to the default value (100) reduces the logical page reads to 7.<br />
However, even more telling is that simply creating the correctcovering index reduces the page reads to 2.<br />
Using your example, I created the 2 following indexes:<br />
CREATE INDEX rf_ix_Covering ON Production.Product(DaysToManufacture)<br />
INCLUDE (Name, ProductNumber, Size, ReorderPoint, Color);<br />
CREATE INDEX rf_ix_TrueCovering ON Production.Product(Color, DaysToManufacture, ReorderPoint)<br />
INCLUDE (Name, ProductNumber, Size) ;<br />
Then I ran the following forms of the query forcing it to use your covering index, the clustered index, and allowing it to pick its own index (it uses the covering index I created). I also used the recompile option and enabled Statistics IO and actual execution plan settings:<br />
SELECT Name, ProductNumber<br />
FROM Production.Product with(index(rf_ix_Covering))<br />
WHERE DaysToManufacture &lt; 4<br />
AND ReorderPoint &lt; 100<br />
AND Color = &#8216;Red&#8217;<br />
Option(recompile)<br />
SELECT Name, ProductNumber<br />
FROM Production.Product with(index(1))<br />
WHERE DaysToManufacture &lt; 4<br />
AND ReorderPoint &lt; 100<br />
AND Color = &#8216;Red&#8217;<br />
Option(recompile)<br />
SELECT Name, ProductNumber<br />
FROM Production.Product<br />
WHERE DaysToManufacture &lt; 4<br />
AND ReorderPoint &lt; 100<br />
AND Color = &#8216;Red&#8217;<br />
Option(recompile)<br />
Statistics IO output (with row counts removed and LOB counts truncated) was:<br />
Table &#8216;Product&#8217;. Scan count 1, logical reads 7, physical reads 0, read-ahead reads 0&#8230;<br />
Table &#8216;Product&#8217;. Scan count 1, logical reads 15, physical reads 0, read-ahead reads 0&#8230;<br />
Table &#8216;Product&#8217;. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0&#8230;<br />
And the actual execution plans showed that the cost of the three queries when executed as a single batch are respectively 29%, 56%, and 15% of the total cost of the batch. This clearly demonstrates that the &quot;bad covering index&quot; is almost 50% the cost of the clustered index scan, and twice the cost of using the appropriate covering index.</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: Rob Farley		</title>
		<link>https://lobsterpot.com.au/blog/2011/05/25/covering-index-because-its-covering-up-the-truth/#comment-1919</link>

		<dc:creator><![CDATA[Rob Farley]]></dc:creator>
		<pubDate>Wed, 25 May 2011 00:23:30 +0000</pubDate>
		<guid isPermaLink="false">http://blogs.lobsterpot.com.au/?p=2955#comment-1919</guid>

					<description><![CDATA[I really hope everyone notices your wink there, Alex. :)]]></description>
			<content:encoded><![CDATA[<p>I really hope everyone notices your wink there, Alex. 🙂</p>
]]></content:encoded>
		
			</item>
	</channel>
</rss>
