<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results matching tags 'Query Plans', 'execution plans', and 'aggregates'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Query+Plans,execution+plans,aggregates&amp;orTags=0</link><description>Search results matching tags 'Query Plans', 'execution plans', and 'aggregates'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Why generalizations are dangerous</title><link>http://sqlblog.com/blogs/aaron_bertrand/archive/2011/09/15/why-generalizations-are-dangerous.aspx</link><pubDate>Thu, 15 Sep 2011 23:19:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:38491</guid><dc:creator>AaronBertrand</dc:creator><description>&lt;p&gt;A couple of years ago, John Sansom wrote a blog post comparing the performance of two different ways to get the maximum value from a column: MAX() and TOP (1).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://www.johnsansom.com/performance-comparison-of-select-top-1-verses-max/" title="http://www.johnsansom.com/performance-comparison-of-select-top-1-verses-max/" target="_blank"&gt;http://www.johnsansom.com/performance-comparison-of-select-top-1-verses-max/&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the conclusion, he states:&amp;nbsp; &lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;div style="padding:10px 20px;"&gt;&lt;i&gt;When a clustered index is present on the table &amp;amp; column that is 
to be selected, both the MAX() operator and the query (SELECT TOP 1 
ColumnName order by ColumnName) have almost identical performance.
&lt;/i&gt;
&lt;p&gt;&lt;i&gt;When there is no clustered index on the table &amp;amp; column to be queried, the MAX() operator offers the better performance.&lt;/i&gt;
&lt;/p&gt;
&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now for this specific case, that is quite true. But I find it alarming when people take his conclusion and believe it applies to every single scenario - so much so that they make policy decisions around prohibiting the use of TOP 1 in all situations (regardless of whether the ordering is on an indexed column, a non-indexed column, or even an aggregate). This isn't John's fault, of course. It's just the nature of people who believe that something they see once means it applies everywhere (SELECT without ORDER BY, anyone?).&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Recently a user asked the community to help them re-write a query that was currently using TOP 1 - not because the query was slow or produced the wrong results, but because they were told they could no longer use TOP 1. When asked why, they simply pointed at John's blog post above, and were going with the theory that TOP 1 is always slower and it must be eradicated from their codebase. &lt;br&gt;&lt;/p&gt;

&lt;p&gt;Not being a big fan of generalizations, I tried to explain that John's situation was not quite the same - for one he was getting the max value from a single column, whereas the query in question actually wanted the max from an aggregate in a subquery - but they didn't seem to want to have anything to do with it. So, naturally, I set out to run some tests myself. Here is the query that was subject to refactoring - essentially they wanted the team name with the highest number of members:&lt;/p&gt;

&lt;blockquote&gt;
&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;SELECT &lt;/font&gt;&lt;font color="black"&gt;t.name&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;FROM&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;team &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;t&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;INNER JOIN &lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;SELECT TOP &lt;/font&gt;&lt;font color="black"&gt;1 &lt;/font&gt;&lt;font color="magenta"&gt;COUNT&lt;/font&gt;&lt;font color="gray"&gt;(*) &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;membercount&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;teamID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;FROM&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;dbo.teammember&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;GROUP BY &lt;/font&gt;&lt;font color="black"&gt;teamID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;ORDER BY &lt;/font&gt;&lt;font color="magenta"&gt;COUNT&lt;/font&gt;&lt;font color="gray"&gt;(*) &lt;/font&gt;&lt;font color="blue"&gt;DESC&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;team_with_most_members&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;ON &lt;/font&gt;&lt;font color="black"&gt;t.id &lt;/font&gt;&lt;font&gt;&lt;font color="black"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="black"&gt;team_with_most_members.teamID&lt;/font&gt;&lt;font color="gray"&gt;;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/blockquote&gt;

&lt;p&gt;There were two other solutions offered (well, three, but one didn't work). One was from me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;SELECT &lt;/font&gt;&lt;font color="black"&gt;t.name &lt;/font&gt;&lt;font color="blue"&gt;FROM&lt;br&gt;&lt;/font&gt;&lt;font color="gray"&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;TeamID&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;rn &lt;/font&gt;&lt;font&gt;&lt;font color="black"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="magenta"&gt;ROW_NUMBER&lt;/font&gt;&lt;font color="gray"&gt;() &lt;/font&gt;&lt;font color="blue"&gt;OVER &lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;ORDER BY &lt;/font&gt;&lt;font color="black"&gt;c &lt;/font&gt;&lt;font color="blue"&gt;DESC&lt;/font&gt;&lt;font color="gray"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;FROM&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="gray"&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;TeamID&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;c &lt;/font&gt;&lt;font&gt;&lt;font color="black"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="magenta"&gt;COUNT&lt;/font&gt;&lt;font color="gray"&gt;(*)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="black"&gt;dbo.TeamMember &lt;/font&gt;&lt;font color="blue"&gt;GROUP BY &lt;/font&gt;&lt;font color="black"&gt;TeamID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;x&lt;br&gt;&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;y&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;INNER JOIN &lt;/font&gt;&lt;font color="black"&gt;dbo.Team &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;t&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;ON &lt;/font&gt;&lt;font color="black"&gt;y.TeamID &lt;/font&gt;&lt;font&gt;&lt;font color="black"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="black"&gt;t.ID&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;WHERE &lt;/font&gt;&lt;font color="black"&gt;y.rn &lt;/font&gt;&lt;font&gt;&lt;font color="black"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="black"&gt;1&lt;/font&gt;&lt;font color="gray"&gt;;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
 
&lt;p&gt;And one was from Wil:&lt;/p&gt;

&lt;blockquote&gt;
&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;SELECT &lt;/font&gt;&lt;font color="black"&gt;t.name &lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="black"&gt;team &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;t &lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;JOIN &lt;/font&gt;&lt;font color="black"&gt;teammember &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;tm &lt;/font&gt;&lt;font color="blue"&gt;ON &lt;/font&gt;&lt;font color="black"&gt;tm.teamID &lt;/font&gt;&lt;font color="blue"&gt;= &lt;/font&gt;&lt;font color="black"&gt;t.ID &lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;GROUP BY &lt;/font&gt;&lt;font color="black"&gt;t.Name&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;HAVING &lt;/font&gt;&lt;font color="magenta"&gt;COUNT&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;tm.id&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font&gt;&lt;font color="black"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;SELECT &lt;/font&gt;&lt;font color="magenta"&gt;MAX&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;members&lt;/font&gt;&lt;font color="gray"&gt;)&lt;br&gt; &lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;SELECT &lt;/font&gt;&lt;font color="magenta"&gt;COUNT&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;id&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="black"&gt;members &lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="black"&gt;teammember &lt;/font&gt;&lt;font color="blue"&gt;GROUP BY &lt;/font&gt;&lt;font color="black"&gt;teamid&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="blue"&gt;AS &lt;/font&gt;&lt;font color="black"&gt;sub&lt;/font&gt;&lt;font color="gray"&gt;)&lt;/font&gt; 
&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/blockquote&gt;

So to compare the three options, I first created some sample tables. The first was the main Team table:&lt;br&gt;

&lt;blockquote&gt;
&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;CREATE TABLE &lt;/font&gt;&lt;font color="black"&gt;dbo.Team&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;ID &lt;/font&gt;&lt;font color="blue"&gt;INT PRIMARY KEY CLUSTERED&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;Name &lt;/font&gt;&lt;font color="blue"&gt;VARCHAR&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;32&lt;/font&gt;&lt;font color="gray"&gt;));&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/blockquote&gt;

&lt;p&gt;Then I created two versions of the TeamMember table, one with a clustered index on the TeamID column, and one with a non-clustered index: &lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;CREATE TABLE &lt;/font&gt;&lt;font color="black"&gt;dbo.TeamMember_A&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;ID &lt;/font&gt;&lt;font color="blue"&gt;INT IDENTITY&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;1&lt;/font&gt;&lt;font color="gray"&gt;,&lt;/font&gt;&lt;font color="black"&gt;1&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="blue"&gt;PRIMARY KEY NONCLUSTERED&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;TeamID &lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;Name &lt;/font&gt;&lt;font color="blue"&gt;VARCHAR&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;32&lt;/font&gt;&lt;font color="gray"&gt;));&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;CREATE CLUSTERED INDEX &lt;/font&gt;&lt;font color="black"&gt;x &lt;/font&gt;&lt;font color="blue"&gt;ON &lt;/font&gt;&lt;font color="black"&gt;dbo.TeamMember_A&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;TeamID&lt;/font&gt;&lt;font color="gray"&gt;);&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;CREATE TABLE &lt;/font&gt;&lt;font color="black"&gt;dbo.TeamMember_B&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;ID &lt;/font&gt;&lt;font color="blue"&gt;INT IDENTITY&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;1&lt;/font&gt;&lt;font color="gray"&gt;,&lt;/font&gt;&lt;font color="black"&gt;1&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="blue"&gt;PRIMARY KEY CLUSTERED&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;TeamID &lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;Name &lt;/font&gt;&lt;font color="blue"&gt;VARCHAR&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;32&lt;/font&gt;&lt;font color="gray"&gt;));&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;CREATE INDEX &lt;/font&gt;&lt;font color="black"&gt;x &lt;/font&gt;&lt;font color="blue"&gt;ON &lt;/font&gt;&lt;font color="black"&gt;dbo.TeamMember_B&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;TeamID&lt;/font&gt;&lt;font color="gray"&gt;);&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/blockquote&gt;

&lt;p&gt;To populate them with a reasonable volume of data, I performed some creative queries against sys.objects. First I populated a table variable with a group of random rows based on object_id, with the first column being the TeamID, and the second column being the number of rows that I would insert into the TeamMember tables:

&lt;/p&gt;&lt;blockquote&gt;
&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;DECLARE &lt;/font&gt;&lt;font color="#434343"&gt;@src &lt;/font&gt;&lt;font color="blue"&gt;TABLE&lt;br&gt;&lt;/font&gt;&lt;font color="gray"&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;TeamID &lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;TeamSize &lt;/font&gt;&lt;font color="blue"&gt;INT&lt;br&gt;&lt;/font&gt;&lt;font color="gray"&gt;);&lt;br&gt;&lt;br&gt;;&lt;/font&gt;&lt;font color="blue"&gt;WITH &lt;/font&gt;&lt;font color="black"&gt;x&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;o&lt;/font&gt;&lt;font color="gray"&gt;,&lt;/font&gt;&lt;font color="black"&gt;c&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="blue"&gt;AS&lt;br&gt;&lt;/font&gt;&lt;font color="gray"&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SELECT&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;[object_id] &lt;/font&gt;&lt;font color="gray"&gt;% &lt;/font&gt;&lt;font color="black"&gt;10000&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="magenta"&gt;CONVERT&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;[object_id] &lt;/font&gt;&lt;font color="gray"&gt;/ &lt;/font&gt;&lt;font color="black"&gt;15000.0&lt;/font&gt;&lt;font color="gray"&gt;) + &lt;/font&gt;&lt;font color="black"&gt;1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="black"&gt;sys.objects&lt;br&gt;&lt;/font&gt;&lt;font color="gray"&gt;)&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;INSERT &lt;/font&gt;&lt;font color="#434343"&gt;@src &lt;/font&gt;&lt;font color="blue"&gt;SELECT TOP &lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;30&lt;/font&gt;&lt;font color="gray"&gt;) &lt;/font&gt;&lt;font color="black"&gt;o&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;c&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="black"&gt;x &lt;/font&gt;&lt;font color="blue"&gt;WHERE &lt;/font&gt;&lt;font color="black"&gt;c &lt;/font&gt;&lt;font color="gray"&gt;&amp;gt; &lt;/font&gt;&lt;font color="black"&gt;0&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;ORDER BY &lt;/font&gt;&lt;font color="black"&gt;c &lt;/font&gt;&lt;font color="blue"&gt;DESC&lt;/font&gt;&lt;font color="gray"&gt;;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/blockquote&gt;

&lt;p&gt;This created 30 values like this (the last several rows yield c = 1): &lt;br&gt;&lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a.png" border="1" height="271" width="144"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Now that I had a set of 30 teams to create, I could use a cursor and a while loop (fun, fun) to populate the TeamMember tables. Could I have used a numbers table and done a cross join or something to avoid the loop? Sure, but this was easy enough and it is not exactly production code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;table bgcolor="#eeeeee" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;DECLARE &lt;/font&gt;&lt;font color="#434343"&gt;@TeamID &lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="#434343"&gt;@TeamSize &lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="#434343"&gt;@i &lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;DECLARE &lt;/font&gt;&lt;font color="black"&gt;c &lt;/font&gt;&lt;font color="blue"&gt;CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY&lt;/font&gt;&lt;font color="black"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;FOR SELECT &lt;/font&gt;&lt;font color="black"&gt;TeamID&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;TeamSize&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="#434343"&gt;@src&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;OPEN &lt;/font&gt;&lt;font color="black"&gt;c&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;FETCH NEXT &lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="black"&gt;c &lt;/font&gt;&lt;font color="blue"&gt;INTO &lt;/font&gt;&lt;font color="#434343"&gt;@TeamID&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="#434343"&gt;@TeamSize&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;WHILE &lt;/font&gt;&lt;font&gt;&lt;font color="magenta"&gt;@@FETCH_STATUS&lt;/font&gt;&lt;/font&gt;&lt;font color="#434343"&gt; &lt;/font&gt;&lt;font&gt;&lt;font&gt;&lt;font&gt;&lt;font color="black"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="black"&gt;0&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SET &lt;/font&gt;&lt;font color="#434343"&gt;@i &lt;/font&gt;&lt;font&gt;&lt;font color="black"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="black"&gt;1&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;WHILE &lt;/font&gt;&lt;font color="#434343"&gt;@i &lt;/font&gt;&lt;font color="gray"&gt;&amp;lt;= &lt;/font&gt;&lt;font color="#434343"&gt;@TeamSize&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;INSERT &lt;/font&gt;&lt;font color="black"&gt;dbo.TeamMember_A&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;TeamID&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;Name&lt;/font&gt;&lt;font color="gray"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SELECT &lt;/font&gt;&lt;font color="#434343"&gt;@TeamID&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="magenta"&gt;CONVERT&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;VARCHAR&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;32&lt;/font&gt;&lt;font color="gray"&gt;), &lt;/font&gt;&lt;font color="#434343"&gt;@TeamID&lt;/font&gt;&lt;font color="gray"&gt;);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;INSERT &lt;/font&gt;&lt;font color="black"&gt;dbo.TeamMember_B&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;TeamID&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="black"&gt;Name&lt;/font&gt;&lt;font color="gray"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SELECT &lt;/font&gt;&lt;font color="#434343"&gt;@TeamID&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="magenta"&gt;CONVERT&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="blue"&gt;VARCHAR&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="black"&gt;32&lt;/font&gt;&lt;font color="gray"&gt;), &lt;/font&gt;&lt;font color="#434343"&gt;@TeamID&lt;/font&gt;&lt;font color="gray"&gt;);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SET &lt;/font&gt;&lt;font color="#434343"&gt;@i &lt;/font&gt;&lt;font&gt;&lt;font color="black"&gt;+=&lt;/font&gt;&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="black"&gt;1&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;END&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FETCH NEXT&lt;/font&gt;&lt;font color="black"&gt; &lt;/font&gt;&lt;font color="blue"&gt;FROM &lt;/font&gt;&lt;font color="black"&gt;c &lt;/font&gt;&lt;font color="blue"&gt;INTO &lt;/font&gt;&lt;font color="#434343"&gt;@TeamID&lt;/font&gt;&lt;font color="gray"&gt;, &lt;/font&gt;&lt;font color="#434343"&gt;@TeamSize&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;END&lt;br&gt;&lt;br&gt;CLOSE &lt;/font&gt;&lt;font color="black"&gt;c&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;DEALLOCATE &lt;/font&gt;&lt;font color="black"&gt;c&lt;/font&gt;&lt;font color="gray"&gt;;&lt;/font&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/blockquote&gt;

&lt;p&gt;So a quick count showed we had 30 rows in the Team table, and about 1.3 million rows in the TeamMember tables (with individual teams ranging from one row to 140,000 rows). &lt;/p&gt;

&lt;p&gt;Now we could put our three queries to the test! I opened up my trusty copy of &lt;a href="http://sqlsentry.net/plan-explorer/sql-server-query-view.asp" title="http://sqlsentry.net/plan-explorer/sql-server-query-view.asp" target="_blank"&gt;SQL Sentry Plan Explorer&lt;/a&gt; and pasted the three queries into the Command Text pane. I clicked the "Actual Plan" button, which goes to the server, runs the query, retrieves the actual plan, and discards the results. First I ran it for the A table (clustered index on TeamID), and these were the results from the Statements Tree tab:&lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_comp.png" border="1" height="105" width="654"&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Similar results for the B table (the one with just a non-clustered index on the TeamID column):&lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_comp.png" border="1" height="103" width="642"&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;In both cases, Wil's solution came out at about twice the cost as the original query (and my proposed replacement). You can see where the doubling comes in from Wil's graphical plan (an extra scan), compared to the other two (the screen shots are presented in the same order as the 6 rows shown in the Statements Tree rows above - click on any to embiggen):&lt;br&gt;&lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&amp;nbsp;&lt;a href="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_orig.png" title="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_orig.png" target="_blank"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_orig.png" border="1" height="105" width="624"&gt;&lt;/a&gt;&lt;br&gt;Original - TeamMember_A&lt;br&gt;&lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&lt;a href="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_aaron.png" title="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_aaron.png" target="_blank"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_aaron.png" border="1" height="104" width="813"&gt;&lt;/a&gt; &lt;br&gt;Aaron - TeamMember_A&lt;br&gt;&lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&lt;a href="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_wil.png" title="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_wil.png" target="_blank"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_a_wil.png" border="1" height="154" width="502"&gt;&lt;/a&gt;&lt;br&gt;Wil - TeamMember_A&lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&lt;a href="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_orig.png" title="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_orig.png" target="_blank"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_orig.png" border="1" height="103" width="381"&gt;&lt;/a&gt;&lt;br&gt;Original - TeamMember_B &lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&lt;a href="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_aaron.png" title="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_aaron.png" target="_blank"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_aaron.png" border="1" height="106" width="610"&gt;&lt;/a&gt;&lt;br&gt;Aaron - TeamMember_B&lt;/p&gt;

&lt;p style="margin-left:40px;"&gt;&lt;a href="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_wil.png" title="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_wil.png" target="_blank"&gt;&lt;img src="http://bertrandaaron.files.wordpress.com/2011/09/so_1_b_wil.png" border="1" height="145" width="619"&gt;&lt;/a&gt;&lt;br&gt;Wil - TeamMember_B &lt;br&gt;&lt;/p&gt;

&lt;p&gt;I tried running the tests again with parallelism off, and while the 
plans looked a little different, the overall results were nearly 
identical (~50/25/25 split). &lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;Conclusion&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Generalizations are dangerous. Even if a situation looks similar to the one you've got, you owe it to yourself to test. Especially in a case where you've been asked to change your code to improve performance, and you've actually accepted a solution that performs worse.&lt;br&gt;&lt;/p&gt;



&lt;p&gt;&lt;span style="font-style:italic;"&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;</description></item></channel></rss>