<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>SQLServerPedia</title>
	
	<link>http://sqlserverpedia.com/blog</link>
	<description />
	<lastBuildDate>Fri, 19 Mar 2010 02:34:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/sqlserverpedia" /><feedburner:info uri="sqlserverpedia" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license><feedburner:emailServiceId>sqlserverpedia</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>I Stand Corrected</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/18lEaysiTGA/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/i-stand-corrected/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 02:34:31 +0000</pubDate>
		<dc:creator>Thomas LaRock</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">http://thomaslarock.com/?p=3890</guid>
		<description><![CDATA[The other day Aaron Bertrand pointed out that a recent tip I wrote had a rather nasty oversight. You can read more about the discussion over at his blog.
The short of it is this: what I wrote in the tip is cot very clear, and is most likely going to be interpreted wrongly. Aaron&#8217;s post [...]]]></description>
			<content:encoded><![CDATA[<p>The other day Aaron Bertrand <a href="http://www.mssqltips.com/tip.asp?tip=1964">pointed out that a recent tip</a> I wrote had a rather nasty oversight. You can read more about the <a href="http://sqlblog.com/blogs/aaron_bertrand/archive/2010/03/15/yes-you-can-benefit-from-both-data-and-backup-compression.aspx">discussion over at his blog</a>.</p>
<p>The short of it is this: what I wrote in the tip is cot very clear, and is most likely going to be interpreted wrongly. Aaron&#8217;s post does a great job of explaining the difference. I also want people to understand that if you are doing compressed backups, you won&#8217;t see much added benefit if you also enable data compression. As Aaron points out in his example, the overall benefit on time and size of the final backup file are comparable whether you are compressing data or not.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=18lEaysiTGA:Vmojcwl5QfI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=18lEaysiTGA:Vmojcwl5QfI:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=18lEaysiTGA:Vmojcwl5QfI:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/18lEaysiTGA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/i-stand-corrected/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/i-stand-corrected/</feedburner:origLink></item>
		<item>
		<title>Double MCITP</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/Y39QHAoJeKc/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/double-mcitp/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 17:00:15 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1420</guid>
		<description><![CDATA[Yesterday I took the afternoon off of work with the intention of spending the entire afternoon taking two Microsoft certification tests. I had no intention of passing the tests, but I went ahead and scheduled to take 70-432 and 70-450 back to back
I was pretty nervous about the exams. After 18 months on the job [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I took the afternoon off of work with the intention of spending the entire afternoon taking two Microsoft certification tests. I had no intention of passing the tests, but I went ahead and scheduled to take 70-432 and 70-450 back to back</p>
<p>I was pretty nervous about the exams. After 18 months on the job as a DBA you would think I could have passed them in my sleep. Of course, if I didn&#8217;t pass it, was I really that good at my job? Sure, servers weren&#8217;t going to suddenly start exploding if I failed one or both exams, but it would have been a huge blow to my confidence.</p>
<p>Thankfully, <a href='http://twitter.com/peschkaj/status/10631250838' >I passed.</a></p>
<p>This was a pretty big milestone as I&#8217;ve been a developer for 90% of my professional career. It&#8217;s only recently that I&#8217;ve switched around and gone with the support route. Even then I don&#8217;t consider myself a DBA. I solve problems. Right now SQL Server is how I accomplish that. This certification is just some icing on top of the last 18 months of experience. It might not prove that I know my shit, but it proves that I know a minimally acceptable amount of somebody&#8217;s shit.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?i=kTlXDgLchKs:7I-MpRwtRPk:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?i=kTlXDgLchKs:7I-MpRwtRPk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?i=kTlXDgLchKs:7I-MpRwtRPk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?i=kTlXDgLchKs:7I-MpRwtRPk:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:zYSYRoQSaQY"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?d=zYSYRoQSaQY" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9_syndication/~4/kTlXDgLchKs" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Y39QHAoJeKc:7I-MpRwtRPk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Y39QHAoJeKc:7I-MpRwtRPk:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Y39QHAoJeKc:7I-MpRwtRPk:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/Y39QHAoJeKc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/double-mcitp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/double-mcitp/</feedburner:origLink></item>
		<item>
		<title>Double MCITP</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/Y39QHAoJeKc/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/double-mcitp/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 17:00:15 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1420</guid>
		<description><![CDATA[Yesterday I took the afternoon off of work with the intention of spending the entire afternoon taking two Microsoft certification tests. I had no intention of passing the tests, but I went ahead and scheduled to take 70-432 and 70-450 back to back
I was pretty nervous about the exams. After 18 months on the job [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I took the afternoon off of work with the intention of spending the entire afternoon taking two Microsoft certification tests. I had no intention of passing the tests, but I went ahead and scheduled to take 70-432 and 70-450 back to back</p>
<p>I was pretty nervous about the exams. After 18 months on the job as a DBA you would think I could have passed them in my sleep. Of course, if I didn&#8217;t pass it, was I really that good at my job? Sure, servers weren&#8217;t going to suddenly start exploding if I failed one or both exams, but it would have been a huge blow to my confidence.</p>
<p>Thankfully, <a href='http://twitter.com/peschkaj/status/10631250838' >I passed.</a></p>
<p>This was a pretty big milestone as I&#8217;ve been a developer for 90% of my professional career. It&#8217;s only recently that I&#8217;ve switched around and gone with the support route. Even then I don&#8217;t consider myself a DBA. I solve problems. Right now SQL Server is how I accomplish that. This certification is just some icing on top of the last 18 months of experience. It might not prove that I know my shit, but it proves that I know a minimally acceptable amount of somebody&#8217;s shit.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?i=kTlXDgLchKs:7I-MpRwtRPk:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?i=kTlXDgLchKs:7I-MpRwtRPk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?i=kTlXDgLchKs:7I-MpRwtRPk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?i=kTlXDgLchKs:7I-MpRwtRPk:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9_syndication?a=kTlXDgLchKs:7I-MpRwtRPk:zYSYRoQSaQY"><img src="http://feeds.feedburner.com/~ff/facility9_syndication?d=zYSYRoQSaQY" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9_syndication/~4/kTlXDgLchKs" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Y39QHAoJeKc:7I-MpRwtRPk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Y39QHAoJeKc:7I-MpRwtRPk:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Y39QHAoJeKc:7I-MpRwtRPk:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/Y39QHAoJeKc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/double-mcitp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/double-mcitp/</feedburner:origLink></item>
		<item>
		<title>Presenting at SQL Saturday #39</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/iYKAnUZjtmI/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/presenting-at-sql-saturday-39/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 15:17:30 +0000</pubDate>
		<dc:creator>Thomas LaRock</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">http://thomaslarock.com/?p=3884</guid>
		<description><![CDATA[It&#8217;s official, I will be presenting at SQL Saturday #39 on April 24th in New York City. My talk will be on SQL Server 2008 Audit and I am gearing it for people that are not familiar with that feature of SQL 2008.
I&#8217;ve been to SQL Saturday&#8217;s before, I&#8217;ve been to Manhattan before, and I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s official, I will <a href="http://sqlsaturday.com/viewsession.aspx?sat=39&amp;sessionid=1455">be presenting</a> at<a href="http://sqlsaturday.com/39/eventhome.aspx"> SQL Saturday #39</a> on April 24th in <a href="http://www.bing.com/maps/explore/#5003/0.6002=q:1290+Avenue+of+the+Americas,+New+York,+NY+10104:lat:40.8677492110617:long:-74.154998779:nosp:0:adj:0&amp;o=&amp;a=0/5872/style=auto&amp;lat=40.760976&amp;lon=-73.979428&amp;z=16&amp;pid=5874">New York City</a>. My talk will be on SQL Server 2008 Audit and I am gearing it for people that are not familiar with that feature of SQL 2008.</p>
<p>I&#8217;ve been to SQL Saturday&#8217;s before, I&#8217;ve been to Manhattan before, and I&#8217;ve even been to the Microsoft office there a few times before as well. But never all three things at once, so this is a first for me. I am excited to be able to take part in this event. I see a lot of familiar names on the list of speakers and I am very interested in hearing them speak.</p>
<p>If you are in the area on April 24th, stop by for some free training.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=iYKAnUZjtmI:KPcVdPzFVQI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=iYKAnUZjtmI:KPcVdPzFVQI:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=iYKAnUZjtmI:KPcVdPzFVQI:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/iYKAnUZjtmI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/presenting-at-sql-saturday-39/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/presenting-at-sql-saturday-39/</feedburner:origLink></item>
		<item>
		<title>Undocumented Virtual Column: %%lockres%</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/F3JakBCtA6E/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-2005/undocumented-virtual-column-lockres/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 13:43:09 +0000</pubDate>
		<dc:creator>Grant Fritchey</dc:creator>
				<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">http://scarydba.wordpress.com/?p=1153</guid>
		<description><![CDATA[One of my development teams needed a mechanism for identifying the value of a key that was part of a lock (don&#8217;t ask). I&#8217;d never tried doing that before. Obviously if you hit the DMV sys.dm_os_tran_locks you can see the hash of the key in the resource_description column. But how to pull the value back. After some [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=scarydba.wordpress.com&#38;blog=3082101&#38;post=1153&#38;subd=scarydba&#38;ref=&#38;feed=1" />]]></description>
			<content:encoded><![CDATA[<p>One of my development teams needed a mechanism for identifying the value of a key that was part of a lock (don&#8217;t ask). I&#8217;d never tried doing that before. Obviously if you hit the DMV sys.dm_os_tran_locks you can see the hash of the key in the resource_description column. But how to pull the value back. After some research, I first found this <a href="http://www.informit.com/articles/article.aspx?p=686168&amp;seqNum=5">excellent article</a> by the late, great, Ken Henderson (I really wish he was still around). The article outlined, among other things, the use of an undocumented &#8220;virtual&#8221; column called %%lockres%%. Some more searching then uncovered <a href="http://consultingblogs.emc.com/jamesrowlandjones/archive/2009/05/28/the-curious-case-of-the-dubious-deadlock-and-the-not-so-logical-lock.aspx">this great article</a> by James Rowland-Jones, AKA Claypole. He described how, in a very high volume system, he used %%lockres%% to identify the source of a deadlock as the internal mechanisms that SQL Server uses to manage locks, the hash of the key. Oh, and he opened an <a href="https://connect.microsoft.com/SQLServer/feedback/details/458076/make-lockres-a-documented-feature">incident on Connect</a>, which seems to be closed, but vote on it anyway, I did. %%lockres%% is also covered in Kalen Delaney&#8217;s excellent book on <a href="http://www.amazon.com/Microsoft-SQL-Server-2008-Internals/dp/0735626243/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1268911790&amp;sr=8-1">SQL Server 2008 Internals</a> and even warrants a bit of discussion in <a href="http://www.amazon.com/Professional-Server-2008-Internals-Troubleshooting/dp/0470484284/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1268912390&amp;sr=1-1">Professional SQL Server 2008</a>, but that was written by James Rowland-Jones, so I&#8217;m not sure it counts.</p>
<p>In the meantime, while I was investigating this stuff, evidently the development team was looking into it on their own. They came to the same set of resources and decided to use the virtual column as part of their real-time, transactional application. Yeah, an undocumented &#8220;virtual&#8221; column going into a major application. Since I would probably be unable to do anything about this, I decided to at least look into how this thing behaves so I can be aware of what types of problems I might run into.</p>
<p>First, a simple query:</p>
<p>SELECTa.City<br />
&#8211;,%%lockres%%<br />
FROM Person.Address AS a<br />
WHERE a.AddressID = 432</p>
<p>If you run this query and take a look at the execution plan you&#8217;ll see a nice clean clustered index seek, just as you would suspect. If you take away the comment and run it again, the execution plan is identical. On the version of AdventureWorks2008 currently installed on my machine, I get two page reads, regardless of whether or not I include %%lockres%% or not. With the comments removed, it returns the hash of the primary key: (b0004e040bc2). This looks pretty painless, free even.</p>
<p>If we want to see %%lockres%% in action, it&#8217;s not too difficult:</p>
<p>BEGIN TRAN<br />
UPDATE Person.Address<br />
SET City = &#8216;dude&#8217;<br />
WHERE AddressID = 432;<br />
&#8211;ROLLBACK TRAN</p>
<p>Obviously this will put a key lock on that row in the table. If I just select against sys.dm_os_tran_locks, the data returned looks like this:</p>
<p>resource_type   resource_description   resource_associated_entity_id   request_mode<br />
KEY                       (b0004e040bc2)            72057594043564032                      X </p>
<p>The original request from the development team was for a way to get the key value back when you know that a table is locked, such as the case here. I wrote this simple query to make that happen:</p>
<p><span style="color:#0000ff;font-size:x-small;"><span style="color:#0000ff;font-size:x-small;"><span style="color:#0000ff;font-size:x-small;"><span style="color:#0000ff;font-size:x-small;">SELECT </span></span></span></span>a.AddressID<br />
FROM person.address(NOLOCK) AS a<br />
JOIN sys.dm_tran_locks AS dtl<br />
ON a.%%lockres%% = dtl.resource_description<br />
WHERE dtl.resource_type = &#8216;KEY&#8217;</p>
<p>This query works and returns our key value of 432 just as you would want. But, take a look at the execution plan:</p>
<p><a href="http://scarydba.files.wordpress.com/2010/03/addresslock.png"><img class="alignnone size-full wp-image-1158" title="AddressLock" src="http://scarydba.files.wordpress.com/2010/03/addresslock.png?w=495&#038;h=127" alt="" width="495" height="127" /></a></p>
<p>Yes, that&#8217;s a clustered index (or table, same thing) scan followed by a Sort followed by a merge join, processing 19614 rows to return one. But hey, it was only 341 reads. To say the least, I&#8217;m not excited about seeing this in a production system. This was explicitly cautioned in Kalen Delaney&#8217;s book. While it appears that the remote scan operator, which is how the DMV is accessed in this case, is 59% of the operation, that&#8217;s the estimated cost and has been pointed out before, isn&#8217;t the best measure of real cost in the system.</p>
<p>The development team went off and developed their own query, they had said they were looking for the key value, but evidently they were looking for who was holding the lock on a particular key value:</p>
<p>SELECT s.nt_user_name<br />
FROM sys.dm_tran_locks l<br />
INNER JOIN sys.dm_exec_sessions s<br />
on l.request_session_id = s.session_id<br />
inner join sys.partitions p on l.resource_associated_entity_id = p.hobt_id<br />
where OBJECT_NAME(p.object_id) = &#8216;Address&#8217; and<br />
l.resource_description in (select %%lockres%%<br />
from person.Address(NOLOCK) a WHERE a.AddressID = 432)</p>
<p>I actually had to adjust their query just a bit to get it to work correctly, but basically they had the right idea. Here&#8217;s the final execution plan:</p>
<p><a href="http://scarydba.files.wordpress.com/2010/03/badquery.png"></a></p>
<p><a href="http://scarydba.files.wordpress.com/2010/03/badquery1.png"><img class="alignnone size-full wp-image-1171" title="BadQuery" src="http://scarydba.files.wordpress.com/2010/03/badquery1.png?w=495&#038;h=188" alt="" width="495" height="188" /></a></p>
<p>This was still not terribly inspiring a thing to think about running in a production system although it only had one scan and seven reads. Whether or not putting this in a transactional system is a good idea, it certainly adds yet another tool, albeit an undocumented one, to the tool belt.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/scarydba.wordpress.com/1153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/scarydba.wordpress.com/1153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/scarydba.wordpress.com/1153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/scarydba.wordpress.com/1153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/scarydba.wordpress.com/1153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/scarydba.wordpress.com/1153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/scarydba.wordpress.com/1153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/scarydba.wordpress.com/1153/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/scarydba.wordpress.com/1153/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/scarydba.wordpress.com/1153/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=scarydba.wordpress.com&blog=3082101&post=1153&subd=scarydba&ref=&feed=1" /><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=F3JakBCtA6E:Uc44bZ3vbHk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=F3JakBCtA6E:Uc44bZ3vbHk:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=F3JakBCtA6E:Uc44bZ3vbHk:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/F3JakBCtA6E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-2005/undocumented-virtual-column-lockres/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-2005/undocumented-virtual-column-lockres/</feedburner:origLink></item>
		<item>
		<title>Adventures in SQL: SP_MSFOREACHTABLE to find the largest table</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/-z9UyEdi7m4/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/adventures-in-sql-sp_msforeachtable-to-find-the-largest-table/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 13:27:00 +0000</pubDate>
		<dc:creator>Jen Stirrup</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">tag:blogger.com,1999:blog-414079309540634094.post-1258455212234509297</guid>
		<description><![CDATA[When exploring a SQL Server database for the first time, it’s always useful to identify the most populated tables first because they are very likely to be the most important tables. To do this in a situation where there are tight time-scales, it’s ...]]></description>
			<content:encoded><![CDATA[<div align="justify">When exploring a SQL Server database for the first time, it’s always useful to identify the most populated tables first because they are very likely to be the most important tables. To do this in a situation where there are tight time-scales, it’s possible to use some undocumented SQL Server procedures to quickly produce a list of the tables which have the most rows. </div><div align="justify"><br /></div><div align="justify">Before proceeding, however, it’s wise to note that undocumented stored procedures are <strong>not guaranteed</strong> by Microsoft. Further, they are not ‘fixed’ so they could change without warning, so use this command at your own discretion, and treat the results with care! </div><div align="justify"><br /></div><div align="justify">One example of an undocumented SQL Server procedure which has been useful is <strong>SP_FOREACHTABLE</strong>.&nbsp; Although it’s not guaranteed, it might be useful for some to try it out as a starting point when exploring data, when it’s useful to find out the most populated tables in your new unexplored database. </div><div align="justify"><br /></div><div align="justify">In this example, a new table called TableRowCount will be created. This table will hold the results of the execution of SP_FOREACHTABLE.&nbsp; To assist you, the SQL to do this is given below:</div><div align="justify"><br /></div><span style="color: teal;"><span style="color: grey;">/****** Check if table TableRowCount exists already, and if so, delete it&nbsp;&nbsp;&nbsp; ******/</span> </span><span style="color: blue;">IF </span>EXISTS (<span style="color: blue;">SELECT</span> * <span style="color: blue;">FROM</span> <span style="color: teal;">sys.objects</span> <span style="color: blue;">WHERE</span> <span style="color: magenta;">object_id = OBJECT_ID</span>(<span style="color: red;">N'[dbo].[TableRowCount]'</span>) AND <span style="color: blue;">type</span> in (<span style="color: red;">N'U'</span>)) <br /><span style="color: blue;">DROP TABLE</span> [dbo].[TableRowCount] <br /><span style="color: blue;">GO</span> <br /><span style="color: grey;">/****** Create table TableRowCount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ******/</span> <br /><span style="color: blue;">CREATE TABLE</span> [TableRowCount]( <br />&nbsp; TableName <span style="color: blue;">sysname</span>, <br />&nbsp; [TableRowCount]<span style="color: blue;"> int </span>)<br /><br />Once the table is created, the SP_FOREACHTABLE procedure is executed as follows:<br /><br /><span style="color: teal;"><span style="color: grey;">/****** Execute stored procedure, and save results in table TableRowCount ******/</span> </span><br /><span style="color: blue;">EXEC</span> <span style="color: #804000;">sp_MSForEachTable</span> <span style="color: red;">'INSERT [TableRowCount](TableName, [TableRowCount]) SELECT ''?'', COUNT(*) FROM ?'</span><br /><br />Then, it’s possible to retrieve the results of this command from the TableRowCount table, as follows:<br /><br /><span style="color: #999999;">/****** Display the results from table TableRowCount, in descending order ******/</span><br /><br /><br />select * from TableRowCount<br />order by TableRowCount.TableRowCount desc<br /><br />The above statement will sort the data so that the table with the highest number of rows will appear at the top. It's a guess that the most populated table is an important one, but it's not a bad guess all the same!<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/414079309540634094-1258455212234509297?l=www.jenstirrup.com' alt='' /></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?a=PsJUbCcIZT4:r2AdbVcCvs4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?a=PsJUbCcIZT4:r2AdbVcCvs4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?i=PsJUbCcIZT4:r2AdbVcCvs4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?a=PsJUbCcIZT4:r2AdbVcCvs4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?a=PsJUbCcIZT4:r2AdbVcCvs4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?i=PsJUbCcIZT4:r2AdbVcCvs4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?a=PsJUbCcIZT4:r2AdbVcCvs4:4cEx4HpKnUU"><img src="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?i=PsJUbCcIZT4:r2AdbVcCvs4:4cEx4HpKnUU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?a=PsJUbCcIZT4:r2AdbVcCvs4:63t7Ie-LG7Y"><img src="http://feeds.feedburner.com/~ff/jenstirrup/FZfr?d=63t7Ie-LG7Y" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/jenstirrup/FZfr/~4/PsJUbCcIZT4" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=-z9UyEdi7m4:r2AdbVcCvs4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=-z9UyEdi7m4:r2AdbVcCvs4:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=-z9UyEdi7m4:r2AdbVcCvs4:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/-z9UyEdi7m4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/adventures-in-sql-sp_msforeachtable-to-find-the-largest-table/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/adventures-in-sql-sp_msforeachtable-to-find-the-largest-table/</feedburner:origLink></item>
		<item>
		<title>A Clustered Index Does Not Guarantee Order</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/1y5M6vZfWFY/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/a-clustered-index-does-not-guarantee-order/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 12:41:00 +0000</pubDate>
		<dc:creator>Larry Leonard</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">tag:blogger.com,1999:blog-4149930.post-2347578404447516471</guid>
		<description><![CDATA[Learned something the hard way recently: just because a table has a clustered index doesn't mean a SELECT without an ORDER BY will return the rows in order. For example, given this table:


CREATE TABLE MyTable
(
    ID  INT IDENTITY (1, 1)  NOT NULL
 ...]]></description>
			<content:encoded><![CDATA[<p>Learned something the hard way recently: just because a table has a clustered index doesn't mean a SELECT without an ORDER BY will return the rows in order. For example, given this table:</p>

<pre class="brush:tsql">
CREATE TABLE MyTable
(
    ID  INT IDENTITY (1, 1)  NOT NULL
        CONSTRAINT PK_tblMyTable PRIMARY KEY CLUSTERED (ID)
)
</pre>

<p>... if you say:</p>

<pre class="brush:tsql">
SELECT * FROM MyTable
</pre>

<p>... then the rows will be returned in <u>undefined</u> (that is, random) order.</p>

<p>"Clustering", I've learned, is a <em>physical</em> construct, not a <em>logical</em> one. The rows are laid out <em>in physical order</em> on the hard drive, but SQL Server is free (in the abscence of an ORDER BY clause) to return them in whatever order it thinks most efficient.</p>

<p>As developers, we don't usually see this behavior, because we tend to have fresh, well-maintained tables. In fact, I only discovered it in a customer's database that hadn't had any maintenance done to it in years. So, the bottom line is, as always, "no ORDER BY, no ordering."</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4149930-2347578404447516471?l=sqlsoundings.blogspot.com' alt='' /></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SqlSoundingsForSS?a=Tf3X75EtHGE:-Y3ZAOEQE-g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SqlSoundingsForSS?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SqlSoundingsForSS?a=Tf3X75EtHGE:-Y3ZAOEQE-g:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/SqlSoundingsForSS?i=Tf3X75EtHGE:-Y3ZAOEQE-g:3QFJfmc7Om4" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SqlSoundingsForSS?a=Tf3X75EtHGE:-Y3ZAOEQE-g:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/SqlSoundingsForSS?d=YwkR-u9nhCs" border="0"></img></a>
</div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=1y5M6vZfWFY:-Y3ZAOEQE-g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=1y5M6vZfWFY:-Y3ZAOEQE-g:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=1y5M6vZfWFY:-Y3ZAOEQE-g:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/1y5M6vZfWFY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/a-clustered-index-does-not-guarantee-order/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/a-clustered-index-does-not-guarantee-order/</feedburner:origLink></item>
		<item>
		<title>Hyper-V v2 has come a long way, but so has VMware</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/GEij7QEiteE/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/hyper-v-v2-has-come-a-long-way-but-so-has-vmware/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 11:00:48 +0000</pubDate>
		<dc:creator>Denny Cherry</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/sql-server/?p=810</guid>
		<description><![CDATA[
The timing on this post might seam a little strange, but I&#8217;ve been meaning to write this for a while and I finely got a chance to do it.
Back when Hyper-V 1.0 was released it wasn&#8217;t all that great of a product.  It showed some promise, but it really wasn&#8217;t there.  I had all sorts [...]]]></description>
			<content:encoded><![CDATA[
<p>The timing on this post might seam a little strange, but I&#8217;ve been meaning to write this for a while and I finely got a chance to do it.</p>
<p>Back when Hyper-V 1.0 was released it wasn&#8217;t all that great of a product.  It showed some promise, but it really wasn&#8217;t there.  I had all sorts of people (mostly from Microsoft) telling me that it was way better than ESX and that I needed to give it a shot.  My personal feelings are that it wasn&#8217;t anywhere near where ESX was, and for my production environment I needed the better product, so we went with ESX 3.5.</p>
<p>Well a while back Microsoft released Hyper-V 2.0 and it is a much better release than it was at the time.  I&#8217;d even be willing to stack it up next to VMware&#8217;s ESX 3.5 which was VMware&#8217;s competing version at the time of release.  Put next to ESX 3.5 you would have two well matched products.  Both included a real time online migration solution vMotion for ESX and life migration for Hyper-V.  Both support being put into a high availability cluster.  Both support pass through disks so that the guest OS has direct access to the fibre channel storage.</p>
<p>However shortly after Hyper-V 2.0 was release VMware released vSphere 4.0 which is the successor to ESX 3.5 and with vSphere 4.0 they&#8217;ve blown the doors off of Hyper-V yet again.</p>
<p>vSphere gives us FT or Fault Tolerance which basically runs a single VM on two machines with only one of the machines being active at a time.  In the event that one host fails the other host being running the VM actively with no outage to the guest.  Users connected to the guest won&#8217;t even know that the guest has switched to another machine.</p>
<p>VMware has also introduced some interesting features as experimental which means that we will probably see them show up as full on features in a future release.  This includes the ability to map an HBA directly to a virtual machine to give the VM actual direct access to the HBA.  At the moment that HBA can only be mapped to a single VM, but hopefully in the next release they will fix that.</p>
<p>Now don&#8217;t get we wrong, I think that Hyper-V has come a long way since the v1 release.  Do I think that Hyper-V is an Enterprise Ready solution?  Yes I do.  Do I think Hyper-V is ready to be called the winner in the virtualization server space?  No, not at all.  I think it is anyone&#8217;s game still before we have a clear winner.  Hyper-V has a big selling point to it, the cost to get into Hyper-V is free, as long as you don&#8217;t want to cluster it.  Then you&#8217;ll need to purchase a management tools license for each host machine.  How with VMware you&#8217;ll want the management tool weather you cluster the machines or not, but its a single purchase from VMware at least.</p>
<p>What it really comes down to is that you need to fully evaluate both platforms and due a solid CBA (Cost Benefit Analysis) as well as a full feature analysis before picking a platform for your enterprise.  Because once you pick one platform moving from one to the other is very tough to do.</p>
<p>Denny</p>

<img src="http://feeds.feedburner.com/~r/techtarget/wIpw/~4/TNeKUqn_w0I" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=GEij7QEiteE:CsSmwVawUTs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=GEij7QEiteE:CsSmwVawUTs:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=GEij7QEiteE:CsSmwVawUTs:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/GEij7QEiteE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/hyper-v-v2-has-come-a-long-way-but-so-has-vmware/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/hyper-v-v2-has-come-a-long-way-but-so-has-vmware/</feedburner:origLink></item>
		<item>
		<title>Dirty Tricks – Comparing rowcount</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/aT9vdOEOPIc/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/dirty-tricks-comparing-rowcount/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 07:49:00 +0000</pubDate>
		<dc:creator>Jen McCown</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">http://midnightdba.itbookworm.com/midnightdba/blog/post.aspx?id=19e26ca6-138c-4d9b-a6cf-ac3ecfae2595</guid>
		<description><![CDATA[<p>
<em>Content Rating: Beginner</em> 
</p>
<p>
I don&#39;t have many cool tools at my current gig to help me out, so I&#39;m often forced to come up with quick and dirty solutions of my own. Today I have to compare row counts in two identical databases, one in Dev and one in QA. Here&#39;s what I did. 
</p>
<p>
1. Generate a list of select count(*) statements 
</p>
<font size="2" color="#008000"><font size="2" color="#008000">
<address>
-- Get the SELECT statements for rowcounts for all user tables</address></font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">
<address>
select<font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;select &#39;&#39;&#39;</font></font><font size="2"> </font><font size="2" color="#808080"><font size="2" color="#808080">+</font></font><font size="2"> name </font><font size="2" color="#808080"><font size="2" color="#808080">+</font></font><font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;&#39;&#39; nm, count(*) cnt from &#39;</font></font><font size="2"> </font><font size="2" color="#808080"><font size="2" color="#808080">+</font></font><font size="2"> [name] </font><font size="2" color="#808080"><font size="2" color="#808080">+</font></font><font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39; UNION &#39;</font></font><font size="2"> </font></address></font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">
<address>
from<font size="2"> </font><font size="2" color="#008000"><font size="2" color="#008000">sys</font></font><font size="2" color="#808080"><font size="2" color="#808080">.</font></font><font size="2" color="#008000"><font size="2" color="#008000">objects</font></font><font size="2"> </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">where</font></font><font size="2"> type_desc </font><font size="2" color="#808080"><font size="2" color="#808080">=</font></font><font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;USER_TABLE&#39;</font></font><font size="2"> </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">order</font></font><font size="2"> </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">by</font></font><font size="2"> [name] 
<p>
This generates a list of statements like this: 
</p>
</font></address></font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">select</font></font><font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;Client&#39;</font></font><font size="2"> nm</font><font size="2" color="#808080"><font size="2" color="#808080">,</font></font><font size="2"> </font><font size="2" color="#ff00ff"><font size="2" color="#ff00ff">count</font></font><font size="2" color="#808080"><font size="2" color="#808080">(*)</font></font><font size="2"> cnt </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">from</font></font><font size="2"> Client </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">UNION</font></font><font size="2"> </font><font size="2">
<p>
2. Copy-paste that list into a query window and run. (Note that we remove the last Union statement).<font size="2" color="#0000ff"><font size="2" color="#0000ff"> 
<address>
select<font size="2" color="#000000"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;Client&#39;</font></font><font size="2" color="#000000"> nm</font><font size="2" color="#808080"><font size="2" color="#808080">,</font></font><font size="2" color="#000000"> </font><font size="2" color="#ff00ff"><font size="2" color="#ff00ff">count</font></font><font size="2" color="#808080"><font size="2" color="#808080">(*)</font></font><font size="2" color="#000000"> cnt </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">from</font></font><font size="2" color="#000000"> Client </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">UNION</font></font><font size="2"><font color="#000000"> </font></font></address></font></font>
</p>
</font>
<address>
select<font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;Supplier&#39;</font></font><font size="2"> nm</font><font size="2" color="#808080"><font size="2" color="#808080">,</font></font><font size="2"> </font><font size="2" color="#ff00ff"><font size="2" color="#ff00ff">count</font></font><font size="2" color="#808080"><font size="2" color="#808080">(*)</font></font><font size="2"> cnt </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">from</font></font><font size="2"> Client </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">UNION</font></font><font size="2">&#160;</font><font size="2" color="#0000ff">&#160;</font></address>
<address>
select<font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;Anchor&#39;</font></font><font size="2"> nm</font><font size="2" color="#808080"><font size="2" color="#808080">,</font></font><font size="2"> </font><font size="2" color="#ff00ff"><font size="2" color="#ff00ff">count</font></font><font size="2" color="#808080"><font size="2" color="#808080">(*)</font></font><font size="2"> cnt </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">from</font></font><font size="2"> Client </font><font size="2">
<p>
This gets us a resultset like this: 
</p>
</font></address>
<address>
<strong>nm&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cnt&#160;</strong></address>
<address>
Client&#160;&#160;&#160;&#160;&#160;&#160; 12333&#160;</address>
<address>
Supplier&#160;&#160; &#160;401</address>
<address>
Anchor&#160;&#160;&#160; &#160;32</address>
<p>
3. Do the same on the other environment. 
</p>
<p>
&#160;Now at this point, you have your data. If there are few enough tables, you can compare by hand. Or you could run each set of SELECT statements with Save As File, import those file to your sandbox DB as two tables, and compare rowcounts that way. 
</p>
<p>
Edit: That&#39;s the old school way of getting rowcounts from pre-DMV days. So <strong>if you&#39;re using SQL Server 2000 or earlier, or need exact rowcounts</strong>, use the above.&#160; If you&#39;d like something faster and easier, check out Aaron Bertrand&#39;s (<a href="http://sqlblog.com/blogs/aaron_bertrand/">blog</a> &#124; <a href="http://sqlblog.com/blogs/aaron_bertrand/">twitter</a>) solutions in the comments below!
</p>
<p>
Another day, another dirty little trick from the MidnightDBA.&#160; Show us your dirty tricks, or a better way to compare - either blog or post in comments! 
</p>
<p>
-Jen McCown<br />
<a href="http://www.midnightdba.com/">http://www.MidnightDBA.com</a> 
</p>
]]></description>
			<content:encoded><![CDATA[<p>
<em>Content Rating: Beginner</em> 
</p>
<p>
I don&#39;t have many cool tools at my current gig to help me out, so I&#39;m often forced to come up with quick and dirty solutions of my own. Today I have to compare row counts in two identical databases, one in Dev and one in QA. Here&#39;s what I did. 
</p>
<p>
1. Generate a list of select count(*) statements 
</p>
<font size="2" color="#008000"><font size="2" color="#008000">
<address>
-- Get the SELECT statements for rowcounts for all user tables</address></font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">
<address>
select<font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;select &#39;&#39;&#39;</font></font><font size="2"> </font><font size="2" color="#808080"><font size="2" color="#808080">+</font></font><font size="2"> name </font><font size="2" color="#808080"><font size="2" color="#808080">+</font></font><font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;&#39;&#39; nm, count(*) cnt from &#39;</font></font><font size="2"> </font><font size="2" color="#808080"><font size="2" color="#808080">+</font></font><font size="2"> [name] </font><font size="2" color="#808080"><font size="2" color="#808080">+</font></font><font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39; UNION &#39;</font></font><font size="2"> </font></address></font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">
<address>
from<font size="2"> </font><font size="2" color="#008000"><font size="2" color="#008000">sys</font></font><font size="2" color="#808080"><font size="2" color="#808080">.</font></font><font size="2" color="#008000"><font size="2" color="#008000">objects</font></font><font size="2"> </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">where</font></font><font size="2"> type_desc </font><font size="2" color="#808080"><font size="2" color="#808080">=</font></font><font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;USER_TABLE&#39;</font></font><font size="2"> </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">order</font></font><font size="2"> </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">by</font></font><font size="2"> [name] 
<p>
This generates a list of statements like this: 
</p>
</font></address></font></font><font size="2" color="#0000ff"><font size="2" color="#0000ff">select</font></font><font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;Client&#39;</font></font><font size="2"> nm</font><font size="2" color="#808080"><font size="2" color="#808080">,</font></font><font size="2"> </font><font size="2" color="#ff00ff"><font size="2" color="#ff00ff">count</font></font><font size="2" color="#808080"><font size="2" color="#808080">(*)</font></font><font size="2"> cnt </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">from</font></font><font size="2"> Client </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">UNION</font></font><font size="2"> </font><font size="2">
<p>
2. Copy-paste that list into a query window and run. (Note that we remove the last Union statement).<font size="2" color="#0000ff"><font size="2" color="#0000ff"> 
<address>
select<font size="2" color="#000000"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;Client&#39;</font></font><font size="2" color="#000000"> nm</font><font size="2" color="#808080"><font size="2" color="#808080">,</font></font><font size="2" color="#000000"> </font><font size="2" color="#ff00ff"><font size="2" color="#ff00ff">count</font></font><font size="2" color="#808080"><font size="2" color="#808080">(*)</font></font><font size="2" color="#000000"> cnt </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">from</font></font><font size="2" color="#000000"> Client </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">UNION</font></font><font size="2"><font color="#000000"> </font></font></address></font></font>
</p>
</font>
<address>
select<font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;Supplier&#39;</font></font><font size="2"> nm</font><font size="2" color="#808080"><font size="2" color="#808080">,</font></font><font size="2"> </font><font size="2" color="#ff00ff"><font size="2" color="#ff00ff">count</font></font><font size="2" color="#808080"><font size="2" color="#808080">(*)</font></font><font size="2"> cnt </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">from</font></font><font size="2"> Client </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">UNION</font></font><font size="2">&nbsp;</font><font size="2" color="#0000ff">&nbsp;</font></address>
<address>
select<font size="2"> </font><font size="2" color="#ff0000"><font size="2" color="#ff0000">&#39;Anchor&#39;</font></font><font size="2"> nm</font><font size="2" color="#808080"><font size="2" color="#808080">,</font></font><font size="2"> </font><font size="2" color="#ff00ff"><font size="2" color="#ff00ff">count</font></font><font size="2" color="#808080"><font size="2" color="#808080">(*)</font></font><font size="2"> cnt </font><font size="2" color="#0000ff"><font size="2" color="#0000ff">from</font></font><font size="2"> Client </font><font size="2">
<p>
This gets us a resultset like this: 
</p>
</font></address>
<address>
<strong>nm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cnt&nbsp;</strong></address>
<address>
Client&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12333&nbsp;</address>
<address>
Supplier&nbsp;&nbsp; &nbsp;401</address>
<address>
Anchor&nbsp;&nbsp;&nbsp; &nbsp;32</address>
<p>
3. Do the same on the other environment. 
</p>
<p>
&nbsp;Now at this point, you have your data. If there are few enough tables, you can compare by hand. Or you could run each set of SELECT statements with Save As File, import those file to your sandbox DB as two tables, and compare rowcounts that way. 
</p>
<p>
Edit: That&#39;s the old school way of getting rowcounts from pre-DMV days. So <strong>if you&#39;re using SQL Server 2000 or earlier, or need exact rowcounts</strong>, use the above.&nbsp; If you&#39;d like something faster and easier, check out Aaron Bertrand&#39;s (<a href="http://sqlblog.com/blogs/aaron_bertrand/">blog</a> | <a href="http://sqlblog.com/blogs/aaron_bertrand/">twitter</a>) solutions in the comments below!
</p>
<p>
Another day, another dirty little trick from the MidnightDBA.&nbsp; Show us your dirty tricks, or a better way to compare - either blog or post in comments! 
</p>
<p>
-Jen McCown<br />
<a href="http://www.midnightdba.com/">http://www.MidnightDBA.com</a> 
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=aT9vdOEOPIc:UF8DAgF24hk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=aT9vdOEOPIc:UF8DAgF24hk:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=aT9vdOEOPIc:UF8DAgF24hk:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/aT9vdOEOPIc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/dirty-tricks-comparing-rowcount/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/dirty-tricks-comparing-rowcount/</feedburner:origLink></item>
		<item>
		<title>Performance Tuning 101 – What You Will Not Learn In The Class Room (Part 2)</title>
		<link>http://feedproxy.google.com/~r/sqlserverpedia/~3/Rqc5iJXzSCI/</link>
		<comments>http://sqlserverpedia.com/blog/sql-server-bloggers/performance-tuning-101-%e2%80%93-what-you-will-not-learn-in-the-class-room-part-2/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 04:12:00 +0000</pubDate>
		<dc:creator>Adam Haines</dc:creator>
				<category><![CDATA[SQL Server Bloggers]]></category>

		<guid isPermaLink="false">tag:blogger.com,1999:blog-4646137438366687895.post-6643583342773077191</guid>
		<description><![CDATA[digg_url = "http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will_17.html";digg_title = "Performance Tuning 101 – What You Will Not Learn In The Class Room (Part 2)";digg_bgcolor = "#FFFFFF";digg_skin = "normal";digg_url = undefin...]]></description>
			<content:encoded><![CDATA[<div class="wlWriterHeaderFooter" style="float:right; margin:0px; padding:0px 0px 4px 8px;"><script type="text/javascript">digg_url = "http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will_17.html";digg_title = "Performance Tuning 101 – What You Will Not Learn In The Class Room (Part 2)";digg_bgcolor = "#FFFFFF";digg_skin = "normal";</script><script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script><script type="text/javascript">digg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;</script></div><p>In my last post, <a title="http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html" href="http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html">http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html</a> I talked about performance tuning queries that appear to be well tuned.&#160; There are a lot of optimization techniques available unbeknownst to most developers that do not require indexes or radical code changes.&#160; These are the optimizations that I will be talking about in this post.&#160; There is absolutely no way I could go over every possible optimization technique available, but I will do my best to present as much content here today, and will make future posts on other techniques.</p>  <p>I will start things off&#160; by talking about a challenge that Ramesh Meyyappan presented in his webcast, <a href="http://www.sqlworkshops.com/">http://www.sqlworkshops.com/</a>.&#160; Ramesh’s challenge was to solve the TOP 101 phenomenon, using SQL Server 2005.&#160; To start things off, I will create a sample table, with data.</p>  <pre class="brush:csharp">USE [tempdb]
GO

SET NOCOUNT ON;
GO

IF EXISTS(SELECT 1 FROM sys.tables WHERE NAME = 'TestData')
BEGIN
    DROP TABLE dbo.[TestData];
END
GO

CREATE TABLE dbo.TestData(
RowNum INT PRIMARY KEY,
SomeId INT,
SomeCode CHAR(2000)
);
GO

;WITH 
   L0 AS (SELECT 1 AS C UNION ALL SELECT 1)       --2 rows
  ,L1 AS (SELECT 1 AS C FROM L0 AS A, L0 AS B)    --4 rows (2x2)
  ,L2 AS (SELECT 1 AS C FROM L1 AS A, L1 AS B)    --16 rows (4x4)
  ,L3 AS (SELECT 1 AS C FROM L2 AS A, L2 AS B)    --256 rows (16x16)
  ,L4 AS (SELECT 1 AS C FROM L3 AS A, L3 AS B)    --65536 rows (256x256)
  ,L5 AS (SELECT 1 AS C FROM L4 AS A, L4 AS B)    --4,294,967,296 rows (65536x65536)
  ,Number AS (SELECT row_number() OVER (ORDER BY (SELECT 0)) AS N FROM L5) 
INSERT INTO dbo.TestData
SELECT
    N AS RowNumber,
    ABS(CHECKSUM(NEWID()))%1000000+1 AS SomeId ,
    REPLICATE('a',2000) AS SomeCode
FROM Number
WHERE [N] &lt;= 50000
GO

UPDATE STATISTICS dbo.[TestData] WITH FULLSCAN;
GO</pre>


<p>Next, I will create a query that uses TOP and an order by to return 100 rows.&#160; </p>

<pre class="brush:csharp">--Fast
SELECT TOP 100 [RowNum],[SomeId],[SomeCode]
FROM dbo.[TestData]
WHERE [RowNum] &lt; 30000
ORDER BY [SomeId]
OPTION (MAXDOP 1)
/*
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 1 ms.

 SQL Server Execution Times:
   CPU time = 78 ms,  elapsed time = 102 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
*/</pre>


<p>Now watch what happens when I change the TOP operator to 101.&#160; You will notice that I did not change anything else in the query other than increasing the number of rows returned by 1.</p>

<pre class="brush:csharp">--Slow
SELECT TOP 101 [RowNum],[SomeId],[SomeCode]
FROM dbo.[TestData]
WHERE [RowNum] &lt; 30000
ORDER BY [SomeId]
OPTION(MAXDOP 1)

/*
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 312 ms,  elapsed time = 1690 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
*/</pre>


<p>Wow…. TOP 101 is over 17 times slower than TOP 100 and all I changed is the number of rows in the TOP operator!!!!!&#160; So why does the optimizer take so much longer to optimize and execute a query using TOP 101, oppose to TOP 100?&#160; The short answer is the memory requirements.&#160; The TOP 101 queries requires a lot more query memory than TOP 101, which translates into tempdb sorting.&#160; As you may recall, I addressed some techniques to solve the tempdb sorting problem in my last post, <a title="http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html" href="http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html">http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html</a>.&#160; If you are using SQL 2008, you can use the same optimization techniques presented in my prior post, but SQL 2005 is a completely different animal.&#160; To make the TOP 101 query faster, we need to first understand why it is slower.&#160; Let’s take a look at what is different when we run the TOP 100 and the TOP 101 query.</p>

<p>Lets start by looking at the memory SQL Server grants to each query.&#160; Open two different query windows and execute each top query within a while loop.&#160; We can then use sys.dm_os_memory_grants to get the required memory. </p>

<p>Here is a sample of how to run the TOP query in a while loop.</p>

<pre class="brush:csharp">WHILE 1=1
SELECT TOP 100 [RowNum],[SomeId],[SomeCode]
FROM dbo.[TestData]
WHERE [RowNum] &lt; 30000
ORDER BY [SomeId]
OPTION(MAXDOP 1)</pre>


<p>In a new query window, run the following query to get the memory specifications.</p>

<pre class="brush:csharp">SELECT  [granted_memory_kb],[required_memory_kb],[max_used_memory_kb] FROM sys.dm_exec_query_memory_grants WHERE [session_id] = 58</pre>


<p>Here are my results:</p>

<pre class="brush:csharp">     granted_memory_kb    required_memory_kb   max_used_memory_kb
---- -------------------- -------------------- --------------------
FAST 1024                 216                  216

     granted_memory_kb    required_memory_kb   max_used_memory_kb
---- -------------------- -------------------- --------------------
SLOW 6040                 512                  6040</pre>


<p>The results are simply astonishing.&#160; The memory requirements increase nearly 28 times when I use TOP 101, instead of TOP 100.&#160; I do not have a formal explanation of why the TOP 101 operator, consumes more memory than TOP 100.&#160; Brad Schulz, <a title="http://bradsruminations.blogspot.com/" href="http://bradsruminations.blogspot.com/">http://bradsruminations.blogspot.com/</a>, has contacted Conor Cunningham about this issue and believes that 101 is an arbitrary threshold.&#160; Brad is working on an in-depth post involving the TOP operator.&#160; Keep an eye out for this one, as it should be really good.&#160; Anyway, once the 101 threshold is breached the optimizer uses different calculations to optimize a query, which can effectively bloat the memory requirements for the query.&#160; This memory bloat forces the sort operation to spill into tempdb.&#160; This is where the TOP 101 bottleneck exists.&#160; To verify this problem, open profiler and choose the sort warnings counter and you will see that the slow query has a sort warning error, while the fast query does not.</p>

<p>Now that I have identified the problem, how do I solve it?&#160; I will start by attempting the methods that I used in the previous article, <a title="http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html" href="http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html">http://jahaines.blogspot.com/2010/03/performance-tuning-101-what-you-will.html</a>.</p>

<pre class="brush:csharp">SELECT TOP 101 [RowNum],[SomeId],CAST([SomeCode] AS VARCHAR(4200))
FROM dbo.[TestData]
WHERE [RowNum] &lt; 30000
ORDER BY [SomeId]
OPTION(MAXDOP 1)

/*
 SQL Server Execution Times:
   CPU time = 344 ms,  elapsed time = 3385 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
*/</pre>


<p>Bloating the estimated row size still did not help our situation.&#160; Next I will try shrinking the row size.</p>

<pre class="brush:csharp">SELECT TOP 101 [RowNum],[SomeId],RTRIM(CAST([SomeCode] AS VARCHAR(2000)))
FROM dbo.[TestData]
WHERE [RowNum] &lt; 30000
ORDER BY [SomeId]
OPTION(MAXDOP 1)

/*
 SQL Server Execution Times:
   CPU time = 344 ms,  elapsed time = 2461 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
*/</pre>

<p>Hmm.&#160; Still no luck….. How can I reduce the row size of the input passed into the sort operator?&#160; When you really sit back and think about the problem, the answer is really simple.&#160; To reduce the row size, all you have to do is reduce the columns involved in the sort.&#160; I like to use the TOP inside a derived table, making sure to only use the RowNum and SomeId columns.&#160; We can then join back onto the TestData table.&#160; This gives us a fast sort and a ultra fast index seek on the 101 rows we are returning. </p>

<pre class="brush:csharp">SELECT t.[RowNum],t.[SomeId], t.[SomeCode]
FROM dbo.[TestData] t
INNER JOIN(
    SELECT TOP 101 [RowNum],[SomeId]
    FROM dbo.[TestData]
    WHERE [RowNum] &lt; 30000
    ORDER BY [SomeId]
) AS t2
    ON T.RowNum = t2.RowNum
ORDER BY t.[SomeId]
OPTION (MAXDOP 1)

/*
 SQL Server Execution Times:
   CPU time = 31 ms,  elapsed time = 104 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
*/</pre>


<p>Alternatively, we can use correlated subqueries or the cross apply operator.</p>

<pre class="brush:csharp">SELECT TOP 101
    t.[RowNum],
    (SELECT t2.[SomeId] FROM dbo.[TestData] t2 WHERE t2.[RowNum] = t.[RowNum]) AS SomeId,
    (SELECT t2.[SomeCode] FROM dbo.[TestData] t2 WHERE t2.[RowNum] = t.[RowNum]) AS SomeCode
FROM dbo.[TestData] t
WHERE t.[RowNum] &lt; 30000
ORDER BY t.[SomeId]
OPTION (MAXDOP 1)

SELECT TOP 101
    t.[RowNum],
    t2.SomeId,
    t2.SomeCode
FROM dbo.[TestData] T
CROSS APPLY(SELECT t2.SomeId, t2.SomeCode FROM dbo.[TestData] t2 WHERE t2.[RowNum] = t.[RowNum]) AS t2
WHERE t.[RowNum] &lt; 30000
ORDER BY t.[SomeId]
OPTION (MAXDOP 1)</pre>

<p><style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>It should be noted that the correlated subquery method will produce more IO because it uses two subqueries.&#160; As you can see, the solution to this challenge is quite simple, but the solution requires an understanding of what is occurring underneath the hood of SQL Server.&#160; </p>

<p><em>Note: It is still possible that some of the sorting will be sent to tempdb, but you should see a elapsed time that rivals TOP 100.</em></p>

<p>The next optimization technique, I will be demonstrating is a predicate pushing problem.&#160; Unbeknownst to most developers, SQL Server 2005 does have a problem with predicate pushing in views.&#160; A lot of these issues have been resolved in SQL Server 2008, but should be known.&#160; I will be demonstrating a very simple example, using a ranking function.&#160; Ranking functions are relatively new to SQL Server and were introduced in 2005.&#160; I am sure there are other scenarios that cause predicate pushing problems, but I will only be addressing the ranking problem, in this post.</p>

<p>Let’s start by creating a small sample table.</p>

<pre class="brush:csharp">USE [tempdb]
GO

CREATE TABLE Test(
ID INT IDENTITY(1,1) PRIMARY KEY,
FName VARCHAR(50),
LName VARCHAR(50)
);

INSERT INTO dbo.Test VALUES ('Adam','Haines');
INSERT INTO dbo.Test VALUES ('John','Smith');
INSERT INTO dbo.Test VALUES ('Jane','Doe');
GO

CREATE NONCLUSTERED INDEX ncl_idx_LName ON dbo.Test(LName) INCLUDE(FName);
GO</pre>


<p><style type="text/css">

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>

<p>As you can see, the table is relatively simple.&#160; The idea is to present an easy to understand example that demonstrates potential performance problems with views.</p>

<p>Here is my simple query that shows an index seek on LName.</p>

<pre class="brush:csharp">SELECT Id,FName,LName,ROW_NUMBER() OVER(PARTITION BY LName ORDER BY Id) AS seq
FROM dbo.Test
WHERE LName = 'Smith'
GO</pre>

<p><a href="http://lh6.ggpht.com/_ayZBUzPGG9A/S6GoIUzrVMI/AAAAAAAAAZc/wejeWU8BuTU/s1600-h/image%5B3%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="116" alt="image" src="http://lh4.ggpht.com/_ayZBUzPGG9A/S6GoJEU6F8I/AAAAAAAAAZg/sJLbt4WiWRs/image_thumb%5B1%5D.png?imgmax=800" width="606" border="0" /></a> <style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>

<p>Let’s see what happens when I put the logic into a view, with no predicate.&#160; The predicate will be called from outside the view and should be pushed down into the view, as views are materialized into the underlying objects at runtime.</p>

<pre class="brush:csharp">CREATE VIEW dbo.vw_Test
AS
SELECT Id,FName,LName,ROW_NUMBER() OVER(PARTITION BY LName ORDER BY Id) AS seq
FROM dbo.Test
GO</pre>


<p>I will now query the view using the same predicate as the original query.</p>

<pre class="brush:csharp">SELECT Id,FName,LName,seq
FROM dbo.vw_Test 
WHERE LName = 'Smith'
GO</pre>

<p><a href="http://lh4.ggpht.com/_ayZBUzPGG9A/S6GoJa6BkaI/AAAAAAAAAZk/ctVSsJJVFdg/s1600-h/image%5B7%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="133" alt="image" src="http://lh5.ggpht.com/_ayZBUzPGG9A/S6GoKGtndaI/AAAAAAAAAZo/VzqbA9h9n48/image_thumb%5B3%5D.png?imgmax=800" width="566" border="0" /></a> <style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>

<p>The problem here is the optimizer decided to filter the results of the query <strong>AFTER</strong> the table “Test” has been scanned.&#160; One should expect the optimizer to seek on the LName column because the optimizer should push the predicate; however, SQL Server 2005 does not do a great job of this.&#160; SQL Server 2008 will appropriately push the predicate deep into the plan to get the index seek.&#160; How do we solve this problem?&#160; Unfortunately, there is not a whole lot you can do to make the plan work more efficiently.&#160; The best option in my opinion is to a INLINE TVF to parameterize the query.&#160; </p>

<pre class="brush:csharp">CREATE FUNCTION dbo.fn_Test(@LName VARCHAR(50))
RETURNS TABLE
RETURN(
    SELECT Id,FName,LName,ROW_NUMBER() OVER(PARTITION BY LName ORDER BY Id) AS seq
    FROM dbo.Test
    WHERE LName = @LName
)
GO</pre>


<p></p>

<p>Now execute a select against the TVF using the same predicate.</p>

<pre class="brush:csharp">SELECT Id,FName,LName,seq
FROM dbo.fn_Test('Smith')</pre>

<p><a href="http://lh5.ggpht.com/_ayZBUzPGG9A/S6GoKheNGOI/AAAAAAAAAZs/aQEhHjn_9U0/s1600-h/image%5B11%5D.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="139" alt="image" src="http://lh3.ggpht.com/_ayZBUzPGG9A/S6GoMCRJW-I/AAAAAAAAAZw/M0DmwmM5Jt0/image_thumb%5B5%5D.png?imgmax=800" width="551" border="0" /></a> <style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>

<p>There you have it.&#160; I have demonstrated a few optimization techniques that I have used to solve performance problems.&#160; I have only scratched the surface here.&#160; There are many more optimization techniques available.&#160; Stay tuned for future posts, where I will explore even more optimization techniques including a shocking example demonstrating how an index rebuild can introduce fragmentation and how to avoid it.</p>

<p>Until next time, happy coding.</p>  <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4646137438366687895-6643583342773077191?l=jahaines.blogspot.com' alt='' /></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/DemystifyingSqlServer?a=FS9g864tMEM:rRplRm6mpM4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/DemystifyingSqlServer?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DemystifyingSqlServer?a=FS9g864tMEM:rRplRm6mpM4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/DemystifyingSqlServer?i=FS9g864tMEM:rRplRm6mpM4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/DemystifyingSqlServer?a=FS9g864tMEM:rRplRm6mpM4:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/DemystifyingSqlServer?d=7Q72WNTAKBA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/DemystifyingSqlServer/~4/FS9g864tMEM" height="1" width="1"/><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Rqc5iJXzSCI:rRplRm6mpM4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Rqc5iJXzSCI:rRplRm6mpM4:G79ilh31hkQ"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=G79ilh31hkQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/sqlserverpedia?a=Rqc5iJXzSCI:rRplRm6mpM4:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/sqlserverpedia?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/sqlserverpedia/~4/Rqc5iJXzSCI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverpedia.com/blog/sql-server-bloggers/performance-tuning-101-%e2%80%93-what-you-will-not-learn-in-the-class-room-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverpedia.com/blog/sql-server-bloggers/performance-tuning-101-%e2%80%93-what-you-will-not-learn-in-the-class-room-part-2/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.513 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-03-18 23:26:43 -->
