<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title> &#187; Performance</title>
	<atom:link href="http://benchmarkitconsulting.com/category/sql-server/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://benchmarkitconsulting.com</link>
	<description></description>
	<lastBuildDate>Mon, 06 Feb 2012 16:34:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Check Constraints That Call Functions</title>
		<link>http://benchmarkitconsulting.com/colin-stasiuk/2011/08/08/check-constraints-that-call-functions/</link>
		<comments>http://benchmarkitconsulting.com/colin-stasiuk/2011/08/08/check-constraints-that-call-functions/#comments</comments>
		<pubDate>Mon, 08 Aug 2011 14:02:06 +0000</pubDate>
		<dc:creator>Colin Stasiuk</dc:creator>
				<category><![CDATA[Benchmark IT Consulting]]></category>
		<category><![CDATA[Colin Stasiuk]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Check Constraints]]></category>
		<category><![CDATA[Function]]></category>
		<category><![CDATA[RBAR]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2008]]></category>

		<guid isPermaLink="false">http://benchmarkitconsulting.com/?p=1790</guid>
		<description><![CDATA[Originally this blog post was going to be about how using check constraints that call functions basically eliminates SQL Server&#8217;s ability to do set-based operations and I was going to setup an example that inserted 10 rows to show that because of the check constraint that calls a function SQL Server ends up calling the [...]]]></description>
			<content:encoded><![CDATA[<p>Originally this blog post was going to be about how using check constraints that call functions basically eliminates SQL Server&#8217;s ability to do set-based operations and I was going to setup an example that inserted 10 rows to show that because of the check constraint that calls a function SQL Server ends up calling the function 10 times (once per row inserted).  Once I started building my test scripts to show this I stumbled and fell face first into what I think is almost a worst side effect of using check constraints that call functions.</p>
<p><strong>Disclaimer</strong>: The use case I&#8217;m going with (checking the uniqueness of a column with a function) I understand can be &#8220;solutioned&#8221; much better with a unique constraint but this is not to show the best way to do something, rather a tricky little problem with doing it with a check constraint that calls a function.</p>
<p>OK first lets build ourselves a test db and table:</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">USE</span> master
GO
<span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">DATABASE</span> <span style="color: #808080;">&#91;</span>FunWithFunctions<span style="color: #808080;">&#93;</span>
GO
<span style="color: #0000FF;">USE</span> FunWithFunctions
GO
<span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">TABLE</span> dbo.<span style="color: #202020;">tblCustomers</span>
	<span style="color: #808080;">&#40;</span>
	CustomerID <span style="color: #0000FF;">INT</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">NULL</span> <span style="color: #0000FF;">IDENTITY</span> <span style="color: #808080;">&#40;</span><span style="color: #000;">1</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span>,
	CustomerName <span style="color: #0000FF;">NVARCHAR</span><span style="color: #808080;">&#40;</span><span style="color: #000;">50</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">NULL</span>,
	CustomerEmailAddress <span style="color: #0000FF;">NVARCHAR</span><span style="color: #808080;">&#40;</span><span style="color: #000;">50</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">NULL</span>
	<span style="color: #808080;">&#41;</span>  <span style="color: #0000FF;">ON</span> <span style="color: #808080;">&#91;</span><span style="color: #0000FF;">PRIMARY</span><span style="color: #808080;">&#93;</span>
GO
<span style="color: #0000FF;">ALTER</span> <span style="color: #0000FF;">TABLE</span> dbo.<span style="color: #202020;">tblCustomers</span> <span style="color: #0000FF;">ADD</span> <span style="color: #0000FF;">CONSTRAINT</span>
	PK_tblCustomers <span style="color: #0000FF;">PRIMARY</span> <span style="color: #0000FF;">KEY</span> <span style="color: #0000FF;">CLUSTERED</span>
	<span style="color: #808080;">&#40;</span>
	CustomerID
	<span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">WITH</span><span style="color: #808080;">&#40;</span> STATISTICS_N<span style="color: #808080;">OR</span>ECOMPUTE <span style="color: #808080;">=</span> <span style="color: #0000FF;">OFF</span>, IGN<span style="color: #808080;">OR</span>E_DUP_KEY <span style="color: #808080;">=</span> <span style="color: #0000FF;">OFF</span>, <span style="color: #808080;">ALL</span>OW_ROW_LOCKS <span style="color: #808080;">=</span> <span style="color: #0000FF;">ON</span>, <span style="color: #808080;">ALL</span>OW_PAGE_LOCKS <span style="color: #808080;">=</span> <span style="color: #0000FF;">ON</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">ON</span> <span style="color: #808080;">&#91;</span><span style="color: #0000FF;">PRIMARY</span><span style="color: #808080;">&#93;</span>
GO</pre></div></div>

<p>Now we&#8217;re going to build our function that returns the count of CustomerIDs that have the same email address:</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">FUNCTION</span> dbo.<span style="color: #202020;">fnEmailAddressUniqueness</span><span style="color: #808080;">&#40;</span>@EmailAddress <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">NVARCHAR</span><span style="color: #808080;">&#40;</span><span style="color: #000;">50</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span>
<span style="color: #0000FF;">RETURNS</span> <span style="color: #0000FF;">INT</span>
<span style="color: #0000FF;">AS</span>
<span style="color: #0000FF;">BEGIN</span>
	<span style="color: #0000FF;">DECLARE</span> @ReturnValue <span style="color: #0000FF;">INT</span> <span style="color: #808080;">=</span> <span style="color: #000;">0</span>
	<span style="color: #0000FF;">SELECT</span>	@ReturnValue <span style="color: #808080;">=</span> <span style="color: #FF00FF;">COUNT</span><span style="color: #808080;">&#40;</span>CustomerID<span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">FROM</span> tblCustomers <span style="color: #0000FF;">WHERE</span> CustomerEmailAddress <span style="color: #808080;">=</span> @EmailAddress
	<span style="color: #0000FF;">RETURN</span>	@ReturnValue
<span style="color: #0000FF;">END</span>
GO</pre></div></div>

<p>OK now we&#8217;re going to add a check constraint that uses this function to make sure that there are no other Customers with that email address (CustomerEmailAddress = 0)</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">ALTER</span> <span style="color: #0000FF;">TABLE</span> dbo.<span style="color: #202020;">tblCustomers</span> <span style="color: #0000FF;">ADD</span> <span style="color: #0000FF;">CONSTRAINT</span> CK_fnEmailAddressUniqueness <span style="color: #0000FF;">CHECK</span> <span style="color: #808080;">&#40;</span>dbo.<span style="color: #202020;">fnEmailAddressUniqueness</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#91;</span>CustomerEmailAddress<span style="color: #808080;">&#93;</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">=</span><span style="color: #000;">0</span><span style="color: #808080;">&#41;</span>
GO</pre></div></div>

<p>Fantastic&#8230; now this was where I was going to do my insert of 10 rows and show through a profiler trace that my function was going to get called 10 times (once per row) but this happened:</p>
<p><a href="http://benchmarkitconsulting.com/wp-content/uploads/2011/08/funwithfunctions1.jpg"><img class="alignnone size-full wp-image-1795" title="funwithfunctions1" src="http://benchmarkitconsulting.com/wp-content/uploads/2011/08/funwithfunctions1.jpg" alt="" width="996" height="338" /></a></p>
<p>(click to enlarge)</p>
<p>Ummmmm weird&#8230;. what happened?</p>
<p>I thought maybe there was something wrong with my function at first so I decided to call the function manually:</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">SELECT</span> dbo.<span style="color: #202020;">fnEmailAddressUniqueness</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Superman@gmail.com'</span><span style="color: #808080;">&#41;</span></pre></div></div>

<p>That returned 0 (zero) as expected so I was left scratching my head for a while trying to imagine how a check constraint that is checking to make sure a value is 0 would fail (especially on an empty table) then it hit me&#8230;.</p>
<p><img class="alignnone size-full wp-image-1798" title="funwithfunctions2" src="http://benchmarkitconsulting.com/wp-content/uploads/2011/08/funwithfunctions2.jpg" alt="" width="200" height="174" /></p>
<p>This check constraint that is calling a function is not getting evaluated BEFORE the insert&#8230; but DURING/AFTER.</p>
<p>To test this theory I changed the ADD CONSTRAINT statement to this (after I dropped it):</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">ALTER</span> <span style="color: #0000FF;">TABLE</span> dbo.<span style="color: #202020;">tblCustomers</span> <span style="color: #0000FF;">ADD</span> <span style="color: #0000FF;">CONSTRAINT</span> CK_fnEmailAddressUniqueness <span style="color: #0000FF;">CHECK</span> <span style="color: #808080;">&#40;</span>dbo.<span style="color: #202020;">fnEmailAddressUniqueness</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#91;</span>CustomerEmailAddress<span style="color: #808080;">&#93;</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">=</span><span style="color: #000;">1</span><span style="color: #808080;">&#41;</span>
GO</pre></div></div>

<p>And wouldn&#8217;t you know it&#8230; I could now insert data.</p>
<p>I wasn&#8217;t satisfied with just that&#8230; I wanted to actually see with my own two eye that it was actually inserting the row, checking the constraint (that calls the function), and removing the row because of the failure.</p>
<p>As dirty as this is, in one SSMS window I did this (using the GO 100000 statement to execute the following statement 100,000 times):</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">INSERT</span> <span style="color: #0000FF;">INTO</span> dbo.<span style="color: #202020;">tblCustomers</span><span style="color: #808080;">&#40;</span>CustomerName, CustomerEmailAddress<span style="color: #808080;">&#41;</span>
<span style="color: #0000FF;">VALUES</span>
<span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'Clark Kent'</span>, <span style="color: #FF0000;">'Superman@gmail.com'</span><span style="color: #808080;">&#41;</span></pre></div></div>

<p>And then in a different SSMS window I ran this statement continually:</p>

<div class="wp_syntax"><div class="code"><pre class="tsql" style="font-family:monospace;"><span style="color: #0000FF;">SELECT</span> <span style="color: #808080;">*</span> <span style="color: #0000FF;">FROM</span> tblCustomers <span style="color: #0000FF;">WITH</span><span style="color: #808080;">&#40;</span>NOLOCK<span style="color: #808080;">&#41;</span></pre></div></div>

<p>and I did this till the planets aligned and I was able to execute it at the exact split second I needed to capture this:</p>
<p><img class="alignnone size-full wp-image-1800" title="CheckConstraintFunctionCapture1" src="http://benchmarkitconsulting.com/wp-content/uploads/2011/08/CheckConstraintFunctionCapture1.jpg" alt="" width="396" height="178" /></p>
<p>and then the next time I ran the same SELECT it was gone! (notice the CustomerID 5601)</p>
<p>So I stopped the &#8220;GO 100000&#8243; statement that was continually trying to insert that single row and ran the rest of my insert (without the Superman@gmail.com row) and the rest of the data went in fine (with the CustomerID being in the 9000&#8242;s even though those IDs really never were actually used&#8221;)</p>
<p>Neat/Scary huh?</p>
<p>Anyways I found this to be quite surprising and I figured that I wouldn&#8217;t be the only one who would so I thought I&#8217;d do a post on it.</p>
<p>Have a great day!</p>
<p>If you&#8217;d like to chat with me about this or anything else (SQL or other) please leave a comment or hit me up on my Twitter: <a href="http://twitter.com/ColinStasiuk" target="_blank">@ColinStasiuk</a></p>
<p><a href="http://benchmarkitconsulting.com/" target="_blank"><img title="benchmark_sm" src="http://benchmarkitconsulting.com/wp-content/uploads/2009/02/benchmark_sm.jpg" alt="" width="157" height="74" /></a></p>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Check+Constraints+That+Call+Functions+http://tinyurl.com/3okda4b" title="Post to Twitter"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-twitter-big4.png" alt="Post to Twitter" /></a> <a class="tt" href="http://delicious.com/post?url=http://benchmarkitconsulting.com/colin-stasiuk/2011/08/08/check-constraints-that-call-functions/&amp;title=Check+Constraints+That+Call+Functions" title="Post to Delicious"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-delicious-big4.png" alt="Post to Delicious" /></a> <a class="tt" href="http://digg.com/submit?url=http://benchmarkitconsulting.com/colin-stasiuk/2011/08/08/check-constraints-that-call-functions/&amp;title=Check+Constraints+That+Call+Functions" title="Post to Digg"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-digg-big4.png" alt="Post to Digg" /></a> <a class="tt" href="http://stumbleupon.com/submit?url=http://benchmarkitconsulting.com/colin-stasiuk/2011/08/08/check-constraints-that-call-functions/&amp;title=Check+Constraints+That+Call+Functions" title="Post to StumbleUpon"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-su-big4.png" alt="Post to StumbleUpon" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://benchmarkitconsulting.com/colin-stasiuk/2011/08/08/check-constraints-that-call-functions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>EDMPASS July Meeting w/Brent Ozar #YEG</title>
		<link>http://benchmarkitconsulting.com/colin-stasiuk/2010/05/31/edmpass-july-meeting-wbrent-ozar-yeg/</link>
		<comments>http://benchmarkitconsulting.com/colin-stasiuk/2010/05/31/edmpass-july-meeting-wbrent-ozar-yeg/#comments</comments>
		<pubDate>Mon, 31 May 2010 20:09:37 +0000</pubDate>
		<dc:creator>Colin Stasiuk</dc:creator>
				<category><![CDATA[Benchmark IT Consulting]]></category>
		<category><![CDATA[Colin Stasiuk]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[PASS]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Brent Ozar]]></category>
		<category><![CDATA[EDMPASS]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2008]]></category>
		<category><![CDATA[Virtualization]]></category>

		<guid isPermaLink="false">http://benchmarkitconsulting.com/?p=1415</guid>
		<description><![CDATA[On July 7th 2010 the Edmonton Chapter of PASS is having it’s next meeting. Details below: http://www.eventbrite.com/event/686883487 Please be sure to not only click the “Add to my calendar” but also the “Register” button so that we can plan accordingly for food and drinks.  Date:  July 7th 2010 Time: 5:00 pm &#8211; 7:00 pm Location: Stanley A. Milner library Map: [...]]]></description>
			<content:encoded><![CDATA[<p>On July 7th 2010 the Edmonton Chapter of PASS is having it’s next meeting. Details below:</p>
<p><a href="http://www.eventbrite.com/event/686883487" target="_blank">http://www.eventbrite.com/event/686883487</a></p>
<p><strong>Please be sure to not only click the “Add to my calendar” but also the “Register” button so that we can plan accordingly for food and drinks.</strong> </p>
<p><strong>Date:</strong>  July 7th 2010<br />
<strong>Time:</strong> 5:00 pm &#8211; 7:00 pm<br />
<strong>Location:</strong> Stanley A. Milner library<br />
<strong>Map:</strong> <a href="http://www.mapquest.com/maps/map.adp?formtype=address&amp;country=CA&amp;popflag=0&amp;latitude=&amp;longitude=&amp;name=&amp;phone=&amp;level=&amp;addtohistory=&amp;cat=&amp;address=7+Sir+Winston+Churchill+Square+NW&amp;city=Edmonton&amp;state=AB&amp;zipcode=" target="_blank">7 Sir Winston Churchill Square</a><br />
<strong>Meeting Room:</strong> <strong>Centennial Room &#8211; Basement</strong><br />
<strong>Speaker:</strong> Brent Ozar<br />
<strong>Topic:</strong> Virtualization and Magicians: Dealing with Virtual SQL Server</p>
<p><strong>Session Abstract:</strong></p>
<h3>Virtualization and Magicians: Dealing with Virtual SQL Server</h3>
<div>So the sysadmins told you they’ve learned a few tricks, and they’re going to virtualize your database servers. In this session, we’ll talk about our real-world experiences with virtual SQL Servers and how to help the sysadmins avoid implementation mistakes that will saw SQL Server’s performance in half.</div>
<ul>
<li>How to configure CPU, memory and storage for virtual environments</li>
<li>How to benchmark your servers and make sure they’ll handle your loads</li>
<li>Common pitfalls like antivirus definition downloads that can cripple your servers</li>
<li>What to watch for after V-day</li>
</ul>
<p><strong>Presenter Information:</strong>  Brent Ozar</p>
<p>Brent is a SQL Server Domain Expert with Quest Software. Brent has a decade of broad IT experience, performing systems administration and project management before moving into database administration. In his current role, Brent specializes in performance tuning, disaster recovery and automating SQL Server management. Previously, Brent spent 2 years at Southern Wine &amp; Spirits, a Miami-based wine &amp; spirits distributor.</p>
<p>Brent has experience conducting training sessions, has written several technical articles, and blogs prolifically at <a href="http://www.brentozar.com/" target="_blank">http://www.BrentOzar.com</a>. He’s currently writing SQL Server Internals and Troubleshooting for Wiley/Wrox along with Christian Bolton, and Justin Langford.  He’s Editor-in-Chief at SQLServerPedia.com, where he also records video podcasts.</p>
<p><strong>Agenda:<br />
</strong>5:00 pm &#8211; Pizza and Socializing<br />
5:30 pm &#8211; Sponsor Presentation<br />
5:45 pm &#8211; Feature Presentation<br />
7:00 pm &#8211; Wrap Up and Draws</p>
<p>If you haven’t signed up already at <a href="http://edmpass.com/?page_id=7" target="_blank">EDMPASS.com</a> please do so now to receive meeting notifications, news, and updates from EDMPASS.</p>
<p>Hope to see you there.</p>
<p>Enjoy!!</p>
<p><a href="http://benchmarkitconsulting.com" target="_blank"><img class="alignnone size-full wp-image-402" title="benchmark_sm" src="http://benchmarkitconsulting.com/wp-content/uploads/2009/02/benchmark_sm.jpg" alt="" width="157" height="74" /></a><a href="http://sqlserverpedia.com/wiki/Editors#Colin_Stasiuk" target="_blank"><img src="http://sqlserverpedia.com/badges/SQLServerPedia_Badge_Blogger.jpg" alt="" width="120" height="60" /> </a></p>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=EDMPASS+July+Meeting+w%2FBrent+Ozar+%23YEG+http://tinyurl.com/2wrhsqk" title="Post to Twitter"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-twitter-big4.png" alt="Post to Twitter" /></a> <a class="tt" href="http://delicious.com/post?url=http://benchmarkitconsulting.com/colin-stasiuk/2010/05/31/edmpass-july-meeting-wbrent-ozar-yeg/&amp;title=EDMPASS+July+Meeting+w%2FBrent+Ozar+%23YEG" title="Post to Delicious"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-delicious-big4.png" alt="Post to Delicious" /></a> <a class="tt" href="http://digg.com/submit?url=http://benchmarkitconsulting.com/colin-stasiuk/2010/05/31/edmpass-july-meeting-wbrent-ozar-yeg/&amp;title=EDMPASS+July+Meeting+w%2FBrent+Ozar+%23YEG" title="Post to Digg"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-digg-big4.png" alt="Post to Digg" /></a> <a class="tt" href="http://stumbleupon.com/submit?url=http://benchmarkitconsulting.com/colin-stasiuk/2010/05/31/edmpass-july-meeting-wbrent-ozar-yeg/&amp;title=EDMPASS+July+Meeting+w%2FBrent+Ozar+%23YEG" title="Post to StumbleUpon"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-su-big4.png" alt="Post to StumbleUpon" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://benchmarkitconsulting.com/colin-stasiuk/2010/05/31/edmpass-july-meeting-wbrent-ozar-yeg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Just cause it works&#8230; doesn&#8217;t make it right.</title>
		<link>http://benchmarkitconsulting.com/colin-stasiuk/2009/04/02/just-cause-it-works-doesnt-make-it-right/</link>
		<comments>http://benchmarkitconsulting.com/colin-stasiuk/2009/04/02/just-cause-it-works-doesnt-make-it-right/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 14:40:16 +0000</pubDate>
		<dc:creator>Colin Stasiuk</dc:creator>
				<category><![CDATA[Benchmark IT Consulting]]></category>
		<category><![CDATA[Colin Stasiuk]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[functions]]></category>
		<category><![CDATA[index]]></category>
		<category><![CDATA[Index Scan]]></category>
		<category><![CDATA[Index Seek]]></category>
		<category><![CDATA[Scan]]></category>
		<category><![CDATA[Seek]]></category>

		<guid isPermaLink="false">http://benchmarkitconsulting.com/?p=614</guid>
		<description><![CDATA[OK so the title might not be very specific so I&#39;m sure I&#39;m breaking some rule about how to be a &#8220;successful&#8221; author&#8230; but if I can get a bunch of people on April Fool&#39;s Day &#8220;Rickrolled&#8221; I&#39;m hoping enough people will read on. In SQL there are so many ways to solve the same [...]]]></description>
			<content:encoded><![CDATA[<p>OK so the title might not be very specific so I&#39;m sure I&#39;m breaking some rule about how to be a &#8220;successful&#8221; author&#8230; but if I can get a bunch of people on April Fool&#39;s Day &#8220;<a href="http://en.wikipedia.org/wiki/Rickroll" target="_blank">Rickrolled</a>&#8221; I&#39;m hoping enough people will read on.</p>
<p>In SQL there are so many ways to solve the same problem that sometimes people just pick the first thing that works. While this may be the fastest way to get a solution in place depending on the size and scope of the problem you are trying to solve you may be having to revisit your solution down the road to find a &#8220;better way&#8221;.</p>
<p>Someone could make a years worth of articles of examples but the one I&#39;m going to touch on today is using a function in a where clause.</p>
<p>OK for this example I&#39;m not going to build my own table cause I don&#39;t know enough superhero characters to make a decent sample size so I&#39;m going to be working with the AdventureWorks (SQL 2005) databases.</p>
<p>OK first off let&#39;s set our STATISTICS TIME ON as well as our STATISTICS IO ON using the following statement:</p>
<p><code style="font-size: 12px;"><span style="color:blue">SET STATISTICS </span><span style="color:black">TIME </span><span style="color:blue">ON<br />
</span><span style="color:black">GO<br />
</span><span style="color:blue">SET STATISTICS </span><span style="color:black">IO </span><span style="color:blue">ON<br />
</span><span style="color:black">GO</span></code></p>
<p>OK now let&#39;s run the following statement:</p>
<p><code style="font-size: 12px;"><span style="color:blue">SELECT </span><span style="color:black">FirstName</span><span style="color:gray">, </span><span style="color:black">LastName</span><span style="color:gray">, </span><span style="color:black">EmailAddress</span><span style="color:gray">, </span><span style="color:black">Phone</span><span style="color:gray">, </span><span style="color:black">ModifiedDate<br />
</span><span style="color:blue">FROM   </span><span style="color:black">Person.Contact<br />
</span><span style="color:blue">WHERE  </span><span style="color:magenta">LEFT</span><span style="color:gray">(</span><span style="color:black">EmailAddress</span><span style="color:gray">, </span><span style="color:black">5</span><span style="color:gray">) </span><span style="color:blue">= </span><span style="color:red">&#39;cryst&#39;<br />
</span><span style="color:black">GO<br />
</span></code></p>
<p>So in that statement we&#39;re doing a function (LEFT) in our WHERE clause. AdventureWorks isn&#39;t the biggest database in the world so the query comes back in a subsecond and our STATISTICS (at least on my test server) look like this:</p>
<p><em><span style="color: #3366ff;">SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 0 ms.</span></em></p>
<p><em><span style="color: #3366ff;">(22 row(s) affected)<br />
Table &#39;Contact&#39;. Scan count 1, logical reads 220, physical reads 0,<br />
read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</span></em></p>
<p><em><span style="color: #3366ff;">SQL Server Execution Times: CPU time = 15 ms, elapsed time = 12 ms.</span></em></p>
<p>Now let&#39;s do the same thing but this time we&#39;re NOT going to use a function in the WHERE clause:</p>
<p><code style="font-size: 12px;"><span style="color:black"><br />
</span><span style="color:blue">SELECT </span><span style="color:black">FirstName</span><span style="color:gray">, </span><span style="color:black">LastName</span><span style="color:gray">, </span><span style="color:black">EmailAddress</span><span style="color:gray">, </span><span style="color:black">Phone</span><span style="color:gray">, </span><span style="color:black">ModifiedDate<br />
</span><span style="color:blue">FROM   </span><span style="color:black">Person.Contact<br />
</span><span style="color:blue">WHERE  </span><span style="color:black">EmailAddress </span><span style="color:gray">LIKE </span><span style="color:red">&#39;cryst%&#39;<br />
</span><span style="color:black">GO</span></code></p>
<p>OK subsecond results&#8230; as expected but in looking at the STATISTICS we see this:</p>
<p><em><span style="color: #3366ff;">SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 0 ms.</span></em></p>
<p><em><span style="color: #3366ff;">(22 row(s) affected)<br />
Table &#39;Contact&#39;. Scan count 1, logical reads 56, physical reads 0,<br />
read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.</span></em></p>
<p><em><span style="color: #3366ff;">SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms.</span></em></p>
<p>OK so at this point we see that using the LIKE statement and not a function directly against a column in our WHERE clause resulted in less logical reads, less CPU time and had an overall a smaller value for elapsed time. So how could that be?</p>
<p>Let&#39;s include the actual exection plan (CTRL-M) and run our two queries again:</p>
<p><code style="font-size: 12px;"><span style="color:blue">SELECT </span><span style="color:black">FirstName</span><span style="color:gray">, </span><span style="color:black">LastName</span><span style="color:gray">, </span><span style="color:black">EmailAddress</span><span style="color:gray">, </span><span style="color:black">Phone</span><span style="color:gray">, </span><span style="color:black">ModifiedDate<br />
</span><span style="color:blue">FROM   </span><span style="color:black">Person.Contact<br />
</span><span style="color:blue">WHERE  </span><span style="color:magenta">LEFT</span><span style="color:gray">(</span><span style="color:black">EmailAddress</span><span style="color:gray">, </span><span style="color:black">5</span><span style="color:gray">) </span><span style="color:blue">= </span><span style="color:red">&#39;cryst&#39;<br />
</span><span style="color:black">GO<br />
</span><span style="color:blue">SELECT </span><span style="color:black">FirstName</span><span style="color:gray">, </span><span style="color:black">LastName</span><span style="color:gray">, </span><span style="color:black">EmailAddress</span><span style="color:gray">, </span><span style="color:black">Phone</span><span style="color:gray">, </span><span style="color:black">ModifiedDate<br />
</span><span style="color:blue">FROM   </span><span style="color:black">Person.Contact<br />
</span><span style="color:blue">WHERE  </span><span style="color:black">EmailAddress </span><span style="color:gray">LIKE </span><span style="color:red">&#39;cryst%&#39;<br />
</span><span style="color:black">GO<br />
</span></code></p>
<p>In looking at the execution plan you will see the first query (using LEFT) is doing an index scan and the second query (using LIKE) is doing an index seek and as we know an index seek is preferable as it only pulls back the rows that satisfy the query.</p>
<p>So what&#39;s the takeaway from this article&#8230; we solved the same problem (finding email addresses that start with the characters &#8220;cryst&#8221;) 2 different ways and got very different results, not in the result set but in the way SQL Server executed the request. </p>
<p>By not using a function in our WHERE clause we took an index scan (expensive) and turned it into an index seek (more efficient). </p>
<p>Enjoy!!</p>
<p style="text-align: left;"><a href="http://benchmarkitconsulting.com"><img class="alignnone size-full wp-image-402" title="benchmark_sm" src="http://benchmarkitconsulting.com/wp-content/uploads/2009/02/benchmark_sm.jpg" alt="" /></a><a href="http://sqlserverpedia.com/wiki/Editors#Colin_Stasiuk" target="_blank"><img src="http://sqlserverpedia.com/badges/SQLServerPedia_Badge_Blogger.jpg" alt="" /> </a></p>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Just+cause+it+works%26%238230%3B+doesn%26%238217%3Bt+make+it+right.+http://tinyurl.com/dkbjmc" title="Post to Twitter"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-twitter-big4.png" alt="Post to Twitter" /></a> <a class="tt" href="http://delicious.com/post?url=http://benchmarkitconsulting.com/colin-stasiuk/2009/04/02/just-cause-it-works-doesnt-make-it-right/&amp;title=Just+cause+it+works%26%238230%3B+doesn%26%238217%3Bt+make+it+right." title="Post to Delicious"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-delicious-big4.png" alt="Post to Delicious" /></a> <a class="tt" href="http://digg.com/submit?url=http://benchmarkitconsulting.com/colin-stasiuk/2009/04/02/just-cause-it-works-doesnt-make-it-right/&amp;title=Just+cause+it+works%26%238230%3B+doesn%26%238217%3Bt+make+it+right." title="Post to Digg"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-digg-big4.png" alt="Post to Digg" /></a> <a class="tt" href="http://stumbleupon.com/submit?url=http://benchmarkitconsulting.com/colin-stasiuk/2009/04/02/just-cause-it-works-doesnt-make-it-right/&amp;title=Just+cause+it+works%26%238230%3B+doesn%26%238217%3Bt+make+it+right." title="Post to StumbleUpon"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-su-big4.png" alt="Post to StumbleUpon" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://benchmarkitconsulting.com/colin-stasiuk/2009/04/02/just-cause-it-works-doesnt-make-it-right/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Performance Tuning &#8211; Level Playing Field</title>
		<link>http://benchmarkitconsulting.com/colin-stasiuk/2009/01/06/performance-tuning-level-playing-field/</link>
		<comments>http://benchmarkitconsulting.com/colin-stasiuk/2009/01/06/performance-tuning-level-playing-field/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 14:57:03 +0000</pubDate>
		<dc:creator>Colin Stasiuk</dc:creator>
				<category><![CDATA[Benchmark IT Consulting]]></category>
		<category><![CDATA[Colin Stasiuk]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[DBCC]]></category>
		<category><![CDATA[DBCC DROPCLEANBUFFERS]]></category>
		<category><![CDATA[DBCC FREEPROCCACHE]]></category>
		<category><![CDATA[Performance Tuning]]></category>

		<guid isPermaLink="false">http://benchmarkitconsulting.com/?p=269</guid>
		<description><![CDATA[When you&#8217;re performance tuning T-SQL one thing you want to make sure is that you are have a consistent environment to test your changes/modifications.  Two commands that will help ensure that your environment stays close to the same for each iteration of your script are DBCC DROPCLEANBUFFERS and DBCC FREEPROCCACHE. Now for all those people testing [...]]]></description>
			<content:encoded><![CDATA[<p>When you&#8217;re performance tuning T-SQL one thing you want to make sure is that you are have a consistent environment to test your changes/modifications.  Two commands that will help ensure that your environment stays close to the same for each iteration of your script are <a href="http://msdn.microsoft.com/en-us/library/ms187762.aspx" target="_blank">DBCC DROPCLEANBUFFERS</a> and <a href="http://msdn.microsoft.com/en-us/library/ms174283.aspx" target="_blank">DBCC FREEPROCCACHE</a>.</p>
<p>Now for all those people testing in production (first hang your head in shame <img src='http://benchmarkitconsulting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) you should use ALOT of caution with these two DBCC commands (or better yet just avoid them altogether in production).</p>
<p><strong>DBCC DROPCLEANBUFFERS</strong> gives you a cold buffer cache while avoiding a full service shutdown/restart.  Good to do a CHECKPOINT before running this command so all the dirty pages for your database that you&#8217;re working with will be written to disk.  Using this command will help give you a level playing field and an accurate estimation of your codes execution time.  Not using this command might end up with a cached query and your changes (while great I&#8217;m sure) might seem to make a big difference without really doing so.</p>
<p><strong>DBCC FREEPROCCACHE</strong> gives you the ability to clear all (or a specific) elements from the plan cache or remove all workload groups from a specified resource pool.  Once again be very careful where you use this as clearing your plan cache will cause stored procs to be recompiled which will give you a performance degredation. </p>
<p>These two DBCC commands can help out alot when trying to troubleshoot/optimize T-SQL code.  Run them both before each execution of the code you are working with to help make sure that the positive effect that you&#8217;re seeing is due to your code and not cached information.</p>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Performance+Tuning+%26%238211%3B+Level+Playing+Field+http://tinyurl.com/akucvb" title="Post to Twitter"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-twitter-big4.png" alt="Post to Twitter" /></a> <a class="tt" href="http://delicious.com/post?url=http://benchmarkitconsulting.com/colin-stasiuk/2009/01/06/performance-tuning-level-playing-field/&amp;title=Performance+Tuning+%26%238211%3B+Level+Playing+Field" title="Post to Delicious"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-delicious-big4.png" alt="Post to Delicious" /></a> <a class="tt" href="http://digg.com/submit?url=http://benchmarkitconsulting.com/colin-stasiuk/2009/01/06/performance-tuning-level-playing-field/&amp;title=Performance+Tuning+%26%238211%3B+Level+Playing+Field" title="Post to Digg"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-digg-big4.png" alt="Post to Digg" /></a> <a class="tt" href="http://stumbleupon.com/submit?url=http://benchmarkitconsulting.com/colin-stasiuk/2009/01/06/performance-tuning-level-playing-field/&amp;title=Performance+Tuning+%26%238211%3B+Level+Playing+Field" title="Post to StumbleUpon"><img class="nothumb" src="http://benchmarkitconsulting.com/wp-content/plugins/tweet-this/icons/tt-su-big4.png" alt="Post to StumbleUpon" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://benchmarkitconsulting.com/colin-stasiuk/2009/01/06/performance-tuning-level-playing-field/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

