<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results matching tags 'Query Plans', 'training', and 'indexes'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Query+Plans,training,indexes&amp;orTags=0</link><description>Search results matching tags 'Query Plans', 'training', and 'indexes'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Geek City: Ordered Seeks and Scans</title><link>http://sqlblog.com/blogs/kalen_delaney/archive/2011/01/21/ordered-seeks-and-scans.aspx</link><pubDate>Fri, 21 Jan 2011 23:28:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:32833</guid><dc:creator>Kalen Delaney</dc:creator><description>&lt;P&gt;I got a couple of really great questions during my &lt;A href="http://www.vconferenceonline.com/event/home.aspx?id=129"&gt;SSWUG Workshop this morning&lt;/A&gt;, as I was discussing seeks and scans, and since the answers to the two questions are very related, I decided to address both of them in more detail in this blog post. &lt;/P&gt;
&lt;P&gt;Most people think about a seek operation as retrieving just one or a few rows, and a scan as accessing the entire table&amp;nbsp; or index leaf level.&amp;nbsp; And that usually is what I mean when I am just describing SQL Server behavior. But there is also the possibility that SQL Server could perform a 'partial scan', starting at some row in the table or index leaf, and then scanning only to a particular ending row. However, there is no operator in a query plan called 'partial scan'.&amp;nbsp; So how can you tell when you have one?&lt;/P&gt;
&lt;P&gt;Before I specifically answer that, let me tell you about the first question in the workshop this morning. I had been showing the Properties window (available from View/Properties Window), pointing out that when you click on one of the icons in a graphical query plan, the Properties window shows the same information that is in the yellow box that pops up, plus additional information. One of the values shown in one called 'Ordered', and when 'Ordered' has the value true, then there is also a value called 'Scan Direction', which might make you think that ordering is only relevant to scans.&amp;nbsp; But you will see True values for 'Ordered' even when the operation is a seek. This is usually an indication that a partial scan is being performed. &lt;/P&gt;
&lt;P&gt;And because I was talking about heaps being unordered sets of rows, one of the delegates asked: "Are index seeks against a heap always unordered?" &lt;/P&gt;
&lt;P&gt;The answer is, of course, "it depends".&amp;nbsp; If you have a covered query, the index access could be an ordered seek of the covering index, even though the underlying table is a heap. Here is an example from the AdventureWorks database. I make a copy of the Sales.SalesOrderHeader table, so it is a heap, and then build a nonclustered index on the Freight column. &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;IF EXISTS (SELECT * FROM dbo.SalesOrderHeader) &lt;BR&gt;&amp;nbsp;&amp;nbsp; DROP TABLE dbo.SalesOrderHeader; &lt;BR&gt;GO &lt;BR&gt;SELECT * INTO dbo.SalesOrderHeader &lt;BR&gt;FROM Sales.SalesOrderHeader; &lt;BR&gt;GO &lt;BR&gt;CREATE INDEX ix_Freight ON dbo.SalesOrderHeader(Freight); &lt;BR&gt;GO&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Then I look at the plan for a covered query using the ix_Freight index:&lt;/P&gt;
&lt;P&gt;SELECT AVG(Freight) &lt;BR&gt;FROM dbo.SalesOrderHeader &lt;BR&gt;WHERE Freight &amp;lt; 100;&lt;/P&gt;
&lt;P&gt;And here is the plan showing the index seek:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/kalen_delaney/image_0C2A1714.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://sqlblog.com/blogs/kalen_delaney/image_thumb_0A0D184B.png" width=699 height=164&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;And the Properties sheet for the Index Seek shows that Ordered - True and Scan Direction = FORWARD.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/kalen_delaney/image_761385B4.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://sqlblog.com/blogs/kalen_delaney/image_thumb_62862613.png" width=262 height=366&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;This is an example of an ordered seek on a nonclustered index, or what we can think of as a partial scan, or range scan. &lt;/P&gt;
&lt;P&gt;The other question during the workshop was how to tell if the seek was really a range scan. Part of the answer is to look for the Ordered = True value, as I just illustrated. Another thing to notice in the graphical query plan is the thickness of the line moving rows to the left from the Index Seek, indicating that LOTS of rows are being returned from the Seek. That's another clue that we have a partial scan.&lt;/P&gt;
&lt;P&gt;We can also get partial scans with clustered indexes. I'll build a clustered index on my new table.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;CREATE CLUSTERED INDEX clus_OrderID ON dbo.SalesOrderHeader(SalesOrderID); &lt;BR&gt;GO&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;There are 31465 rows in the dbo.SalesOrderHeader table, with SalesOrderID values ranging from 43659 to 75123. I'll SELECT a small range of data:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;SELECT * FROM dbo.SalesOrderHeader &lt;BR&gt;WHERE SalesOrderID &amp;lt; 44000&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The plan shows a Clustered Index Seek, and the Properties shows Ordered = True.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;If I make the range bigger, and look for SalesOrderID &amp;lt; 60000, I still get an Index Seek, and the same when using an upper limit of 75000. If I run a query that returns ALL the rows, I &lt;STRONG&gt;still&lt;/STRONG&gt; get an Index Seek. &lt;/P&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/kalen_delaney/image_2AF06525.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://sqlblog.com/blogs/kalen_delaney/image_thumb_305ED5C9.png" width=401 height=196&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Both queries are using an Index Seek, but notice the difference in the thickness of the arrows. &lt;/P&gt;
&lt;P&gt;It turns out that the only time the optimizer will tell us it is doing a scan is when it knows absolutely that it will be looking at every row in the table or index leaf. And the only way it can know this is if there is no filter condition (NO WHERE clause) or no index on the filter condition. With the index on SalesOrderID, there is no way the optimizer can be absolutely sure that it will have to scan the whole table. Someone might have inserted a value of 100001 since the last time statistics were updated, and we wouldn't want to perform a scan and return a value that is not in the specified range. So the Index Seek in the plan really just means that SQL Server will access the data using the index, but not with a complete scan. There is something in the query that give a starting point, a stopping point or both. &lt;/P&gt;
&lt;P&gt;I've got another &lt;A href="http://www.vconferenceonline.com/event/home.aspx?id=130"&gt;Workshop for SSWUG on Index Internals&lt;/A&gt;, coming up on February 25th. Hopefully, I'll get a lot more great questions during that one!&lt;/P&gt;
&lt;P&gt;Thanks!&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff00ff size=4&gt;&lt;STRONG&gt;~Kalen&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;</description></item><item><title>Did You Know? I'm doing 3 more online seminars with SSWUG!</title><link>http://sqlblog.com/blogs/kalen_delaney/archive/2010/06/11/3-more-online-seminars-with-sswug.aspx</link><pubDate>Fri, 11 Jun 2010 22:46:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:26122</guid><dc:creator>Kalen Delaney</dc:creator><description>&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/kalen_delaney/archive/2010/04/22/more-online-seminars.aspx"&gt;As I told you in April&lt;/A&gt;, I recorded two more seminars with Stephen Wynkoop, on aspects of Query Processing. The first one will be broadcast on June 30 and the second on August 27. In between, we'll broadcast my Index Internals seminar, on July 23.&amp;nbsp; Workshops can be replayed for up to a week after the broadcast, and you can even buy a DVD of the workshop.&lt;/P&gt;
&lt;P&gt;You can get more details by clicking on the workshop name, below, or check out the announcement on the SSWUG site at &lt;A title=http://www.sswug.org/editorials/default.aspx?id=1948 href="http://www.sswug.org/editorials/default.aspx?id=1948"&gt;http://www.sswug.org/editorials/default.aspx?id=1948&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.vconferenceonline.com/shows/workshops/queryplans.asp"&gt;&lt;STRONG&gt;Query Plans Workshop&lt;/STRONG&gt;&lt;/A&gt; (June 30, 2010) &lt;BR&gt;Learn about basic elements, tools for exploring your query plans, how to detect inefficient plans and best practice guidelines&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;A href="http://www.vconferenceonline.com/shows/workshops/indexing.asp"&gt;&lt;STRONG&gt;Indexing Workshop&lt;/STRONG&gt;&lt;/A&gt; (July 23, 2010) &lt;BR&gt;Learn about basic index structures, tools for exploring those structures, index design considerations and best practice guidelines &lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.vconferenceonline.com/shows/workshops/plancaching.asp"&gt;&lt;STRONG&gt;Plan Caching Workshop&lt;/STRONG&gt;&lt;/A&gt; (Aug 27, 2010) &lt;BR&gt;Learn about basic management of the plan cache, tools for exploring the plans in cache and detecting when they are reused, query design considerations to provide the optimal caching behavior and best practice guidelines &lt;/P&gt;
&lt;P&gt;For those of you who attended my presentation at the Colorado PASS seminar last Wednesday in Denver, note that the 3rd workshop (Plan Caching), includes most of what I talked about in my presentation, and a lot more besides. The scripts from that session are now up on my site at &lt;A href="http://www.sqlserverinternals.com/conferences"&gt;www.sqlserverinternals.com/conferences&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Have fun!&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff00ff size=4&gt;~Kalen&lt;/FONT&gt;&lt;/P&gt;</description></item></channel></rss>