<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www2.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>Benjamin Nevarez</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Writing a Book, and Moving my Blog</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2010/06/09/writing-a-book-and-moving-my-blog.aspx</link><pubDate>Wed, 09 Jun 2010 07:39:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:26043</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>4</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/26043.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=26043</wfw:commentRss><description>&lt;P class=MsoNormal&gt;I started blogging about SQL Server here at &lt;A href="http://sqlblog.com/blogs/ben_nevarez"&gt;SQLblog&lt;/A&gt; back in July, 2009 and it was a lot of fun, I enjoyed it a lot. Then later, after a series of blog posts about the Query Optimizer, I was invited to write an entire book about that same topic. But after a few months I realized that it was going to be hard to continue both blogging and writing chapters for a book, this in addition to my regular day job, so I decided to stop blogging for a little while.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Now that I have finished the last chapter of the book and I am working on the final chapter reviews, I decided to start blogging again. This time I am moving my blog to&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;A href="http://www.benjaminnevarez.com/"&gt;http://www.benjaminnevarez.com&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Same as my previous posts I plan to write about my topics of interest, like the relational engine, and basically anything related to SQL Server. Hopefully you find my new blog interesting and useful.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Finally, I would like to thank Adam for allowing me to blog here.&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=26043" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Blogging/default.aspx">Blogging</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Books/default.aspx">Books</category></item><item><title>Speaking at SQLSaturday #44 in Huntington Beach, CA (Los Angeles Area)</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2010/04/15/speaking-at-sqlsaturday-44-in-huntington-beach-ca-los-angeles-area.aspx</link><pubDate>Thu, 15 Apr 2010 07:14:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:24303</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>0</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/24303.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=24303</wfw:commentRss><description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;I'll be presenting a session at SQLSaturday #44 in Huntington Beach, the first SQLSaturday on Southern California. The event takes place on Saturday, April 24 at the Golden West College on 15744 Goldenwest St, Huntington Beach, CA 92647.&lt;/P&gt;. 
&lt;P class=MsoNormal&gt;For more information visit the following link&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;A href="http://sqlsaturday.com/44/eventhome.aspx"&gt;http://sqlsaturday.com/44/eventhome.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;My session is “How the Query Optimizer Works”. I hope to see you there.&lt;/P&gt;
&lt;P style="TEXT-ALIGN:center;" class=MsoNormal align=center&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_4B91054E.gif"&gt;&lt;IMG style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;" title=clip_image002 border=0 alt=clip_image002 src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_195B5E41.gif" width=236 height=94&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=24303" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Speaking/default.aspx">Speaking</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/SQLSaturday/default.aspx">SQLSaturday</category></item><item><title>The Query Optimizer and Cost Estimation</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2010/02/17/the-query-optimizer-and-cost-estimation.aspx</link><pubDate>Thu, 18 Feb 2010 04:23:59 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:22413</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>1</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/22413.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=22413</wfw:commentRss><description>&lt;p class="MsoNormal"&gt;Last year when I presented my session regarding the Query Optimizer at the PASS Summit and at a couple of local user groups, I was asked how the estimated CPU and I/O costs in an execution plan are calculated. Since Microsoft does not publish how these costs are calculated all I could say was that each operator cost depends on the operator algorithm and the cardinality estimation. &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 time I am working on a related project and I thought that perhaps I could look into this again to show as an example. But since there are dozens of operators I decided to start with a simple one: the Clustered Index Scan operator. So I captured dozens of XML plans, used XQuery to extract their cost information and after some analysis I was able to obtain a basic formula for this specific operator.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;To show this in an example, let us look at the largest table in AdventureWorks. Run the following query and look at the estimated CPU and I/O costs for the Clustered Index Scan operator&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="margin:0in 0in 0pt;tab-stops:.5in;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; 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;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; LineTotal &lt;span style="color:gray;"&gt;=&lt;/span&gt; 35      &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" style="text-align:center;" align="center"&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_22D67C8D.jpg"&gt;&lt;img title="clip_image002" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="366" alt="clip_image002" src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_145C8DCB.jpg" width="342" 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;For a Clustered Index Scan operator I observed that the CPU cost is 0.0001581 for the first record plus 0.0000011 for any additional record after that. In this specific case we have an estimated number of records of 121,317 so we can use 0.0001581 + 0.0000011 * (121317 – 1) or 0.133606 which is the value shown as Estimated CPU Cost. In a similar way, I noticed that the minimum I/O cost is 0.003125 for the first database page and then it grows in increments of 0.00074074 for every additional page. Since this operator scans the entire table I can use the following query to find the number of database pages, which returns 1,234.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="margin:0in 0in 0pt;tab-stops:.5in;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; in_row_data_page_count&lt;span style="color:gray;"&gt;,&lt;/span&gt; row_count       &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin:0in 0in 0pt;tab-stops:.5in;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; &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;dm_db_partition_stats       &lt;p&gt;&lt;/p&gt;     &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin:0in 0in 0pt;tab-stops:.5in;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;'Sales.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" style="margin:0in 0in 0pt;tab-stops:.5in;mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:gray;font-family:'Courier New';mso-no-proof:yes;"&gt;and&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; index_id &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;In this case I have 0.003125 + 0.00074074 * (1234 – 1) or 0.916458 which is the value shown as Estimated I/O Cost.&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, we add both costs, 0.133606 + 0.916458 to get 1.05006 which is the total estimated cost of the operator. In the same way, adding the cost of all the operators will give the total cost of the plan. In this case, the cost of the Clustered Index Scan, 1.05006, plus the cost of the first Compute Scalar operator, 0.01214, the second Compute Scalar operator, 0.01213, and the cost of the Filter operator, 0.0582322, will give the total cost of the plan, 1.13256, as shown next. &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_image004_3FD1E1F5.jpg"&gt;&lt;img title="clip_image004" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="243" alt="clip_image004" src="http://sqlblog.com/blogs/ben_nevarez/clip_image004_thumb_7BE1C1BE.jpg" width="402" 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;Finally, you can combine this with my previous post, Fooling the Query Optimizer at &lt;a href="http://sqlblog.com/blogs/ben_nevarez/archive/2010/01/13/fooling-the-query-optimizer.aspx"&gt;http://sqlblog.com/blogs/ben_nevarez/archive/2010/01/13/fooling-the-query-optimizer.aspx&lt;/a&gt;, to test with “bigger” tables by changing the number of records and pages of a table for testing purposes.&lt;/p&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=22413" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Cost+Estimation/default.aspx">Cost Estimation</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Execution+Plans/default.aspx">Execution Plans</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category></item><item><title>Fooling the Query Optimizer</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2010/01/13/fooling-the-query-optimizer.aspx</link><pubDate>Thu, 14 Jan 2010 04:57:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:21032</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>4</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/21032.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=21032</wfw:commentRss><description>&lt;P class=MsoNormal&gt;Did you ever wanted to know which execution plans the Query Optimizer would generate for your queries should your tables have millions of records? You can actually generate those plans by using the undocumented ROWCOUNT and PAGECOUNT options of the UPDATE STATISTICS statement. These options can be used on small or empty tables and can be helpful&amp;nbsp;for testing&amp;nbsp;in some scenarios where you may not want to spent time or disk space creating big tables.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;By using this method you are tricking the Query Optimizer as it will generate execution plans using cardinality estimations as if the table really had millions of records. Note that this option, available since SQL Server 2005, only helps in creating the execution plan for your queries. Actually running the query will use the real data and of course will execute faster than a table with millions of records.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;UPDATE STATISTICS WITH ROWCOUNT, PAGECOUNT does not change the table statistics, only the counter of number of rows and pages of a table. But the Query Optimizer uses this information to estimate the cardinality of queries as I will show later. Also keep in mind that these are undocumented and unsupported options and should not be used in any production environment.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Let us see an example. Run the following query to create a new table on the AdventureWorks database&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&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;&lt;SPAN style="COLOR:blue;"&gt;Address &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;from&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; Person&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;Address &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;Inspect the number of rows by running the following queries. It must show 19,614 rows.&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;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; &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;partitions &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;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.Address'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;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; &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;dm_db_partition_stats 
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;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.Address'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal&gt;Run the following query&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&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;&lt;SPAN style="COLOR:blue;"&gt;Address &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; city &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; &lt;SPAN style="COLOR:red;"&gt;'London' &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal&gt;Running this query will create new statistics for the city column and will show the following plan. Note that the estimated number of rows is 434 and it is using a simple Table Scan operator&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="TEXT-ALIGN:center;" align=center&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_5DF90560.jpg"&gt;&lt;IMG title=clip_image002 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height=142 alt=clip_image002 src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_1ADEBA63.jpg" width=334 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;We can see where the Query Optimizer is getting the estimated number of rows by inspecting the statistics object. Run this query to see the name of the statistics object&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&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; &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;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;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.Address'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;) &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal&gt;Then use the displayed statistics object name in the following statement (the name may be different in your case)&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;dbcc&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:blue;"&gt;show_statistics&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'dbo.Address'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&lt;/SPAN&gt; _WA_Sys_00000004_46136164&lt;SPAN style="COLOR:gray;"&gt;) &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal&gt;By looking at the histogram you can find the value 434 on EQ_ROWS for the RANGE_HI_KEY value ‘London’ (Statistics and histograms are explained on previous posts in this blog)&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image004_08C42013.jpg"&gt;&lt;IMG title=clip_image004 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:block;FLOAT:none;MARGIN-LEFT:auto;BORDER-LEFT:0px;MARGIN-RIGHT:auto;BORDER-BOTTOM:0px;" height=93 alt=clip_image004 src="http://sqlblog.com/blogs/ben_nevarez/clip_image004_thumb_76A985C2.jpg" width=540 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Now run the UPDATE STATISTICS WITH ROWCOUNT, PAGECOUNT (you can specify any other value for rowcount and pagecount)&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&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;&lt;SPAN style="COLOR:blue;"&gt;Address&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;with&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;rowcount&lt;/SPAN&gt; &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 1000000&lt;SPAN style="COLOR:gray;"&gt;,&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;pagecount&lt;/SPAN&gt; &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 100000 &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal&gt;If you inspect the number of rows again from sys.partitions or sys.dm_db_partition_stats, as shown previously, it will now show 1,000,000 rows. sys.dm_db_partition_stats also shows the new number of pages. Clear the plan cache and run the query again&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;dbcc&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; freeproccache &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;go &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:gray;"&gt;*&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;from&lt;/SPAN&gt; dbo&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR:blue;"&gt;Address &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; city &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; &lt;SPAN style="COLOR:red;"&gt;'London' &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal&gt;Note that the estimated number of rows has changed from 434 to 22,127.1 and that a different plan was generated using this new cardinality estimation. The Query Optimizer decided to parallelize this plan. But this is a very simple query, more dramatic plan changes can happen with more complex queries.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image006_3DC0D532.jpg"&gt;&lt;IMG title=clip_image006 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:block;FLOAT:none;MARGIN-LEFT:auto;BORDER-LEFT:0px;MARGIN-RIGHT:auto;BORDER-BOTTOM:0px;" height=135 alt=clip_image006 src="http://sqlblog.com/blogs/ben_nevarez/clip_image006_thumb_637B0FB6.jpg" width=508 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;After execution the actual number of rows obviously is still is 434 but the Query Optimizer is not able to see this value.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;If you look at the statistics object again, using DBCC SHOW_STATISTICS as shown before, the histogram has not changed. One way to obtain the estimated number of rows shown in the new execution plan is calculating the percentage or fraction of rows for the value ‘London’ from the statistics sample, which in this case is 19,614, as shown on the header of the statistics object. So the fraction is 434 / 19,614 or 022127052. Then obtain the same percentage from the new “current” number of rows which is 1,000,000 calculated as 1,000,000 * 0.022127052 and we get 22,127.1 which is the estimated number of rows displayed in the plan.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Finally, drop the table you just created&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&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;&lt;SPAN style="COLOR:blue;"&gt;Address &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=21032" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Performance/default.aspx">Performance</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Statistics/default.aspx">Statistics</category></item><item><title>Insecure Metadata</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/11/18/insecure-metadata.aspx</link><pubDate>Wed, 18 Nov 2009 09:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:18927</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>0</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/18927.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=18927</wfw:commentRss><description>&lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;I was looking at some metadata access today and this reminded me of when I talked about this topic two years ago at the PASS Summit in Denver.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Back in SQL Server 2000 most of the existing metadata was available to members of the public role, that is, to any login that can connect to the SQL Server instance. SQL Server 2005 promises that a user can only see the metadata of an object the user owns or has access to. This was a huge security improvement. However, some items were still left available to any user, which in some cases could be a security concern. &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 us test some of it. Create a new login called &lt;i style="mso-bidi-font-style:normal;"&gt;insecure&lt;/i&gt; without granting any permission to it. Connect as that user and see what kind of information from the server you are able to obtain. Try this first&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; &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;databases       &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;This new user is able to see the list of all the databases on the server, including the ones he does not have access to. Try&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; &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;configurations       &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;This time you can see some configuration information of your instance including some specific security information like if the ‘c2 audit mode’ is enabled.&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 data available to any SQL Server user is information about the location of the files of the current database, linked servers or backup devices. Try these&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; &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;database_files       &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;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; &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;servers       &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;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; &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;backup_devices       &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;Here I am using catalog views only but the same applies if you use the SQL Server 2000 compatibility views (like sysdatabases). You can also execute some stored procedures like these to get similar information&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:maroon;font-family:'Courier New';mso-no-proof:yes;"&gt;sp_helpdb&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:red;"&gt;'master'       &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;exec&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:maroon;"&gt;sp_configure       &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;exec&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:maroon;"&gt;sp_helpfile       &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;exec&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:maroon;"&gt;sp_helpserver       &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;exec&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:maroon;"&gt;sp_helpdevice       &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;Now let us look at the msdb database. By looking at the following system tables (yes, these are called system tables) you can obtain all the information regarding backup and restore operations performed on your instance. You can obtain information like database names, location of databases files, locations of database backup files and names of users who performed these backups.&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;use&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; msdb     &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;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: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; backupfile      &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;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; backupmediafamily      &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;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; backupset      &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;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; restorefile      &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;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; restorehistory      &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" style="mso-layout-grid-align:none;"&gt;You can also run some extended stored procedures or functions like the following&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;exec&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;master&lt;/span&gt;&lt;span style="color:gray;"&gt;..&lt;/span&gt;&lt;span style="color:maroon;"&gt;xp_msver&lt;/span&gt;&lt;span style="color:blue;"&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;select&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:fuchsia;"&gt;serverproperty&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'ProductVersion'&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" 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:fuchsia;"&gt;serverproperty&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'IsIntegratedSecurityOnly'&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;For example, the first two display the version (build) of SQL Server, which can show if the database administrator has installed the latest service pack or security updates. This can reveal some known security vulnerability of your instance.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Perhaps you can see now that this information, like security configuration, database names, database file names, location of database backups, user names, etc. could be used by an attacker to get additional permissions or data.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Certainly these are the defaults and many of them can be changed to be more secure, but many times this is not practical as some tools and applications depend on these defaults. For example, you can revoke the VIEW ANY DATABASE permission (executed as member of sysadmin) to secure the information displayed on sys.databases.&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;revoke&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;view&lt;/span&gt; &lt;span style="color:gray;"&gt;any&lt;/span&gt; &lt;span style="color:blue;"&gt;database&lt;/span&gt; &lt;span style="color:blue;"&gt;to&lt;/span&gt; &lt;span style="color:blue;"&gt;public       &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;But now only database owners can see their databases listed on sys.databases. Of course, this is a problem for a valid user who is not a database owner, who will only see the master and tempdb databases on this list. To test, grant db_datareader permissions to the &lt;i style="mso-bidi-font-style:normal;"&gt;insecure&lt;/i&gt; user to any user database. Test this again connected as the &lt;i style="mso-bidi-font-style:normal;"&gt;insecure&lt;/i&gt; login&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; &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;databases       &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;Only the master and tempdb databases are listed this time. One known issue of this configuration is that you can not use ODBC Data Source Administrator to create a new data source to connect to a database you have access to (unless you are the database owner)&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_5A489A4C.jpg"&gt;&lt;img title="clip_image002" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="326" alt="clip_image002" src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_70320C9C.jpg" width="427" 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;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Even Management Studio does not list all the databases you have access to (but you can use the USE statement)&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="text-align:center;" align="center"&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image004_6D8BE19C.jpg"&gt;&lt;img title="clip_image004" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="139" alt="clip_image004" src="http://sqlblog.com/blogs/ben_nevarez/clip_image004_thumb_162A4DA4.jpg" width="296" 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;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;But what is still ironic is that, even when you can not use ODBC Data Source Administrator or list your databases in Management Studio, you can still use db_name() to list all the database names anyway like in&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:fuchsia;"&gt;db_name&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;5&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;Finally, note that a command introduced with SQL Server 2005, VIEW DEFINITION, could also help you to have more control on the access to SQL Server metadata.&lt;/p&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=18927" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Metadata/default.aspx">Metadata</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Security/default.aspx">Security</category></item><item><title>Database Engine Tuning Advisor and the Query Optimizer</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/11/11/database-engine-tuning-advisor-and-the-query-optimizer.aspx</link><pubDate>Thu, 12 Nov 2009 03:47:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:18767</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>2</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/18767.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=18767</wfw:commentRss><description>&lt;p class="MsoNormal"&gt;Did you know that the Database Engine Tuning Advisor (DTA) uses the Query Optimizer to help you to create indexes, indexed views, and partitions for your databases? The DTA uses the Query Optimizer to estimate the cost of queries so it can select the choices with the lowest estimated cost. But, how can the Query Optimizer estimate the cost of a query using, for example, an index that does not exist yet?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Creating indexes on a DTA session could be very expensive and can create some other performance problems in your database. In addition to that, when the Query Optimizer uses indexes to estimate the cost of a query, it uses only the index statistics; it does not need to access the index data. &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, to avoid creating real indexes during a DTA session, SQL Server has a special kind of indexes called hypothetical indexes. Hypothetical indexes are not real indexes, they only contain statistics and can be created with the undocumented command CREATE INDEX WITH STATISTICS_ONLY. This command only creates the statistics for the 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;You may not be able to see these indexes during a DTA session because they are dropped automatically. But you can see the CREATE INDEX WITH STATISTICS_ONLY and DROP INDEX commands if you run Profiler to see what the DTA is doing. You can also create these indexes manually as I will show you 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;Hypothetical index have been available in previous versions of SQL Server where they were used by the DTA predecessor, the Index Tuning Wizard.&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 us take a quick tour to some of these concepts here. Create a new table on the AdventureWorks database&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;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;Copy the following query and save it to a file&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; ProductID &lt;span style="color:gray;"&gt;=&lt;/span&gt; 897      &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;Open a new DTA session. You can optionally run a Profiler session if you want to inspect what the DTA is doing. On workload file select the file containing the SQL statement that you just created. Specify AdventureWorks both for the database to tune and for the database for workload analysis. Click the Start Analysis button.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;When the DTA analysis finishes run this query to inspect the contents of the msdb..DTA_reports_query 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; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:blue;"&gt;from&lt;/span&gt; msdb&lt;span style="color:gray;"&gt;..&lt;/span&gt;DTA_reports_query      &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;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_1CC91800.jpg"&gt;&lt;img title="clip_image002" style="border-right:0px;border-top:0px;display:block;float:none;margin-left:auto;border-left:0px;margin-right:auto;border-bottom:0px;" height="45" alt="clip_image002" src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_3EE537A7.jpg" width="507" 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;Notice that the table contains some information like the query that was tuned and the current and recommended cost. The current cost, 1.2434, is easy to obtain by directly requesting an estimated execution plan for the query&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="text-align:center;" align="center"&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image004_2302A52E.jpg"&gt;&lt;img title="clip_image004" style="border-right:0px;border-top:0px;display:inline;border-left:0px;border-bottom:0px;" height="239" alt="clip_image004" src="http://sqlblog.com/blogs/ben_nevarez/clip_image004_thumb_5A0DB697.jpg" width="315" 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;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Since the DTA analysis was completed, the needed hypothetical indexes were already dropped. In the next statement I will create the index recommended by the DTA, but instead of a regular index I will create it as a hypothetical index by adding WITH 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" 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;clustered&lt;/span&gt; &lt;span style="color:blue;"&gt;index&lt;/span&gt; cix_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; &lt;/span&gt;&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" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;with&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_only       &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"&gt;You can validate that a hypothetical index and statistics were created by running this (notice that the index is defined as hypothetical on the index_description field) &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:maroon;font-family:'Courier New';mso-no-proof:yes;"&gt;sp_helpindex&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:red;"&gt;'dbo.SalesOrderDetail'       &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" 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; &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;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;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;However, at the moment I am not aware of a way outside the DTA to ask the Query Optimizer to consider these hypothetical indexes on an estimated execution plan. So I am not able to see where the previous recommended cost is coming from.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Remove the hypothetical index by running 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;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;index&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SalesOrderDetail&lt;span style="color:gray;"&gt;.&lt;/span&gt;cix_ProductID      &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;Implement the DTA recommendation this time as a regular clustered index&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;clustered&lt;/span&gt; &lt;span style="color:blue;"&gt;index&lt;/span&gt; cix_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; &lt;/span&gt;&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;After implementing the recommendation and running the query, the clustered index is in fact being used by the Query Optimizer and this time the estimated cost I got was 0.0033652, very close to the recommended cost listed before on the msdb..DTA_reports_query.&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, drop the dbo.SalesOrderDetail table you just created.&lt;/p&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=18767" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Cost+Estimation/default.aspx">Cost Estimation</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Database+Engine+Tuning+Advisor/default.aspx">Database Engine Tuning Advisor</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Hypothetical+Indexes/default.aspx">Hypothetical Indexes</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Performance/default.aspx">Performance</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category></item><item><title>Are You Using Scalable Shared Databases?</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/10/30/are-you-using-scalable-shared-databases.aspx</link><pubDate>Fri, 30 Oct 2009 07:26:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:18368</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>12</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/18368.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=18368</wfw:commentRss><description>&lt;p&gt;Did you know that you can share read-only databases between several instances of SQL Server?&lt;/p&gt;  &lt;p&gt;Scalable Shared Databases is a very interesting SQL Server feature that many of us seem to almost have forgotten about it. Available for the first time in SQL Server 2005 and originally described on the Microsoft KB article 910378, it was later fully documented on Books Online. This Enterprise edition-only feature allows a read-only database to be accessed at the same time by two or more SQL Server instances (maximum recommended is 8). This configuration offers some performance benefits by allowing each of these instances to use its own resources like memory, CPU, and tempdb database. Scalable Shared Databases are used as reporting databases.&lt;/p&gt;  &lt;p&gt;The concept behind Scalable Shared Databases is very simple: you copy a detached database to a volume, configure that volume as read-only, and then you can attach this database by several SQL Server instances. A shared database will look like a regular read-only database in Management Studio.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_203CEA28.jpg"&gt;&lt;img title="clip_image002" style="border-right:0px;border-top:0px;display:block;float:none;margin-left:auto;border-left:0px;margin-right:auto;border-bottom:0px;" height="238" alt="clip_image002" src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_3BA36F9B.jpg" width="273" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;By the way, it would be interesting to know if Microsoft plans to add additional functionality to this scalability feature or to extend it to read-write databases, perhaps something similar to what Oracle RAC is already doing.&lt;/p&gt;  &lt;p&gt;For more details, especially on restrictions and configuration, see the ‘Deploying a Scalable Shared Database’ entry on Books Online.&lt;/p&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=18368" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Performance/default.aspx">Performance</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Scalability/default.aspx">Scalability</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Scalable+Shared+Databases/default.aspx">Scalable Shared Databases</category></item><item><title>Presenting at PASS: How the Query Optimizer Works</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/10/27/presenting-at-pass-how-the-query-optimizer-works.aspx</link><pubDate>Tue, 27 Oct 2009 06:20:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:18295</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>0</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/18295.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=18295</wfw:commentRss><description>&lt;P&gt;I am excited that this is going to be my second time speaking at the PASS Summit. I have been attending PASS every year since 2003: a few times in Seattle, but also in Orlando (just after hurricane Jeanne), Dallas (just after hurricane Rita), and Denver.&lt;/P&gt;
&lt;P&gt;My session, How the Query Optimizer Works, is scheduled for Wednesday, November 4, 1:30pm - 2:45pm, in room 201.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://summit2009.sqlpass.org/Agenda/ProgramSessions/HowtheQueryOptimizerWorks.aspx"&gt;http://summit2009.sqlpass.org/Agenda/ProgramSessions/HowtheQueryOptimizerWorks.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;So, if you are attending PASS, I hope you can stop by my session or say hello at any of the PASS events.&lt;/P&gt;
&lt;P&gt;This is the description of my session:&lt;/P&gt;
&lt;P&gt;“The Query Optimizer is the component of SQL Server that attempts to determine the best way to execute a query by finding an efficient execution plan. This session will show you how a better understanding on how the Query Optimizer works and what information it needs to generate better execution plans, can help you to improve the performance of your databases. Learn about the high level structures of the Query Optimizer and some important factors that are considered during the optimization phase of query processing. See how you can provide SQL Server with appropriate statistics and indexes so it can perform better cardinality estimation and produce an efficient execution plan. Since the SQL Server Query Optimizer is a cost-based optimizer, this information will help it to better estimate the execution plan cost. Finally, although the Query Optimizer almost always selects a good enough execution plan for a query, it may not create an efficient plan for all the possible scenarios. See how you can troubleshoot these issues and how you can use other alternatives like hints or plan guides to force the query optimizer to produce a better execution plan.” &lt;/P&gt;
&lt;P&gt;Hope to see you there!&lt;/P&gt;
&lt;P&gt;Ben&lt;/P&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_35F1726B.jpg"&gt;&lt;IMG title=clip_image002 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:block;FLOAT:none;MARGIN-LEFT:auto;BORDER-LEFT:0px;MARGIN-RIGHT:auto;BORDER-BOTTOM:0px;" height=121 alt=clip_image002 src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_4AA4EE5B.jpg" width=555 border=0&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=18295" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/PASS+Summit/default.aspx">PASS Summit</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Speaking/default.aspx">Speaking</category></item><item><title>Rebuilding Indexes vs. Updating Statistics</title><link>http://www2.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><slash:comments>3</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/17301.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=17301</wfw:commentRss><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;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=17301" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Indexes/default.aspx">Indexes</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Performance/default.aspx">Performance</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Statistics/default.aspx">Statistics</category></item><item><title>Speaking at the Orange County SQL Server Professionals User Group</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/09/30/speaking-at-the-orange-county-sql-server-professionals-user-group.aspx</link><pubDate>Wed, 30 Sep 2009 06:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:17085</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>2</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/17085.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=17085</wfw:commentRss><description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I will be speaking at the Orange County SQL Server Professionals User Group this Thursday, October 1st, 2009. The topic is “How the Query Optimizer Works”. So if you are in the Orange County or Los Angeles area please stop by and say hello.&lt;/P&gt;
&lt;P&gt;The meeting starts at 6:30 PM. More details and directions can be found here&lt;/P&gt;
&lt;P&gt;Orange County SQL Server Professionals User Group&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.sqloc.com/"&gt;http://www.sqloc.com&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=17085" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Speaking/default.aspx">Speaking</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/User+Group+Meetings/default.aspx">User Group Meetings</category></item><item><title>The Missing Indexes Feature</title><link>http://www2.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><slash:comments>3</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/16984.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=16984</wfw:commentRss><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;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=16984" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Indexes/default.aspx">Indexes</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Optimization/default.aspx">Optimization</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Performance/default.aspx">Performance</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category></item><item><title>Speaking at Los Angeles SQL Server Professionals Group</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/09/14/speaking-at-los-angeles-sql-server-professionals-group.aspx</link><pubDate>Tue, 15 Sep 2009 04:06:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:16780</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>2</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/16780.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=16780</wfw:commentRss><description>&lt;p class="MsoNormal"&gt;I will be speaking at Los Angeles SQL Server Professionals Group this Thursday, September 17, 2009. The topic is “How the Query Optimizer Works”. So if you are in the area please stop by and say hello.&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 meeting starts at 6:30 PM. More details and directions can be found here&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Los Angeles SQL Server Professionals Group&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;a href="http://sql.la/"&gt;http://sql.la&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=16780" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Speaking/default.aspx">Speaking</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/User+Group+Meetings/default.aspx">User Group Meetings</category></item><item><title>How the Query Optimizer Uses Statistics – Part II</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/09/11/how-the-query-optimizer-uses-statistics-part-ii.aspx</link><pubDate>Sat, 12 Sep 2009 05:32:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:16732</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>0</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/16732.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=16732</wfw:commentRss><description>&lt;p class="MsoNormal"&gt;I got a question from a reader of my post How the Query Optimizer Uses Statistics (http://sqlblog.com/blogs/ben_nevarez/archive/2009/09/03/how-the-query-optimizer-uses-statistics.aspx) and I thought that it would be a good idea to post my answer here. Basically the request was to expand the previous example for a predicate with two columns.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;First, a reminder that the histogram only shows the values of the first column of the statistics object. So, how the Query Optimizer does this?&lt;/p&gt;  &lt;p class="MsoNormal"&gt;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;One way to find the answer to this is, well, just to run an example and see what the Query Optimizer does. Let us run a query, see which statistics are automatically created and inspect those 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;This is the code sent by the reader. Run this to create a table and populate it with some data.&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;table&lt;/span&gt; MyStatsTest&lt;span style="color:blue;"&gt; &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" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;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;id &lt;span style="color:blue;"&gt;int&lt;/span&gt; &lt;span style="color:blue;"&gt;identity&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt; 1&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" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;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;ProductGroupID &lt;span style="color:blue;"&gt;int&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" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;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;ProductID &lt;span style="color:blue;"&gt;int       &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;&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;declare&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; @i &lt;span style="color:blue;"&gt;int       &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;set&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;nocount&lt;/span&gt; &lt;span style="color:blue;"&gt;on       &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;set&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; @i &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" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;while&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; @i &lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt; 100000      &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;begin     &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="text-indent:0.5in;mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;insert&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; MyStatsTest&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;ProductGroupID&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" style="text-indent:0.5in;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:fuchsia;"&gt;datepart&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;millisecond&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;getdate&lt;/span&gt;&lt;span style="color:gray;"&gt;())&lt;/span&gt; &lt;span style="color:gray;"&gt;%&lt;/span&gt; 2&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;datepart&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;millisecond&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;getdate&lt;/span&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;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;&lt;span style="color:blue;"&gt;set&lt;/span&gt; @i &lt;span style="color:gray;"&gt;=&lt;/span&gt; @i &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" style="mso-layout-grid-align:none;"&gt;&lt;span style="font-size:10pt;color:blue;font-family:'Courier New';mso-no-proof:yes;"&gt;end     &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;Make sure you start with no statistics objects in the table. You can run this to verify that there are no statistics&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; &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;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;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;'MyStatsTest'&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;If there are some statistics, perhaps after running a query, you can drop them using a command like this (the name of your statistics objects may be different)&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;statistics&lt;/span&gt; MyStatsTest&lt;span style="color:gray;"&gt;.&lt;/span&gt;_WA_Sys_00000002_7D78A4E7      &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 the first query to see the statistics created automatically 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;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; MyStatsTest      &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; ProductId &lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt; 17 &lt;span style="color:gray;"&gt;and&lt;/span&gt; ProductGroupId &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;Now you can run the previous query again and notice that two statistics objects were created. Use DBCC SHOW_STATISTICS to display both histograms like in the next example &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;dbcc&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';mso-no-proof:yes;"&gt; &lt;span style="color:blue;"&gt;show_statistics&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'MyStatsTest'&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; _WA_Sys_00000003_014935CB&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;You can use the first histogram to estimate the number of records for the ProductId &amp;lt; 17 predicate using the method I described in my previous post. I got 1,744 rows which is the sum of the values 392, 302, 313, 419 and 318 (Your table has different data so you will get a different value). &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;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_0CFE1901.jpg"&gt;&lt;img title="clip_image002" style="border-right:0px;border-top:0px;display:block;float:none;margin-left:auto;border-left:0px;margin-right:auto;border-bottom:0px;" height="117" alt="clip_image002" src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_6D1138B5.jpg" width="286" 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;Using the second histogram you can notice that 60.0316003% of the records have ProductGroupid = 1 (This is 60,031 divided by the total number of records 99,999). &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"&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image004_3F52126F.jpg"&gt;&lt;img title="clip_image004" style="border-right:0px;border-top:0px;display:block;float:none;margin-left:auto;border-left:0px;margin-right:auto;border-bottom:0px;" height="63" alt="clip_image004" src="http://sqlblog.com/blogs/ben_nevarez/clip_image004_thumb_18B228A1.jpg" width="291" 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;   &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Since this is using the AND operator you need to obtain the 60.0316003% of 1,744. This is 1,046.95 which is the estimated number of rows shown on the execution plan of the query.&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"&gt;&lt;a href="http://sqlblog.com/blogs/ben_nevarez/clip_image006_3248584D.jpg"&gt;&lt;img title="clip_image006" style="border-right:0px;border-top:0px;display:block;float:none;margin-left:auto;border-left:0px;margin-right:auto;border-bottom:0px;" height="148" alt="clip_image006" src="http://sqlblog.com/blogs/ben_nevarez/clip_image006_thumb_72406B44.jpg" width="318" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;You can do the same calculation for ProductGroupId = 0 and you will get an estimated number of rows of 697.049 which are also shown on the execution plan. Notice that you may need to run DBCC FREEPROCCACHE between tests to clear the plan cache, otherwise it may show a cached 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"&gt;Finally, let us change the query to use OR operator (instead of AND)&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; MyStatsTest      &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; ProductId &lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt; 17 &lt;span style="color:gray;"&gt;or&lt;/span&gt; ProductGroupId &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;The plan shows 60,728 estimated rows. Since this is using an OR operator this value could be obtained as the union of the following two queries&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; MyStatsTest      &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; ProductId &lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt; 17&lt;span style="mso-spacerun:yes;"&gt;&amp;#160;&amp;#160;&amp;#160; &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: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"&gt;and&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; MyStatsTest      &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; ProductId &lt;span style="color:gray;"&gt;&amp;gt;=&lt;/span&gt; 17 &lt;span style="color:gray;"&gt;and&lt;/span&gt; ProductGroupId &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;The first query estimates 1,744 rows and the second one 58,984, for a total of 60,720 rows. You can use the previous method to estimate these values.&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 same value could also be obtained as the union of these two queries&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; MyStatsTest       &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; ProductId &lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt; 17 &lt;span style="color:gray;"&gt;and&lt;/span&gt; ProductGroupId &lt;span style="color:gray;"&gt;=&lt;/span&gt; 0      &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&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; MyStatsTest      &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; ProductGroupId &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;The first one shows 697.049 estimated rows and the second one 60,031, for a total of 60,728.049 estimated rows.&lt;/p&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=16732" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Statistics/default.aspx">Statistics</category></item><item><title>Statistics Used by the Query Optimizer in SQL Server White Paper</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/09/04/statistics-used-by-the-query-optimizer-in-sql-server-white-paper.aspx</link><pubDate>Fri, 04 Sep 2009 23:47:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:16618</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>0</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/16618.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=16618</wfw:commentRss><description>&lt;P class=MsoNormal&gt;In case you are not aware, the excellent white paper “Statistics Used by the Query Optimizer in SQL Server” has been updated for SQL Server 2008.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;You can find it here&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Statistics Used by the Query Optimizer in SQL Server 2008&lt;/P&gt;
&lt;P class=MsoNormal&gt;Writer: Eric N. Hanson and Yavor Angelov&lt;/P&gt;
&lt;P class=MsoNormal&gt;Contributor: Lubor Kollar&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd535534.aspx"&gt;http://msdn.microsoft.com/en-us/library/dd535534.aspx&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=16618" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Statistics/default.aspx">Statistics</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/White+papers/default.aspx">White papers</category></item><item><title>How the Query Optimizer Uses Statistics</title><link>http://www2.sqlblog.com/blogs/ben_nevarez/archive/2009/09/03/how-the-query-optimizer-uses-statistics.aspx</link><pubDate>Thu, 03 Sep 2009 06:00:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:16548</guid><dc:creator>Ben Nevarez</dc:creator><slash:comments>4</slash:comments><comments>http://www2.sqlblog.com/blogs/ben_nevarez/comments/16548.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/ben_nevarez/commentrss.aspx?PostID=16548</wfw:commentRss><description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;This post shows how the Query Optimizer uses statistics to estimate the selectivity of expressions during query optimization.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;You can also use this as a second part of my last post, The Query Optimizer and Parameter Sniffing. Here I will show you the advantage of the use of statistics when the Query Optimizer can “sniff” the parameter values compared to just guessing the selectivity of expressions when local variables are used. So I will be using the same query as in that previous post.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Notice that there are many other details that can not be covered here so this post will focus on a very simple example to show how the Query Optimizer creates and uses statistics.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;To start open your AdventureWorks database and run this to display the current statistics on the ProductID column of the Sales.SalesOrderDetail table&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;dbcc&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:blue;"&gt;show_statistics&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR:red;"&gt;'Sales.SalesOrderDetail'&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;,&lt;/SPAN&gt; IX_SalesOrderDetail_ProductID&lt;SPAN style="COLOR:gray;"&gt;) &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;This will display the header, density vector and histogram of the statistics object.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;1) Understanding the Histogram&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;First I will explain the meaning of the values of a histogram’s steps. Let us take a look at step 86, shown here&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image002_59D696CA.jpg"&gt;&lt;IMG title=clip_image002 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:block;FLOAT:none;MARGIN-LEFT:auto;BORDER-LEFT:0px;MARGIN-RIGHT:auto;BORDER-BOTTOM:0px;" height=73 alt=clip_image002 src="http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_5E0F110E.jpg" width=505 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;RANGE_HI_KEY is the upper boundary of a histogram step. The value 826 is the upper boundary for step 85 and 831 is the upper boundary for step 86. This means that step 86 may contain only values from 827 to 831.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Run the following query to obtain the real number of records for ProductIDs 827 to 831 to compare them against the histogram&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&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; ProductID&lt;SPAN style="COLOR:gray;"&gt;,&lt;/SPAN&gt; &lt;SPAN style="COLOR:fuchsia;"&gt;COUNT&lt;/SPAN&gt;&lt;SPAN style="COLOR:gray;"&gt;(*)&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;as&lt;/SPAN&gt; Total &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;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;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; ProductID &lt;SPAN style="COLOR:gray;"&gt;between&lt;/SPAN&gt; 827 &lt;SPAN style="COLOR:gray;"&gt;and&lt;/SPAN&gt; 831 &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;group&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:blue;"&gt;by&lt;/SPAN&gt; ProductID &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;This produces the following result&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image004_77390DC5.jpg"&gt;&lt;IMG title=clip_image004 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:block;FLOAT:none;MARGIN-LEFT:auto;BORDER-LEFT:0px;MARGIN-RIGHT:auto;BORDER-BOTTOM:0px;" height=107 alt=clip_image004 src="http://sqlblog.com/blogs/ben_nevarez/clip_image004_thumb_658AA66A.jpg" width=147 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Going back to the histogram, EQ_ROWS is the estimated number of rows whose column value equals RANGE_HI_KEY. In our example RANGE_HI_KEY is 831 and the number of records with ProductID 831 is 198. The same value is shown on the histogram.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;RANGE_ROWS is the estimated number of rows whose column value falls inside the range of the step, excluding the upper boundary. In our example, this is the number of records with values from 827 to 830 (831, the upper boundary, is excluded). The histogram shows 110 records and we could obtain the same value by getting the sum of 31 records for 827, 46 records for 828, 0 records for 829 and 33 records for 830. &lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;DISTINCT_RANGE_ROWS is the estimated number of rows with a distinct column value inside this range, excluding the upper bound. In our example we have records for three distinct values: 827, 828, and 830, so DISTINCT_RANGE_ROWS is 3. There are no records for ProductID 829 and 831 is again excluded.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Finally, AVG_RANGE_ROWS is the average number of rows per distinct value and it is calculated as RANGE_ROWS / DISTINCT_RANGE_ROWS. In our example, we have a total of 110 records for 3 DISTINCT_RANGE_ROWS, so that gives, 110 / 3 = 36.6667 also shown on the histogram for step 86.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Now let us see how the statistics are used to estimate the selectivity of the queries.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;2) When the Query Optimizer knows the value&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Let us see the first query&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:gray;"&gt;*&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;from&lt;/SPAN&gt; Sales&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;SalesOrderDetail &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; ProductID &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 831 &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="TEXT-ALIGN:center;mso-layout-grid-align:none;" align=center&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image006_29F93A29.jpg"&gt;&lt;IMG title=clip_image006 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height=140 alt=clip_image006 src="http://sqlblog.com/blogs/ben_nevarez/clip_image006_thumb_782FC610.jpg" width=370 border=0&gt;&lt;/A&gt; 
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal&gt;Since 831 is a RANGE_HI_KEY on step 86, the Query Optimizer will use the EQ_ROWS value and the estimated number of rows will be 198.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Now run the same query with the value 828&lt;/P&gt;
&lt;P class=MsoNormal style="TEXT-ALIGN:center;" align=center&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image008_713EB60A.jpg"&gt;&lt;IMG title=clip_image008 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height=143 alt=clip_image008 src="http://sqlblog.com/blogs/ben_nevarez/clip_image008_thumb_716CE27C.jpg" width=374 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;This time the value is inside the range of step 86 but it is not a RANGE_HI_KEY so the Query Optimizer uses the value calculated before as AVG_RANGE_ROWS. Actually, we get the same estimated number of rows for any of the other values in the range (except RANGE_HI_KEY). This also includes 829, even when there are no records for this ProductID.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Let us try now a nonequality operator and try to find the number of records less than 714. For these we need to calculate the sum of the values of both RANGE_ROWS and EQ_ROWS for steps 1 thru 7, which give us a total of 13,223 rows.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="TEXT-ALIGN:center;" align=center&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image010_1869252F.jpg"&gt;&lt;IMG title=clip_image010 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height=178 alt=clip_image010 src="http://sqlblog.com/blogs/ben_nevarez/clip_image010_thumb_6CE687A4.jpg" width=522 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;This is the query and the estimated number of rows is shown on the execution plan&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:gray;"&gt;*&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;from&lt;/SPAN&gt; Sales&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;SalesOrderDetail &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; ProductID &lt;SPAN style="COLOR:gray;"&gt;&amp;lt;&lt;/SPAN&gt; 714 &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="TEXT-ALIGN:center;" align=center&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image012_05A45167.jpg"&gt;&lt;IMG title=clip_image012 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height=147 alt=clip_image012 src="http://sqlblog.com/blogs/ben_nevarez/clip_image012_thumb_1ECE4E1E.jpg" width=340 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;3) When the Query Optimizer does not know the value&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;In the case when the Query Optimizer does not know the value used in the expression, like when local variables are used, the Query Optimizer can not use the histogram so it will use some other information including the statistics density information or it will try to guess the selectivity using some fixed percentages. First, let us try using the equality operator.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;declare&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; @pid &lt;SPAN style="COLOR:blue;"&gt;int&lt;/SPAN&gt; &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 897 &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:gray;"&gt;*&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;from&lt;/SPAN&gt; Sales&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;SalesOrderDetail &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; ProductID &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; @pid&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The Query Optimizer is not able to see the value 897 in this query. As explained in my previous post, the Query Optimizer does not know the value of the @pid local variable at optimization time. So it will use the density value of the ProductID column, 0.003759399, as listed on the second section, density vector, of the DBCC SHOW_STATISTICS output. If we multiply this value by the total number of records, 121,317, we will get 456.079 which will be shown in the next execution plan.&lt;/P&gt;
&lt;P class=MsoNormal style="TEXT-ALIGN:center;" align=center&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image014_5EC66115.jpg"&gt;&lt;IMG title=clip_image014 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height=156 alt=clip_image014 src="http://sqlblog.com/blogs/ben_nevarez/clip_image014_thumb_3ACF32F8.jpg" width=344 border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Finally, run this query with a nonequality operator&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;declare&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; @pid &lt;SPAN style="COLOR:blue;"&gt;int&lt;/SPAN&gt; &lt;SPAN style="COLOR:gray;"&gt;=&lt;/SPAN&gt; 897 &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; &lt;SPAN style="COLOR:gray;"&gt;*&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;from&lt;/SPAN&gt; Sales&lt;SPAN style="COLOR:gray;"&gt;.&lt;/SPAN&gt;SalesOrderDetail &lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt; ProductID &lt;SPAN style="COLOR:gray;"&gt;&amp;lt;&lt;/SPAN&gt; @pid &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal&gt;Same as before, the value 897 does not matter; any other value will give you the same estimated number of rows and execution plan. The estimated number of rows is always 30% of the total number of records for a nonequality operator. In this case the 30% of 121,317 is 36,395.1 as shown next.&lt;/P&gt;
&lt;P class=MsoNormal style="TEXT-ALIGN:center;" align=center&gt;&lt;A href="http://sqlblog.com/blogs/ben_nevarez/clip_image016_6CF4FFF4.jpg"&gt;&lt;IMG title=clip_image016 style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height=161 alt=clip_image016 src="http://sqlblog.com/blogs/ben_nevarez/clip_image016_thumb_340C4F64.jpg" width=352 border=0&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=16548" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Optimization/default.aspx">Optimization</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Performance/default.aspx">Performance</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Query+Optimizer/default.aspx">Query Optimizer</category><category domain="http://www2.sqlblog.com/blogs/ben_nevarez/archive/tags/Statistics/default.aspx">Statistics</category></item></channel></rss>