<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results matching tags 'Performance' and 'indexes'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Performance,indexes&amp;orTags=0</link><description>Search results matching tags 'Performance' and 'indexes'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Speaking at the Charlotte Users Group</title><link>http://sqlblog.com/blogs/andrew_kelly/archive/2011/08/26/speaking-at-the-charlotte-users-group.aspx</link><pubDate>Sat, 27 Aug 2011 00:33:55 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:38084</guid><dc:creator>Andrew Kelly</dc:creator><description>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I will be giving a presentation in between Earthquakes and Hurricanes in Charlotte NC. this Wednesday the 31st of August on &lt;font color="#0000ff"&gt;Understanding Indexes in SQL Server 2008&lt;/font&gt;. If you are in the area please drop by and say hello. You can find out more information and register for the event &lt;a href="http://august2011cssug.eventbrite.com/" target="_blank"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Andy&lt;/p&gt;</description></item><item><title>SQL Server, Seeks, and Binary Search</title><link>http://sqlblog.com/blogs/paul_white/archive/2011/08/08/sql-server-seeks-and-binary-search.aspx</link><pubDate>Mon, 08 Aug 2011 20:10:27 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:37622</guid><dc:creator>Paul White</dc:creator><description>&lt;p&gt;The following table summarizes the results from my last &lt;a href="http://sqlblog.com/blogs/paul_white/archive/2011/08/04/avoiding-uniqueness-for-performance.aspx"&gt;two&lt;/a&gt; blog entries, showing the CPU time used when performing 5 million clustered index seeks:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/image_2AB2C931.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Clustered Index Seek Test Results" border="0" alt="Clustered Index Seek Test Results" src="http://sqlblog.com/blogs/paul_white/image_thumb_41FDCDA2.png" width="315" height="64" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In test 1, making the clustered index unique improved performance by around 40%. In test 2, making the same change reduced performance by around 70% (on 64-bit systems – more on that later).&amp;#160; As a reminder, both tests use nested loops to join a single-column BIGINT table of numbers to itself:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/image_15749DBC.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Query and Plans" border="0" alt="Query and Plans" src="http://sqlblog.com/blogs/paul_white/image_thumb_52491F8E.png" width="647" height="453" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In test 1, the table contains numbers from 1 to 5 million inclusive; for test 2, the table contains the even numbers from 2 to 10 million (still 5 million rows).&amp;#160; In case you were wondering, the test 2 results are the same if we populate the table with odd numbers from 1 to 9,999,999 instead of even numbers.&amp;#160; How can we explain these results?&lt;/p&gt;  &lt;h3&gt;Performing an Index Seek&lt;/h3&gt;  &lt;p&gt;Perhaps we need to look a bit deeper into how SQL Server performs an index seek.&amp;#160; Most people know that SQL Server indexes are a &lt;a href="http://en.wikipedia.org/wiki/B%2B_tree"&gt;B+ tree&lt;/a&gt;, so let’s work through an example of locating the row containing the value 1 million, when the table contains values from 1 to 5 million, with a unique clustered index.&lt;/p&gt;  &lt;p&gt;Index seeks start at the index root page, which we can find in a number of ways (e.g. &lt;a href="http://msdn.microsoft.com/en-us/library/ms189051.aspx"&gt;sys.system_internals_allocation_units&lt;/a&gt;).&amp;#160; I happened to use &lt;a href="http://blogs.msdn.com/b/sqlserverstorageengine/archive/2006/12/13/more-undocumented-fun_3a00_-dbcc-ind_2c00_-dbcc-page_2c00_-and-off_2d00_row-columns.aspx"&gt;DBCC IND&lt;/a&gt; to determine that the root of the index was page &lt;strong&gt;117482&lt;/strong&gt; in file 1 (in Denali, we can use a new DMF: &lt;a href="http://sqlgeek.pl/2011/07/26/pl-denali-ctp3-nowe-lepsze-dbcc-ind/"&gt;sys.dm_db_database_page_allocations&lt;/a&gt;).&amp;#160; Anyway, whichever way you find it, we can use &lt;a href="http://support.microsoft.com/kb/83065"&gt;DBCC PAGE&lt;/a&gt; to look at the contents of the root page:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/SNAGHTMLd8089b_0F1DA161.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Index Root Page Contents" border="0" alt="Index Root Page Contents" src="http://sqlblog.com/blogs/paul_white/SNAGHTMLd8089b_thumb_36946DCB.png" width="489" height="213" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The col1 (key) column shows the lowest key value that can possibly be present in the lower-level page specified by Child Page Id.&amp;#160; We can see that the lowest possible key value on page 117485 is 906305, and the next lowest key value possible is 1132881 on page 117486.&amp;#160; So, if a row containing the value 1 million exists, the next page to look at is &lt;strong&gt;117485&lt;/strong&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/SNAGHTMLdb085d_41DD8208.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Level 1 Index Contents" border="0" alt="Level 1 Index Contents" src="http://sqlblog.com/blogs/paul_white/SNAGHTMLdb085d_thumb_383513D2.png" width="486" height="232" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;We are now at level 1 of the index, and have to scroll down the output a bit further to see that the next page to look at is &lt;strong&gt;119580&lt;/strong&gt;.&amp;#160; This page is at the leaf level of the index, and we find our target value at position 399:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/image_07525C67.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Leaf level index record" border="0" alt="Leaf level index record" src="http://sqlblog.com/blogs/paul_white/image_thumb_5AC92C80.png" width="429" height="72" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Binary Search&lt;/h3&gt;  &lt;p&gt;When performing an index seek, SQL Server obviously doesn’t run DBCC PAGE and scroll down the output window to find the next page to look at like we just did.&amp;#160; You may know that SQL Server can use binary search to locate index entries, but it’s worth taking a closer look at the index pages to see how this works in practice:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/image_6B61276E.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="SQL Server Page Structure Diagram" border="0" alt="SQL Server Page Structure Diagram" src="http://sqlblog.com/blogs/paul_white/image_thumb_61B8B938.png" width="486" height="478" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The slot array contains a series of two-byte offsets pointing to the index records.&amp;#160; The index records are not necessarily stored in any particular order on the page; only the slot array entries are guaranteed to be in sorted order.&amp;#160; Note that the sorted slot array entries do not contain the index keys themselves, just offsets.&lt;/p&gt;  &lt;h4&gt;Performance&lt;/h4&gt;  &lt;p&gt;When SQL Server uses binary search to locate an index entry, it starts by checking the middle element of the slot array (shown in red in the example above).&amp;#160; It then follows that offset pointer to the index record, and compares the value it finds there with the sought value.&amp;#160; Assuming the value is not the one we are looking for, the sorted nature of the slot array allows SQL Server to narrow the search range in half after this first comparison.&lt;/p&gt;  &lt;p&gt;If the red index record happens to contain a value &lt;em&gt;higher&lt;/em&gt; than the sought value, we know the value we are looking for is in that half of the slot array that sorts lower than the red entry.&amp;#160; This process of cutting the search space in half continues until we find the record we are looking for, or until it becomes clear that the value does not exist.&lt;/p&gt;  &lt;p&gt;The average and worst case performance of binary search is very close to log&lt;sub&gt;2&lt;/sub&gt;N comparisons to find the item of interest in a sorted list of N items.&amp;#160; For the 476 index entries found in our test example index structure at the leaf level, that means at most 9 comparison operations.&amp;#160; That compares well to a linear search of the sorted slot array, which might require as many as 476 comparisons if we are unlucky, 238 on average.&lt;/p&gt;  &lt;p&gt;None of this offers any particular insight into why a binary search into a unique indexes containing only even (or odd!) numbers should be so slow.&amp;#160; One of the advantages of binary search is that it expects to perform around the same amount of work, regardless of the distribution of the values in the index.&amp;#160; Luckily, binary search is not the only game in town.&lt;/p&gt;  &lt;h3&gt;Linear Interpolation&lt;/h3&gt;  &lt;p&gt;As efficient as binary search is in the general case, in some cases we can do better.&lt;/p&gt;  &lt;p&gt;When searching for the value 1 million, we know from level 1 of the index that the lowest key value that can appear on the leaf level page we are interested in is 999,601.&amp;#160; We also know that the lowest key value on the next page is 1,000,077.&amp;#160; From the header information on our target page, we also know there are 476 entries in the slot array on that page.&amp;#160; Given these facts, we can make an immediate guess at which slot the value 1,000,000 ought to appear in:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;expected slot = (1000077 - 999601) / 476 * (1000000 - 999601) = 399&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This simple calculation takes us immediately to slot 399.&amp;#160; As we saw earlier, slot 399 does indeed contain the value 1,000,000:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/image_5EC35485.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Slot 399" border="0" alt="Slot 399" src="http://sqlblog.com/blogs/paul_white/image_thumb_323A249F.png" width="429" height="72" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Naturally, the quality of the linear interpolation guess depends on how evenly distributed the values are within the page.&amp;#160; To a lesser extent, it also depends on how closely the minimum key value information at level 1 of the index matches reality.&amp;#160; In both tests shown in earlier blog entries, the values are precisely evenly distributed and the level 1 index key information is spot on.&lt;/p&gt;  &lt;h4&gt;Performance&lt;/h4&gt;  &lt;p&gt;Linear interpolation has the potential to be more efficient even than binary search, finding the target value in one comparison in this example, compared to nine comparisons for binary search.&amp;#160; Even where the data is not perfectly distributed, there is scope for linear interpolation to be superior, simply by applying the technique repeatedly on successively narrower ranges.&lt;/p&gt;  &lt;p&gt;A reasonable practical compromise might be to try linear interpolation two or three times, before falling back to linear or binary search on the remaining range.&amp;#160; The advantage of linear interpolation may not seem much, but consider that SQL Server makes these comparisons for every index seek operation – when doing many millions of seeks, the difference can soon add up.&amp;#160; It is probably not coincidence that the OLTP TPC benchmark tests perform a very great number of singleton index seeks.&lt;/p&gt;  &lt;h3&gt;Linear Regression&lt;/h3&gt;  &lt;p&gt;A natural extension to the idea of linear interpolation is to apply a linear regression (line of best fit) instead:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/image_42D21F8D.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Linear Regression Diagram" border="0" alt="Linear Regression Diagram" src="http://sqlblog.com/blogs/paul_white/image_thumb_6717040F.png" width="646" height="461" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In the diagram, the blue dotted line represents a linear interpolation based on the values of the smallest and highest values only.&amp;#160; The black line is obtained by a linear regression of &lt;em&gt;all&lt;/em&gt; the data values, and results in a much better fit.&lt;/p&gt;  &lt;p&gt;Since every straight line can be represented by a formula of the form y = mx + b, we can completely specify it by recording the values of the ‘m’ (slope) and ‘b’ (y-axis intercept) parameters.&amp;#160; The R&lt;sup&gt;2&lt;/sup&gt; value gives an idea of how good a fit the linear regression line is to the data.&amp;#160; In the present context, the ‘y’ value represents the indexed value, and the ‘x’ value is the slot position where that value can be found.&amp;#160; It’s easy to see that once we have a linear regression line, we can estimate the slot position for a particular sought index value by solving x = (y – b) / m.&lt;/p&gt;  &lt;p&gt;To use linear regression in a database, we might imagine storing the ‘b’ and ‘m’ parameter values somewhere (perhaps in a compact format in the page header), and deciding whether to apply the technique based on the R&lt;sup&gt;2&lt;/sup&gt; value.&lt;/p&gt;  &lt;h3&gt;What Does SQL Server Do?&lt;/h3&gt;  &lt;p&gt;All this is fine in theory, but does SQL Server &lt;em&gt;really&lt;/em&gt; ever use anything except binary search?&amp;#160; To see, I ran tests with a debugger attached to the SQL Server process, and stepped through the calls made while the seek test queries were running.&amp;#160; The call stack below was obtained when running 64-bit SQL Server:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/SNAGHTML385906e_329631C7.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="64-bit Call Stack" border="0" alt="64-bit Call Stack" src="http://sqlblog.com/blogs/paul_white/SNAGHTML385906e_thumb_28EDC391.png" width="450" height="225" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;By contrast, the following call stack comes from 32-bit SQL Server:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/paul_white/SNAGHTML38c1c77_25F85EDE.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="32-bit Call Stack" border="0" alt="32-bit Call Stack" src="http://sqlblog.com/blogs/paul_white/SNAGHTML38c1c77_thumb_1C4FF0A8.png" width="459" height="218" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;Interestingly, SQL Server follows the same code paths (at least at the call stack level, which is the best we can do without source code) regardless of whether the index is defined as unique or not, and for all the numeric data types I tested (INT, BIGINT, REAL, FLOAT, DECIMAL with a zero scale).&lt;/p&gt;  &lt;p&gt;The performance problem on x64 servers appears to be most pronounced when the key values have a small fixed gap between them.&amp;#160; As we have seen, performance is &lt;em&gt;very&lt;/em&gt; much worse on x64 servers compared with x86 versions when the table contains just even or odd numbers (i.e. with a gap of 1 between index entries).&amp;#160; If we change the test to multiply the original entries by a factor of ten (to produce a sequence of 10, 20, 30, 40…) the performance penalty all but disappears, and the x64 unique index test is around 30% faster than the non-unique test.&lt;/p&gt;  &lt;h3&gt;Conclusions and Further Reading&lt;/h3&gt;  &lt;p&gt;From the evidence available, my best guess is that 64-bit SQL Server does use linear interpolation and/or linear regression instead of binary search under suitable conditions, but that the implementation has edge-case poor performance where the index keys are separated by a small fixed offset.&amp;#160; It seems that we can achieve best performance by using a unique index where possible, and ensuring that keys are, as far as practicable, sequential and contiguous.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://academic.research.microsoft.com/Publication/2202072"&gt;B-tree Indexes, Interpolation Search, and Skew&lt;/a&gt; – Microsoft Research     &lt;br /&gt;&lt;a href="http://im.ufba.br/pub/MAT152/SemestreLetivo20052/intepolationSearch.pdf"&gt;Interpolation Search – a log log N Search&lt;/a&gt; (PDF)&lt;/p&gt;  &lt;p&gt;© 2011 Paul White&lt;/p&gt;  &lt;p&gt;email: &lt;a href="mailto:SQLkiwi@gmail.com"&gt;SQLkiwi@gmail.com&lt;/a&gt;     &lt;br /&gt;twitter: &lt;a href="http://twitter.com/SQL_Kiwi"&gt;@SQL_Kiwi&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Watch those clustered indexes</title><link>http://sqlblog.com/blogs/buck_woody/archive/2010/08/11/watch-those-clustered-indexes.aspx</link><pubDate>Wed, 11 Aug 2010 16:27:52 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:27804</guid><dc:creator>BuckWoody</dc:creator><description>&lt;p&gt;I had a discussion with a friend in Microsoft&amp;nbsp; IT this morning, and as we were evaluating some query plans we ran into more clustered index woes. Remember that clustered indexes affect the base table itself (which is why there can be only one) and are expensive to update. They are fantastic for reading data, but you need to carefully evaluate if they meet the criteria for having an efficient use of this type of index. &lt;/p&gt;
&lt;p&gt;More here: &lt;a href="http://www.sqlskills.com/BLOGS/PAUL/category/Indexes-From-Every-Angle.aspx"&gt;http://www.sqlskills.com/BLOGS/PAUL/category/Indexes-From-Every-Angle.aspx&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Ola Hallengren's maint procedures now supports exclusions</title><link>http://sqlblog.com/blogs/tibor_karaszi/archive/2010/08/09/ola-hallengren-s-maint-procedures-now-supports-exclusions.aspx</link><pubDate>Mon, 09 Aug 2010 05:02:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:27702</guid><dc:creator>TiborKaraszi</dc:creator><description>&lt;P&gt;Ola has a set of stored procedures to do maint operations, see&amp;nbsp;&lt;A href="http://ola.hallengren.com/"&gt;http://ola.hallengren.com/&lt;/A&gt;. Ola has now updated them to support exclusions or inclusions of tables, indexes or even whole schemas from index rebuild/reorg. Check out &lt;A href="http://ola.hallengren.com/Documentation.html#SelectingIndexes"&gt;http://ola.hallengren.com/Documentation.html#SelectingIndexes&lt;/A&gt;&amp;nbsp;for info on how to define exclusions and &lt;A href="http://ola.hallengren.com/Versions.html"&gt;http://ola.hallengren.com/Versions.html&lt;/A&gt;&amp;nbsp;for version overview.&lt;/P&gt;</description></item><item><title>How selective do we need to be for an index to be used?</title><link>http://sqlblog.com/blogs/tibor_karaszi/archive/2010/04/01/how-selective-do-we-need-to-be-for-an-index-to-be-used.aspx</link><pubDate>Thu, 01 Apr 2010 07:39:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:23940</guid><dc:creator>TiborKaraszi</dc:creator><description>&lt;P&gt;You know the answer already: It depends. But I often see some percentage value quoted and the point of this post is to show that there is no such percentage value. &lt;/P&gt;
&lt;P&gt;To get the most out of this blog post, you should understand the basic structure for an index, i.e. how the &lt;A title="b+ tree" href="http://en.wikipedia.org/wiki/B%2B_tree"&gt;b+ tree&lt;/A&gt; look like. You should also understand the difference between a clustered and a non-clustered index. In essence, you should be able to visualize these structures and searches through them as you read the text. If you find that difficult, draw a few versions on a piece of paper and "navigate" through them by tracing through them with a pen or your finger. After a while, you will do this in your mind. For instance, check out the sections under &lt;A title=this href="http://msdn.microsoft.com/en-us/library/ms180978(v=SQL.100).aspx"&gt;this&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;I'm not saying that we shouldn't consider selectivity when designing indexes - of course we should! I'm not saying that one shouldn't have some vague "feeling" about how much data to be return when making such decisions. What I will prove is that there is in reality no set percentage that the optimizer uses. The comment we usually see is something like:&lt;/P&gt;
&lt;P&gt;"If we return more than 5% of the rows, then an index will not be used."&lt;/P&gt;
&lt;P&gt;Where did that 5% number came from? I can assure you that this is not some hard-wired number in the optimizer (except for an edge-case, see below). The optimizer aims at running the query with as low cost as possible. Considering the data access part (think WHERE clause and the condition), this is pretty much about reading as few pages as possible (few page-accesses). &lt;/P&gt;
&lt;P&gt;Just to cut down a bit on the thread that might follow these types of blogs ("Hey, when I do this, your observations doesn't match, your blog post is incorrect!"), let us first consider some special cases:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Clustered index&lt;/STRONG&gt;&lt;BR&gt;The clustered index *is* the data. If the search condition (SARG) is SEEKable, then SQL Server will obviously seek through a clustered index instead of scan it. Anything else would be stupid. There can be *other* search conditions that are more efficient, but we are considering one search condition at-a-time.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Non-clustered index that covers the query&lt;/STRONG&gt;&lt;BR&gt;This is pretty much the same argument as for above. Since all data is in the index ("covers the query"), not seeking it would be stupid. Again, there can be cheaper alternatives for any of the other search conditions, but we are considering one condition at-a-time.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The value is not known to the optimizer&lt;/STRONG&gt;&lt;BR&gt;This is what happens when you have a TSQL variable you compare against. Something like "colname = @v". The optimizer has no knowledge of the contents of this variable. Either it uses density (where applicable, like "="), as stored in the statistics information of the index. Where not applicable (like "&amp;gt;", "&amp;lt;", "BETWEEN" etc), then the optimizer actually do use some hard-wired percentage value. This value can change between versions so give it a spin of you want to know what value you have for your version/build number. Note that a variable is not the same thing as a parameter. SQL Server sniffs parameters (parameter sniffing). Read this for elaboration: &lt;A href="http://msdn.microsoft.com/en-us/library/ee343986.aspx"&gt;http://msdn.microsoft.com/en-us/library/ee343986.aspx&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The search expression is not seek-able&lt;/STRONG&gt;&lt;BR&gt;I hope you know this already, but just to point it out. In most cases, having some calculation at the column side will void the ability to seek through the index. This should ideally be known to all T-SQL developers: Never do calculations at the column side! So, things to avoid are like "colname * 23 &amp;gt; 45" or "SOMEFUNCTION(colname) = 44".&lt;/P&gt;
&lt;P&gt;Hopefully by now we all understand that there are always special cases and exceptions. The more of &lt;A title="Kalen's" href="http://sqlserverinternals.com/"&gt;Kalen's&lt;/A&gt; books you have read, the more you understand this. What we are discussing here is the typical situation. OK? Fine. So, "Why is there no percentage value that the optimizer uses?", you ask. Because the value will differ. In short, SQL Server wants to read as few pages as possible. In the most simple example, the alternative to an index seek is a table scan. So we will use this as basis for your discussion. There can be other alternatives to the table scan (using some other index for some other condition), but that doesn't change the principal "it depends" concept. &lt;/P&gt;
&lt;P&gt;In essence, it is all about the alternative. As I said, our example wil use a table scan as alternative. A table scan (or clustered index scan if it is a clustered table) means that SQL Server will look at every page and see what rows satisfies the search condition on each page.&lt;/P&gt;
&lt;P&gt;My example has two different tables, both with 100,000 rows. These tables both have an integer column with consecutive increasing unique values, which also has a non-clustered index. I will see how selective I need to be when searching on this column in order for an index search to be done, compared to a table scan. I.e, find this percentage cut-off value.&lt;/P&gt;
&lt;P&gt;The fewrows table only fit one row per data page. This means 100,000 data pages. My tests show that the &lt;STRONG&gt;cutoff for fewrows is about 31,000 rows&lt;/STRONG&gt;. I.e., we need to be more selective than &lt;STRONG&gt;31%&lt;/STRONG&gt; for the index to be used.&lt;/P&gt;
&lt;P&gt;The manyrows table fit 384 rows per page. This means 260 pages. My tests show that the &lt;STRONG&gt;cutoff for fewrows is about&amp;nbsp;155 rows&lt;/STRONG&gt;. I.e., we need to be more selective than &lt;STRONG&gt;0.16%&lt;/STRONG&gt; for the index to be used.&lt;/P&gt;
&lt;P&gt;You might end up with different exact numbers, depending on what you have in the statistics, the build number of your SQL Server etc. But what you will see that a similar pattern. A huge difference between the two.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;It is all about the alternative&lt;/STRONG&gt;&lt;BR&gt;If I look at my indexes using sys.dm_db_index_physical_stats, I will see that the non-clustered index on the int column for the two tables are &lt;STRONG&gt;exactly the same&lt;/STRONG&gt; (same number of pages in the index, etc). So, two indexes with the same characteristics have very different cut-off values. How can that be? It is because the alternative differs. The alternative for this example is a table scan. For the bigrows table, the alternative means reading 100,000 pages. But for the smallrows table, the alternative means reading only 260 pages. There can of course be other alternatives, like using some other index for some other search condition. This is, in the end, why we don't have a set percentage value: it is all about the alternative!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;BR&gt;The typical cases will of course fall somewhere between my more extreme examples. But my examples show that there is no set percentage value used by the optimizer. I showed that for my test, the percentage value can be as low as 0.15% or as high as 31%. What matter is the alternative!&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;T-SQL&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;CODE style="FONT-SIZE:12px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;USE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;tempdb &lt;BR&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;IF&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'manyrows'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;IS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;NOT&amp;nbsp;NULL&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DROP&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;manyrows &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;IF&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'fewrows'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;IS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;NOT&amp;nbsp;NULL&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DROP&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;fewrows &lt;BR&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;manyrows&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c1&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;IDENTITY&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;PRIMARY&amp;nbsp;KEY&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c3&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;fewrows&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c1&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;IDENTITY&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;PRIMARY&amp;nbsp;KEY&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c3&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CHAR&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;4500&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;manyrows &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;TOP&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;100000&amp;nbsp;ROW_NUMBER&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;()&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;OVER&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;a.&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;5&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c3 &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;sys.columns&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;a&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;sys.columns&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;b &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;fewrows &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;TOP&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;100000&amp;nbsp;ROW_NUMBER&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;()&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;OVER&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;a.&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'hi'&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c3 &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;sys.columns&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;a&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;sys.columns&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;b &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;INDEX&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ON&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;manyrows&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;INDEX&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ON&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;fewrows&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--Number&amp;nbsp;of&amp;nbsp;pages&amp;nbsp;etc: &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;EXEC&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:darkred;"&gt;sp_indexinfo&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'manyrows' &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--&amp;nbsp;Data:&amp;nbsp;265&amp;nbsp;pages&amp;nbsp;(2.07&amp;nbsp;MB) &lt;BR&gt;--&amp;nbsp;Index&amp;nbsp;x:&amp;nbsp;187&amp;nbsp;pages&amp;nbsp;(1.46&amp;nbsp;MB) &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;EXEC&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:darkred;"&gt;sp_indexinfo&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'fewrows' &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--&amp;nbsp;Data:&amp;nbsp;100385&amp;nbsp;pages&amp;nbsp;(784&amp;nbsp;MB) &lt;BR&gt;--&amp;nbsp;Index&amp;nbsp;x:&amp;nbsp;187&amp;nbsp;pages&amp;nbsp;(1.46&amp;nbsp;MB) &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_NAME&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;),&amp;nbsp;*,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_NAME&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;sys.dm_db_index_physical_stats&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;DB_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(),&amp;nbsp;NULL,&amp;nbsp;NULL,&amp;nbsp;NULL,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'DETAILED'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--Run&amp;nbsp;below&amp;nbsp;with&amp;nbsp;showplan: &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;*&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;manyrows&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;WHERE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;BETWEEN&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;1&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;AND&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;155 &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--155&amp;nbsp;=&amp;nbsp;ix&amp;nbsp;search,&amp;nbsp;156&amp;nbsp;=&amp;nbsp;ts &lt;BR&gt;--Cut-off&amp;nbsp;is&amp;nbsp;0.16% &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;*&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;fewrows&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;WHERE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;BETWEEN&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;1&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;AND&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;31000&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--31000&amp;nbsp;=&amp;nbsp;ix&amp;nbsp;search,&amp;nbsp;32000&amp;nbsp;=&amp;nbsp;ts &lt;BR&gt;--Cut-off&amp;nbsp;is&amp;nbsp;31% &lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/CODE&gt;&lt;/P&gt;</description></item><item><title>Adding a PK online?</title><link>http://sqlblog.com/blogs/tibor_karaszi/archive/2010/01/13/adding-a-pk-online.aspx</link><pubDate>Wed, 13 Jan 2010 08:53:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:20991</guid><dc:creator>TiborKaraszi</dc:creator><description>&lt;P&gt;I just read in a forum about a user who want to replikate a table, but the table doesn't have a PK. The table is pretty large, and&amp;nbsp;having the table not available while adding the PK&amp;nbsp;is undesireable. The table has a clustered index already, and there are other columns which are known to be unique (presence of unique indexes).&lt;/P&gt;
&lt;P&gt;What I wanted to test is whether we can just add the PK constraint using the ONLINE option. Show answer is "yes". We can't turn a unique index into a PK using some meta-data only operation, unfortunately. That would be the easiest step. But we can add a unique constraint using the ONLINE option - there's even an example syntax for this in BOL. We can then remove the pre-existing unique index using ONLINE. Since we are using ONLINE, we need to be on Enterprise or Developer Edition.&lt;/P&gt;
&lt;P&gt;I wanted to test this, and below is my test script:&lt;/P&gt;&lt;CODE style="FONT-SIZE:12px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;USE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;tempdb &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SET&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;NOCOUNT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ON &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;IF&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'t'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;IS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;NOT&amp;nbsp;NULL&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DROP&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;t &lt;BR&gt;GO &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;t&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c1&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;NOT&amp;nbsp;NULL,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c2&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CHAR&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;100&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;UNIQUE&amp;nbsp;CLUSTERED&amp;nbsp;INDEX&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ON&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;t&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c1&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INSERT&amp;nbsp;INTO&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;t &lt;BR&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;TOP&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;5000000&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;ROW_NUMBER&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;()&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;OVER&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;a.id&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;),&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'x' &lt;BR&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;syscolumns&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;a&amp;nbsp; &lt;BR&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;CROSS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;JOIN&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;syscolumns&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;b &lt;BR&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;CROSS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;JOIN&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;syscolumns&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c &lt;BR&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;----------------------------------------------------- &lt;BR&gt;--Now&amp;nbsp;try&amp;nbsp;to&amp;nbsp;add&amp;nbsp;a&amp;nbsp;PK&amp;nbsp;"online"...: &lt;BR&gt;----------------------------------------------------- &lt;BR&gt;&lt;BR&gt;--Add&amp;nbsp;a&amp;nbsp;nullable&amp;nbsp;identity? &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ALTER&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;t&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ADD&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c3&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;IDENTITY&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;NULL &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--Msg&amp;nbsp;8147,&amp;nbsp;Level&amp;nbsp;16,&amp;nbsp;State&amp;nbsp;1,&amp;nbsp;Line&amp;nbsp;1 &lt;BR&gt;--Could&amp;nbsp;not&amp;nbsp;create&amp;nbsp;IDENTITY&amp;nbsp;attribute&amp;nbsp;on&amp;nbsp;nullable&amp;nbsp;column&amp;nbsp;'c3',&amp;nbsp;table&amp;nbsp;'t'. &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--Add&amp;nbsp;a&amp;nbsp;PK&amp;nbsp;using&amp;nbsp;ONLINE? &lt;BR&gt;--Prepare&amp;nbsp;a&amp;nbsp;new&amp;nbsp;connection&amp;nbsp;with&amp;nbsp;following&amp;nbsp;INSERTs &lt;BR&gt;--to&amp;nbsp;verify&amp;nbsp;it&amp;nbsp;can&amp;nbsp;run&amp;nbsp;simultaneously: &lt;BR&gt;--INSERT&amp;nbsp;INTO&amp;nbsp;t(c1,&amp;nbsp;c2)&amp;nbsp;VALUES(5000001,&amp;nbsp;'t') &lt;BR&gt;--INSERT&amp;nbsp;INTO&amp;nbsp;t(c1,&amp;nbsp;c2)&amp;nbsp;VALUES(5000001,&amp;nbsp;'t') &lt;BR&gt;--INSERT&amp;nbsp;INTO&amp;nbsp;t(c1,&amp;nbsp;c2)&amp;nbsp;VALUES(5000002,&amp;nbsp;'t') &lt;BR&gt;--GO &lt;BR&gt;--INSERT&amp;nbsp;INTO&amp;nbsp;t(c1,&amp;nbsp;c2)&amp;nbsp;VALUES(5000003,&amp;nbsp;'t') &lt;BR&gt;&lt;BR&gt;--Above&amp;nbsp;prepared?&amp;nbsp;OK,&amp;nbsp;execute&amp;nbsp;below&amp;nbsp;and&amp;nbsp;jump&amp;nbsp;to &lt;BR&gt;--other&amp;nbsp;window&amp;nbsp;to&amp;nbsp;verify&amp;nbsp;it&amp;nbsp;is&amp;nbsp;online &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ALTER&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;t&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ADD&amp;nbsp;CONSTRAINT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;PK_t&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;PRIMARY&amp;nbsp;KEY&amp;nbsp;NONCLUSTERED&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;c1&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;WITH&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;ONLINE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;=&amp;nbsp;ON&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--Verify&amp;nbsp;the&amp;nbsp;indexes&amp;nbsp;using&amp;nbsp;my&amp;nbsp;own&amp;nbsp;sp_indexinfo &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;EXEC&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:darkred;"&gt;sp_indexinfo&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'t'&lt;/SPAN&gt;&lt;/CODE&gt;</description></item><item><title>Rebuilding Indexes vs. Updating Statistics</title><link>http://sqlblog.com/blogs/ben_nevarez/archive/2009/10/06/rebuilding-indexes-vs-updating-statistics.aspx</link><pubDate>Tue, 06 Oct 2009 07:04:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:17301</guid><dc:creator>Ben Nevarez</dc:creator><description>&lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;One of the questions I was asked recently while speaking at user groups, was regarding the order that jobs like rebuilding indexes or updating statistics should be performed as part of the database maintenance activities. Then I started writing this post about this topic on the weekend but was interrupted several times, including one of them to watch the premiere on VH1 of the movie Anvil: The Story of Anvil.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;In general, the order should not matter, at least if you carefully consider these important points:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;1) By default, the UPDATE STATISTICS statement uses only a sample of records of the table. Using UPDATE STATISTICS WITH FULLSCAN will scan the entire table. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;2) By default, the UPDATE STATISTICS statement updates both index and column statistics. Using the COLUMNS option will update column statistics only. Using the INDEX option will update index statistics only.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;3) Rebuilding an index, for example by using ALTER INDEX … REBUILD, will also update index statistics with the equivalent of using WITH FULLSCAN. Rebuilding indexes does not update column statistics.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;4) Reorganizing an index, for example using ALTER INDEX … REORGANIZE, does not update any statistics.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;So depending on your maintenance jobs and scripts several scenarios can exist.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;The simplest scenario is if you want to rebuild all the indexes and update all the statistics. As mentioned before, if you rebuild all your indexes then all the index statistics will also be updated by scanning all the rows on the table. Then you just need to update your column statistics by running UPDATE STATISTICS WITH FULLSCAN, COLUMNS. Since the first job only updates index statistics and the second one only updates column statistics, it does not matter which one you execute first.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Some other more complicated scenarios include when you have a job which rebuilds your indexes depending on their fragmentation level. In these cases perhaps you want to update only those index statistics that were not touched by the index rebuild job, plus all the column statistics. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Of course, the worst case scenario would be if you first rebuild your indexes, which also updates the index statistics by scanning the entire table, and later you run UPDATE STATISTICS using the default values, which again updates the index statistics but this time with a default sample. Not only are you updating your index statistics twice but you are overwriting the better of the two choices.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Let me show you how these commands work with some examples using the AdventureWorks database. Create a new table dbo.SalesOrderDetail&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;select&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:blue;"&gt;into&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;from&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; sales&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;The next query uses the sys.stats catalog view and shows that there are no statistics objects for the new table. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;select&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; name&lt;span style="color:gray;"&gt;,&lt;/span&gt; auto_created&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;stats_date&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;object_id&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; stats_id&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;as&lt;/span&gt; update_date &lt;span style="color:blue;"&gt;from&lt;/span&gt; &lt;span style="color:green;"&gt;sys&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:green;"&gt;stats&lt;/span&gt;       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;where&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:fuchsia;"&gt;object_id&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;object_id&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'dbo.SalesOrderDetail'&lt;/span&gt;&lt;span style="color:gray;"&gt;)       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Use this query again to inspect the status of the statistics after each of the following commands. Now run the following query&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;select&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:blue;"&gt;from&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;where&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; SalesOrderID &lt;span style="color:gray;"&gt;=&lt;/span&gt; 43670 &lt;span style="color:gray;"&gt;and&lt;/span&gt; OrderQty &lt;span style="color:gray;"&gt;=&lt;/span&gt; 1      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Use the previous sys.stats query to verify that two statistics objects were created, one for the SalesOrderID column and another one for the OrderQty column (they both have names starting with _WA_Sys as shown in the next figure). Now create the following index and again run the query to verify that a new statistics object for the ProductID column has been created. Notice the value of the auto_created column which tells if the statistics were created by the query optimizer.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;create&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;index&lt;/span&gt; ix_ProductID &lt;span style="color:blue;"&gt;on&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail&lt;span style="color:gray;"&gt;(&lt;/span&gt;ProductID&lt;span style="color:gray;"&gt;)&lt;/span&gt;       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="text-align:center;" align="center"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="text-align:center;" align="center"&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_4C71EA23.jpg"&gt;&lt;img title="clip_image002" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="78" alt="clip_image002" src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_5A725C90.jpg" width="399" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Run the next command to update the column statistics only. You can validate that only the column statistics were updated by looking at the update_date column which uses the STATS_DATE function to display the last date the statistics were updated. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;update&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;statistics&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail &lt;span style="color:blue;"&gt;with&lt;/span&gt; &lt;span style="color:blue;"&gt;fullscan&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:green;"&gt;columns       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="text-align:center;mso-layout-grid-align:none;" align="center"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image004_53814C8A.jpg"&gt;&lt;img title="clip_image004" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="79" alt="clip_image004" src="http://sqlblog.com/blogs/ben_nevarez/clip_image004_thumb_286AE1F5.jpg" width="406" border="0" /&gt;&lt;/a&gt;      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;This command will do the same for the index statistics&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;update&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;statistics&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail &lt;span style="color:blue;"&gt;with&lt;/span&gt; &lt;span style="color:blue;"&gt;fullscan&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:blue;"&gt;index       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;These commands will update both index and column statistics&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;update&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;statistics&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail &lt;span style="color:blue;"&gt;with&lt;/span&gt; &lt;span style="color:blue;"&gt;fullscan       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;update&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;statistics&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail &lt;span style="color:blue;"&gt;with&lt;/span&gt; &lt;span style="color:blue;"&gt;fullscan&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:gray;"&gt;all       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;See how an index rebuild only updates index statistics&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;alter&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;index&lt;/span&gt; ix_ProductID &lt;span style="color:blue;"&gt;on&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail &lt;span style="color:blue;"&gt;rebuild       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;Here you can verify that reorganizing an index does not update statistics&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;alter&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;index&lt;/span&gt; ix_ProductID&lt;span style="mso-spacerun:yes;"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color:blue;"&gt;on&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail &lt;span style="color:blue;"&gt;reorganize       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;Finally, remove the table you have just created&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;drop&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;table&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;</description></item><item><title>The Missing Indexes Feature</title><link>http://sqlblog.com/blogs/ben_nevarez/archive/2009/09/25/the-missing-indexes-feature.aspx</link><pubDate>Fri, 25 Sep 2009 06:19:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:16984</guid><dc:creator>Ben Nevarez</dc:creator><description>&lt;p class="MsoNormal"&gt;Since I will be speaking about the Query Optimizer at the coming PASS Summit, I have been preparing my presentation and at the same time blogging about it. This time I will describe the Missing Indexes feature, seen from the point of view of the Query Optimizer.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;We know that it is the job of the Query Optimizer to find an efficient execution plan for a query. But we rarely see the Query Optimizer directly giving us indications about what it needs to produce a better execution plan. One of these cases is the Missing Indexes feature, which was introduced with SQL Server 2005.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;The Query Optimizer defines what the best indexes for a query are, and if these indexes do not exist, it will make this information available in the XML plan and the sys.dm_db_missing_index DMVs. And of course, by showing this information the Query Optimizer is also warning you that it might not be selecting an efficient plan. This information shows which indexes may be helpful to improve the performance of your query. You can even use SQL Server 2008 Management Studio to display the CREATE INDEX commands needed to create these indexes, as shown later.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;However, although this information about missing indexes is very helpful, this feature should not be used as a tuning tool and should not replace your own index analysis. Database administrators and developers should be aware of its limitations, as described on the Books Online entry ‘Limitations of the Missing Indexes Feature’. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;So let us take a quick look to see how this feature works. Create a dbo.SalesOrderDetail table on the AdventureWorks database with the following command&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;select&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt;       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;into&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;from&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; sales&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Run this query and ask for a graphical or XML execution plan&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;select&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt;       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;from&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;where&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; SalesOrderID &lt;span style="color:gray;"&gt;=&lt;/span&gt; 43670      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;This query can benefit from an index on the SalesOrderID column but no missing indexes information is shown this time. One limitation of the Missing Indexes feature is that it does not work on a trivial plan optimization, like in this case. You can verify that this is a trivial plan by looking at the graphical plan properties (Optimization Level shows as TRIVIAL) or by looking at the XML plan (StatementOptmLevel=&amp;quot;TRIVIAL).&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;You can avoid the trivial plan optimization by using more complex features. In our case we are just going to create a non related index&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;create&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;index&lt;/span&gt; ix_ProductID &lt;span style="color:blue;"&gt;on&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail&lt;span style="color:gray;"&gt;(&lt;/span&gt;ProductID&lt;span style="color:gray;"&gt;)       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Note that the index created will not be used by our previous query but the query will no longer qualify for a trivial plan. Run the query again. This time the XML plan will contain something like this&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;MissingIndexes&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;gt;     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;#160;&amp;#160; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;MissingIndexGroup&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;/span&gt;&lt;span style="font-size:10pt;color:red;font-family:'Courier New';mso-no-proof:yes;"&gt;Impact&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;=&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;99.703&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;&amp;gt;       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;MissingIndex&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;/span&gt;&lt;span style="font-size:10pt;color:red;font-family:'Courier New';mso-no-proof:yes;"&gt;Database&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;=&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;[AdventureWorks]&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;Schema&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;[dbo]&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;Table&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;[SalesOrderDetail]&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;&amp;gt;       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;ColumnGroup&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;/span&gt;&lt;span style="font-size:10pt;color:red;font-family:'Courier New';mso-no-proof:yes;"&gt;Usage&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;=&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;EQUALITY&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;&amp;gt;       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;Column&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;/span&gt;&lt;span style="font-size:10pt;color:red;font-family:'Courier New';mso-no-proof:yes;"&gt;Name&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;=&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;[SalesOrderID]&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;ColumnId&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;1&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; /&amp;gt;       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&amp;lt;/&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;ColumnGroup&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;gt;     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&amp;lt;/&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;MissingIndex&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;gt;     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;#160;&amp;#160; &lt;/span&gt;&amp;lt;/&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;MissingIndexGroup&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;gt;     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="font-size:10pt;color:#a31515;font-family:'Courier New';mso-no-proof:yes;"&gt;MissingIndexes&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;&amp;gt;     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;And if you look at the graphical plan (only SQL Server 2008 Management Studio) you will see a Missing Index warning and a CREATE INDEX command&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="text-align:center;" align="center"&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_62264090.jpg"&gt;&lt;img title="clip_image002" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="148" alt="clip_image002" src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_0FD58CC6.jpg" width="514" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;You can right-click on the graphical plan and select Missing Index Details to see the CREATE INDEX command that can be used to create this index&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;/*     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;Missing Index Details from SQLQuery1.sql     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;The Query Processor estimates that implementing the following index could improve the query cost by 99.703%.     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;*/     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;/*     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;USE [AdventureWorks]     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;GO     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;CREATE NONCLUSTERED INDEX [&amp;lt;Name of Missing Index, sysname,&amp;gt;]     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;ON [dbo].[SalesOrderDetail] ([SalesOrderID])     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;     &lt;p&gt;&amp;#160;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;GO     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:green;font-family:'Courier New';mso-no-proof:yes;"&gt;*/     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Create the recommended index after you provide a name to it. This time if you run the same query again and look at the execution plan you will see that an Index Seek operator is using the index you have just created and both the Missing Index warning and the MissingIndex element of the XML plan are gone.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Finally, remove the dbo.SalesOrderDetail table you have just created.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;drop&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;table&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;</description></item><item><title>Heaps, forwarding pointers, ALTER TABLE REBUILD and non-clustered indexes</title><link>http://sqlblog.com/blogs/tibor_karaszi/archive/2009/08/28/heaps-forwarding-pointers-alter-table-rebuild-and-non-clustered-indexes.aspx</link><pubDate>Fri, 28 Aug 2009 10:15:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:16351</guid><dc:creator>TiborKaraszi</dc:creator><description>&lt;P&gt;Let's start with some background on forwarding pointers:&lt;/P&gt;
&lt;P&gt;Forwarding pointers in heaps can be a mess to get rid of. A forwarding pointer happens when you modify a row so that the row doesn't fit on the same page anymore. SQL Server moves the row to a new page and leaves a forwarding pointer where the old row used to be. This means that non-clustered indexes are not affected by the moving of the row - it can still point to the old location. So the modification is less costly than if all non-clustered indexes needed to reflect the row move. But having forwarding pointers can be bad for performance when you read data. A perhaps less known fact is that a scan over a table needs to follow forwarding pointers - essentially "jumping back and forth" a lot if you have many forwarding pointers. That can be really bad for performance (if you have table scans, of course). So, how do we get rid of forwarding pointers? Well, we can shrink the database file, but that is a little like curing a headache by jumping into a big meat grinder. We can export all data and re-import it - not very practical.&lt;/P&gt;
&lt;P&gt;Greg Linwood reminded me that in&amp;nbsp;SQL Server 2008, we can do ALTER&amp;nbsp;TABLE ... REBUILD. Now, I knew about this option, and every time I tell about it in class I've been thinking silently for myself "I need to test whether this is a way to get rid of fwd pointers". (You generally talk about ALTER TABLE ... REBUILD when you talk about enabling compression on a heap.) So, doing a REBUILD of a table using ALTER TABLE sounds promising. Will it get rid of forwarding pointers? Will it also rebuild all non-clustered indexes?&lt;/P&gt;
&lt;P&gt;Quick answer for those who don't care reading the TSQL script:&lt;BR&gt;ALTER TABLE ... REBUILD will remove forwarding pointers, but for some strange reason it will also rebuild all non-clustered indexes on that table.&lt;/P&gt;
&lt;P&gt;See the TSQL code below. It was adapted from a challenge by Linchi Shea to produce a data loading script&amp;nbsp;resulting in&amp;nbsp;worst performance (where I immediately thought of forwarding pointers). See for instance &lt;A href="http://sqlblog.com/blogs/linchi_shea/archive/2009/06/07/t-sql-exercise-simplest-data-loading-script-to-produce-worst-query-performance-june-7th-update.aspx"&gt;http://sqlblog.com/blogs/linchi_shea/archive/2009/06/07/t-sql-exercise-simplest-data-loading-script-to-produce-worst-query-performance-june-7th-update.aspx&lt;/A&gt;. &lt;/P&gt;&lt;CODE style="FONT-SIZE:12px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;USE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;tempdb &lt;BR&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;IF&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;EXISTS&amp;nbsp;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;*&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;sysobjects&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;WHERE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;name&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'test'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DROP&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test &lt;BR&gt;GO &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;NOT&amp;nbsp;NULL &lt;BR&gt;&amp;nbsp;&amp;nbsp;,&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x2&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;NOT&amp;nbsp;NULL &lt;BR&gt;&amp;nbsp;&amp;nbsp;,&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;y&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CHAR&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;10&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;NOT&amp;nbsp;NULL&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DEFAULT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;''&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&amp;nbsp;&amp;nbsp;,&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;z&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CHAR&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;10&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp;NOT&amp;nbsp;NULL&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DEFAULT&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;''&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;) &lt;BR&gt;&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DECLARE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@rows&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;666666&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@toKeep&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;400000&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@diff&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT &lt;BR&gt;&amp;nbsp; &lt;BR&gt;INSERT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x2&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;TOP&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@rows&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;ROW_NUMBER&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;()&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;OVER&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;1&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;))&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;r &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;ROW_NUMBER&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;()&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;OVER&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ORDER&amp;nbsp;BY&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;1&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;))&amp;nbsp;%&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;10&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;s &lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;master..spt_values&amp;nbsp;a&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;CROSS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;JOIN&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;master..spt_values&amp;nbsp;b &lt;BR&gt;GO &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ALTER&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ALTER&amp;nbsp;COLUMN&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;y&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CHAR&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;892&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ALTER&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ALTER&amp;nbsp;COLUMN&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;z&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CHAR&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;100&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;GO &lt;BR&gt;&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DECLARE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@rows&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;666666&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@toKeep&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT&amp;nbsp;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;400000&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@diff&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;INT &lt;BR&gt;DELETE&amp;nbsp;TOP&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@rows&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;-&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@toKeep&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;WHERE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x2&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;IN&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;2&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;4&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;6&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;8&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;GO &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;INDEX&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x1&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ON&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE&amp;nbsp;INDEX&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x2&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ON&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;x2&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;*&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;sys.dm_db_index_physical_stats&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;DB_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(),&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'test'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;),&amp;nbsp;NULL,&amp;nbsp;NULL,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'DETAILED'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--First&amp;nbsp;&amp;nbsp;run&amp;nbsp;(no&amp;nbsp;nc&amp;nbsp;indexes&amp;nbsp;):&amp;nbsp;387157&amp;nbsp;fwd&amp;nbsp;records&amp;nbsp;(out&amp;nbsp;of&amp;nbsp;400000&amp;nbsp;rows),&amp;nbsp;96104&amp;nbsp;pages &lt;BR&gt;--Second&amp;nbsp;run&amp;nbsp;(two&amp;nbsp;nc&amp;nbsp;indexes):&amp;nbsp;387157&amp;nbsp;fwd&amp;nbsp;records&amp;nbsp;(out&amp;nbsp;of&amp;nbsp;400000&amp;nbsp;rows),&amp;nbsp;96105&amp;nbsp;pages &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;CHECKPOINT &lt;BR&gt;DBCC&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;DROPCLEANBUFFERS &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;DECLARE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@t&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;time&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;=&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;SYSDATETIME&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;() &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;ALTER&amp;nbsp;TABLE&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;test&amp;nbsp;REBUILD &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;DATEDIFF&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;ms&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:#434343;"&gt;@t&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;CAST&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;SYSDATETIME&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;()&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;AS&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;time&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;)) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--First&amp;nbsp;run,&amp;nbsp;no&amp;nbsp;non-clustered&amp;nbsp;indexes,&amp;nbsp;three&amp;nbsp;subsequent&amp;nbsp;executions&amp;nbsp;(ms):&amp;nbsp;19351,&amp;nbsp;20683,&amp;nbsp;20275 &lt;BR&gt;--Second&amp;nbsp;run,&amp;nbsp;with&amp;nbsp;two&amp;nbsp;non-clustered&amp;nbsp;indexes,&amp;nbsp;three&amp;nbsp;subsequent&amp;nbsp;executions&amp;nbsp;(ms):&amp;nbsp;31803,&amp;nbsp;35065,&amp;nbsp;37511 &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;SELECT&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;*&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;FROM&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:black;"&gt;sys.dm_db_index_physical_stats&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;DB_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(),&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:magenta;"&gt;OBJECT_ID&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'test'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;),&amp;nbsp;NULL,&amp;nbsp;NULL,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'DETAILED'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR:green;"&gt;--First&amp;nbsp;&amp;nbsp;run,&amp;nbsp;heap&amp;nbsp;=&amp;nbsp;"index"&amp;nbsp;0&amp;nbsp;(no&amp;nbsp;nc&amp;nbsp;indexes&amp;nbsp;):&amp;nbsp;0&amp;nbsp;fwd&amp;nbsp;records,&amp;nbsp;50002&amp;nbsp;pages &lt;BR&gt;--Second&amp;nbsp;run,&amp;nbsp;heap&amp;nbsp;=&amp;nbsp;"index"&amp;nbsp;0&amp;nbsp;(two&amp;nbsp;nc&amp;nbsp;indexes):&amp;nbsp;0&amp;nbsp;fwd&amp;nbsp;records,&amp;nbsp;50003&amp;nbsp;pages &lt;BR&gt;--But:&amp;nbsp;avg_page_space_used_in_percent&amp;nbsp;changes&amp;nbsp;for&amp;nbsp;the&amp;nbsp;nc&amp;nbsp;indexes&amp;nbsp;after&amp;nbsp;the&amp;nbsp;rebuild. &lt;BR&gt;--That&amp;nbsp;I&amp;nbsp;take&amp;nbsp;as&amp;nbsp;nc&amp;nbsp;indexes&amp;nbsp;are&amp;nbsp;also&amp;nbsp;rebuilt. &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/CODE&gt;</description></item><item><title>Automating dm_exec_query_stats and dm_db_index_usage_stats analysis</title><link>http://sqlblog.com/blogs/joe_chang/archive/2009/06/22/automating-dm-exec-query-stats-and-dm-db-index-usage-stats-analysis.aspx</link><pubDate>Mon, 22 Jun 2009 04:25:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14815</guid><dc:creator>jchang</dc:creator><description>&lt;P&gt;Everyone should know by now how really useful the DMVs dm_exec_query_stats, and dm_db_index_usage_stats and the associated DMFs for obtaining the SQL and XML plan: dm_exec_sql_text, dm_exec_query_plan, and dm_exec_text_query_plan. Of course it has been explained that dm_exec_query_stats is not a replacement for SQL Server Profiler and SQL Trace. The DMV is only reliable if execution plans are not frequently evicted from the procedure cache and if SQL is not frequently recompiled. &lt;/P&gt;
&lt;P&gt;Still the DMV dm_exec_query_stats is popular because the results are available with a simple query. The complexity of setting up a trace, making sure it is not adversely impacting server performance, making sure space is available, and most of all, the effort of parsing the trace are all avoided.&lt;/P&gt;
&lt;P&gt;So what do we do next? From the top query statistics we can start looking at the SQL and the execution plans. One minor annoyance is that if we use CROSS APPLY to dm_exec_query_plan, each XML plan has to be saved individually. This can be annoying if one has to remote into to a PC in the server room and this connection is slow. &lt;BR&gt;There is much information in the XML plan that would be helpful if we could see it in a grid along with the execution statistics. &lt;/P&gt;
&lt;P&gt;From the index usage statistics, we can eliminate unused indexes. There might also be indexes that are infrequently used. Sometimes it is obvious that certain indexes can be consolidated. Other times, it is necessary to examine the execution plan to determine if another index is sufficient. The XML plan analysis cross-references in which plans each index is used. All of this is tedious work which can be automated. So this is the purpose of the SQLExecStats tool.&lt;/P&gt;
&lt;P&gt;A few people have tried it on production systems. There are still bugs, and feature requests, but hopefully I can turn this into something useful over time. &lt;/P&gt;
&lt;P&gt;lets use this url for the latest build rather than changing the url for each build&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.qdpma.com/tools/ExecStats.zip"&gt;http://www.qdpma.com/tools/ExecStats.zip&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;The above build is now 20090628. The (poor excuse for) documention is also online &lt;A href="http://www.qdpma.com/SQLExecStats.html"&gt;http://www.qdpma.com/SQLExecStats.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Feedback is welcome, in particular, send me the output files so I can try to figure out if this is collecting the right information.&amp;nbsp;Support will be&amp;nbsp;based on&amp;nbsp;availability. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Note&lt;/STRONG&gt;: SQL Server 2008 sp1 fix now correctly reports parallel execution plan total_worker_time (CPU). It is not fixed on SQL Server 2005 sp3, latest cu?&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Limitations: &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;European Localization &lt;/STRONG&gt;The XML plan is stored as a string, with numbers in US-en format. My program&amp;nbsp;extracts plan cost and estimated row numbers from the XML plan. The previous version did not specify any localization, but I think the default is the host environment. Hence the code double.Format(value) is interpreted as whatever the local environment is instead of US-en. The builds since 20090623&amp;nbsp;specifies the US-en format in most places. &lt;/P&gt;
&lt;P&gt;If some one with European number formats could run this program and send me the output, I would appreciate it.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Bug fixes, features etc&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;2009-06-22: The&amp;nbsp;password now should display *,&amp;nbsp;I don't do security work, and it shows. Some formatting was changed to right align, comma thousands separator, Very large numbers in&amp;nbsp;Excel&amp;nbsp;cannot be changed, 4 bytes integers are represented as numbers, larger numbers are represented as text.&lt;BR&gt;I will do more formatting changes later&lt;/P&gt;
&lt;DIV&gt;&lt;STRONG&gt;2009-06-28&lt;/STRONG&gt;&lt;/DIV&gt;
&lt;DIV&gt;The error described by Zen occurs with case sensitive collations. Apparently&amp;nbsp;one SQL query I issued from the executable was not a case correct with the columns I declared on the receiving side, and this is sufficient to cause the data table load to fail.&lt;/DIV&gt;
&lt;DIV&gt;The current build is really an intermediate build. I am adding the ability to collect table and index information for multiple databases and not everything is consistent yet.&lt;/DIV&gt;
&lt;DIV&gt;Be careful on trying to collect for too many databases, and too many execution plans, there are checks for over size yet.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;STRONG&gt;2009-07-09&lt;/STRONG&gt;&lt;/DIV&gt;
&lt;DIV&gt;I am still in the middle of changing the tool to have the option of collecting table and index info from all databases. So some of the UI is not entirely consistent. However, all bug fixes are in the new version.&lt;/DIV&gt;
&lt;DIV&gt;Previously there were SQL queries that were not case correct with client-side table definitions, and when the default collation is case sensitive, an error occurred. This should be corrected.&lt;/DIV&gt;
&lt;DIV&gt;Also, previously I issued DBCC SHOW_STATISTICS([schema.table],[stat]) &lt;/DIV&gt;
&lt;DIV&gt;which&amp;nbsp;can generate an error if there is a hyphen&amp;nbsp;'-'&amp;nbsp;in the table or schema. I changed this to&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;('schema.table',[stat])&lt;BR&gt;I am not sure if this is the most safe format, should it be: ('schema.table','stat')?&lt;BR&gt;anyways, go to the main url, &lt;A href="http://www.qdpma.com/"&gt;http://www.qdpma.com/&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;look for &lt;A href="http://www.qdpma.com/tools/ExecStats_20090709.zip"&gt;SQL Exec Stats Build 2009-07-09&lt;/A&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;A href="http://www.qdpma.com/tools/ExecStats_20090709.zip"&gt;http://www.qdpma.com/tools/ExecStats_20090709.zip&lt;/A&gt;&lt;/DIV&gt;</description></item></channel></rss>