<?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>Jeremiah Peschka, SQL Server Developer</title>
	
	<link>http://facility9.com</link>
	<description>Jeremiah Peschka's ruminations on sql, ruby, c# and other things</description>
	<lastBuildDate>Fri, 12 Mar 2010 15:13:45 +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/facility9" /><feedburner:info uri="facility9" /><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-sa/3.0/</creativeCommons:license><item>
		<title>How can we grow the pool of Summit speakers?</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/fSzA4onSz1s/how-can-we-grow-the-pool-of-summit-speakers</link>
		<comments>http://facility9.com/2010/03/12/how-can-we-grow-the-pool-of-summit-speakers#comments</comments>
		<pubDate>Fri, 12 Mar 2010 15:13:45 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Speaking]]></category>
		<category><![CDATA[sqlpass]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[i really do care what you think]]></category>
		<category><![CDATA[summit2010]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1414</guid>
		<description><![CDATA[Allen Kinsel, my brother in arms for the Summit 2010 Program, posed a question about how to grow the pool of speakers for the PASS 2010 Summit. Allen has proposed that in order to bring in more speakers, we limit things to 1 session per speaker. With 168 sessions across the board, that&#8217;s a lot [...]]]></description>
			<content:encoded><![CDATA[<p>Allen Kinsel, my brother in arms for the Summit 2010 Program, posed a question about how to <a href='http://www.allenkinsel.com/archive/2010/03/growing-the-pool-of-speakers/' target='_blank'>grow the pool of speakers for the PASS 2010 Summit</a>. Allen has proposed that in order to bring in more speakers, we limit things to 1 session per speaker. With 168 sessions across the board, that&#8217;s a lot of potential speakers. Currently, we limit things to 2 sessions per speaker.</p>
<p>What are your thoughts?</p>
<p>This poll will close on Thursday, March 18 at 8AM EST and I&#8217;ll publish the results in a separate blog post.</p>
Note: There is a poll embedded within this post, please visit the site to participate in this post's poll.
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=fSzA4onSz1s:uhGipgRRE3k:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=fSzA4onSz1s:uhGipgRRE3k:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=fSzA4onSz1s:uhGipgRRE3k:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=fSzA4onSz1s:uhGipgRRE3k:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=fSzA4onSz1s:uhGipgRRE3k:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=fSzA4onSz1s:uhGipgRRE3k:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=fSzA4onSz1s:uhGipgRRE3k:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/fSzA4onSz1s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/03/12/how-can-we-grow-the-pool-of-summit-speakers/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/03/12/how-can-we-grow-the-pool-of-summit-speakers</feedburner:origLink></item>
		<item>
		<title>Pay Attention</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/MMrV63XNBIU/pay-attention</link>
		<comments>http://facility9.com/2010/03/09/pay-attention#comments</comments>
		<pubDate>Tue, 09 Mar 2010 13:45:39 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[nonsense]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[awesome]]></category>
		<category><![CDATA[shut your cake hole and pay attention]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1394</guid>
		<description><![CDATA[What are you doing right now? How many different things are you trying to balance? Stop all of them and pay attention. No, seriously, do it. Nobody is going to die in the next five minutes. Unless you&#8217;re in surgery or something. In which case go do your job.
I&#8217;m here reminding you that you need [...]]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_1397" class="wp-caption alignright" style="width: 210px"><a href="http://facility9.com/files/2010/03/divorabi.jpg"><img src="http://facility9.com/files/2010/03/divorabi.jpg" alt="Suck it, Gilgamesh!" title="divorabi" width="200" height="249" class="size-full wp-image-1397" /></a><p class="wp-caption-text">Are we not men? No, we are Hammurabi!</p></div>What are you doing right now? How many different things are you trying to balance? Stop all of them and pay attention. No, seriously, do it. Nobody is going to die in the next five minutes. Unless you&#8217;re in surgery or something. In which case go do your job.</p>
<p>I&#8217;m here reminding you that you need to pay attention.</p>
<p>This isn&#8217;t like in Middle School history when you were learning about the Epic of Gilgamesh and how he killed a demi-god with the help of a hairy little man and together they survive watching the movie Ishtar and end up wearing a cow&#8217;s ass as a hat or something. Did you pay attention to that story? Yeah, me neither. This is nothing like that.</p>
<p>I&#8217;ve noticed something that bothers me &#8211; we constantly distract ourselves. People are always on the phone or listening to music or basically not paying attention. Stop it.</p>
<h3>Breathe</h3>
<p>Take a deep breath and let it out slowly. Breathe in. Breathe out. Fill up your lungs, focus on breathing. </p>
<p>Do you feel that? That&#8217;s you calming your tiny little primate brain and making it pay attention to one very simple thing that it already does on its own. Feels good, doesn&#8217;t it?</p>
<p>Keeping doing for a bit. Focus on your breathing. If you drift off for a second, just focus on your breathing. Your mind is still there, you just shifted your focus. This page will still be here when you get frustrated.</p>
<h3>Think</h3>
<p>What&#8217;s the point of this?</p>
<p>Honestly, the point was to get you to stop for a minute.</p>
<p>Think about how often you&#8217;re constantly worried about what to do next. Think about how often you&#8217;re thinking about a meeting you had earlier in the week, an argument, or anything else that happened in the past. You think about the past and the future a lot, don&#8217;t you?</p>
<p>Now, think about how much time you spend focusing on right now. Be really honest with yourself. I bet it&#8217;s not a lot.</p>
<p><div id="attachment_1398" class="wp-caption alignright" style="width: 160px"><a href="http://facility9.com/files/2010/03/no-you.jpg"><img src="http://facility9.com/files/2010/03/no-you.jpg" alt="Have you smelled this finger?" title="no-you" width="150" height="189" class="size-full wp-image-1398" /></a><p class="wp-caption-text">This is really mature, guys.</p></div>We constantly distract ourselves. I have friends who listen to books while they run because running is boring. People talk on their phones while they shop and drive because it&#8217;s boring. People will do anything to distract themselves from the task at hand because it&#8217;s boring.</p>
<p><strong>You&#8217;re boring.</strong></p>
<p>Did you perk up and pay attention just now? I thought so. You probably aren&#8217;t boring. You&#8217;re probably a fascinating person with diverse and varied interests and I&#8217;m sorry if I hurt your feelings, but you&#8217;re boring the shit out of me. Fact: life is not full of roller coasters and orgasms. Sometimes you have to peel potatoes. When you&#8217;re peeling the potatoes, peel the potatoes. Don&#8217;t think about how you&#8217;re going to have pie for dessert or how your 14 disk box set of Quantum Leap is going to come in the mail in a few days. Just peel the potatoes.</p>
<h3>Be</h3>
<blockquote><p>Zen students are with their masters at least ten years before the presume to teach others. Nan-in was visited by Tenno, who, having passed his apprenticeship, had become a teacher. The day happened to be rainy, so Tenno wore wooden clogs and carried an umbrella. After greeting him, Nan-in remarked &#8220;I suppose you left your wooden clogs in the vestibule. I want to know if your umbrella is on the right or left side of the clogs.&#8221;</p>
<p>Tenno, confused, had no instant answer. He realized that he was unable to carry his Zen every minute. He became Nan-in&#8217;s pupil, and he studied six more years to accomplish his every-minute Zen.</p>
<p><em>from Zen Flesh Zen Bones, compiled by Paul Reps and Nyogen Senzaki</em></p></blockquote>
<p>To put it another way &#8211; an ordained monk was so humbled by his own inattention that he once again became a student. We all slip up, but if you try you can manage to pay a little bit more attention to what you&#8217;re doing. Take pleasure in the things you&#8217;re doing. When it&#8217;s time to peel the potatoes, peel the potatoes. When it&#8217;s time to indulge in your Margaret Thatcher fetish, don&#8217;t call me.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=MMrV63XNBIU:GIzF13GiWsQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=MMrV63XNBIU:GIzF13GiWsQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=MMrV63XNBIU:GIzF13GiWsQ:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=MMrV63XNBIU:GIzF13GiWsQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=MMrV63XNBIU:GIzF13GiWsQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=MMrV63XNBIU:GIzF13GiWsQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=MMrV63XNBIU:GIzF13GiWsQ:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/MMrV63XNBIU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/03/09/pay-attention/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/03/09/pay-attention</feedburner:origLink></item>
		<item>
		<title>T-SQL Tuesday 4: Io, Io, it’s off to disk we go</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/3-ewIWv0elk/t-sql-tuesday-4-io-io-its-off-to-disk-we-go</link>
		<comments>http://facility9.com/2010/03/09/t-sql-tuesday-4-io-io-its-off-to-disk-we-go#comments</comments>
		<pubDate>Tue, 09 Mar 2010 12:47:16 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[nonsense]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[exploding head trauma is kinky]]></category>
		<category><![CDATA[goats]]></category>
		<category><![CDATA[hackery]]></category>
		<category><![CDATA[omgponies]]></category>
		<category><![CDATA[t-sql tuesday]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1409</guid>
		<description><![CDATA[Io was a nymph. True story. Apparently, her father was some kind of river god. In modern times that means you&#8217;re likely to catch fire. Back in the days when the Greeks were in charge of things being a river god meant that you were somebody (the Greeks thought the earth was a giant brass [...]]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_1407" class="wp-caption alignright" style="width: 155px"><a href="http://facility9.com/files/2010/03/sex_in_the_cloud.jpg"><img src="http://facility9.com/files/2010/03/sex_in_the_cloud.jpg" alt="" title="sex_in_the_cloud" width="145" height="344" class="size-full wp-image-1407" /></a><p class="wp-caption-text">Fact: the earliest recorded use of cloud computing was ancient Greek porn</p></div>Io was a nymph. True story. Apparently, her father was some kind of river god. In modern times that means you&#8217;re likely to <a href='http://www.ohiohistorycentral.org/images/11-3-52.jpg' target='_blank'>catch fire</a>. Back in the days when the Greeks were in charge of things being a river god meant that you were <em>somebody</em> (the Greeks thought the earth was a giant brass plate floating a huge river, all of which was created by perverts who lived on top of a mountain). So, apparently Io&#8217;s dad was important.</p>
<p>Anyway, it is rumored that Io was attractive. So attractive, in fact, that Zeus, lord of the perverts, saw her taking a bath and got more than a little bit aroused. Zeus then behaved in a way that would end up in a savage beating and restraining order back where I come from &#8211; he pestered Io for nookie until her father drove her out of the house &#8211; probably because some horny lunatic who could <a href='http://www.conceptart.org/forums/attachment.php?attachmentid=385302&amp;stc=1&amp;d=1212722267' target='_blank'>shoot children</a> <a href='http://www.softassteel.com/myth/story3/7.jpg' target='_blank'>out of his forehead</a> was bothering his daughter. Io, being a bit strange in the head, relented. Or something. My records aren&#8217;t 100% clear seeing as how they&#8217;ve been written on pottery. The point is that Zeus turned into a giant cloud and turned Io into a cow (no, your hooves don&#8217;t make you look fat).</p>
<p>Somehow Zeus&#8217;s wife got involved and there was bondage involving a cow tied to a tree or something. Eventually Io gets turned back into a real live girl and gives birth to Zeus&#8217;s son. Which brought about an ethics probe into cross-species cloning.</p>
<p>Disk&#8230; disk&#8230; oh yeah I already mentioned that the ancient Greeks were clearly insane and thought that the world was a giant metal plate floating on a huge river name Oceanus all of it encased in a hemisphere with clouds and the sun and the moon and stuff painted all over the inside of the hemisphere. </p>
<p>What&#8217;s outside of the hemisphere? Shut up, that&#8217;s what. It&#8217;s <a href='http://www.condoroptions.com/wp-content/uploads/2008/10/turtles-all-the-way-down.jpg' target='_blank'>turtles all the way down</a>.</p>
<p>There&#8217;s a bit of humor thrown into your <a href='http://www.straightpathsql.com/archives/2010/03/invitation-for-t-sql-tuesday-004-io/' target='_blank'>T-SQL Tuesday</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=3-ewIWv0elk:yI8k7Rmbpzc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=3-ewIWv0elk:yI8k7Rmbpzc:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=3-ewIWv0elk:yI8k7Rmbpzc:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=3-ewIWv0elk:yI8k7Rmbpzc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=3-ewIWv0elk:yI8k7Rmbpzc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=3-ewIWv0elk:yI8k7Rmbpzc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=3-ewIWv0elk:yI8k7Rmbpzc:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/3-ewIWv0elk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/03/09/t-sql-tuesday-4-io-io-its-off-to-disk-we-go/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/03/09/t-sql-tuesday-4-io-io-its-off-to-disk-we-go</feedburner:origLink></item>
		<item>
		<title>My MacGyver Moment</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/7e8V4sfu-rI/my-macgyver-moment</link>
		<comments>http://facility9.com/2010/03/02/my-macgyver-moment#comments</comments>
		<pubDate>Tue, 02 Mar 2010 14:00:41 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[Application Development]]></category>
		<category><![CDATA[hackery]]></category>
		<category><![CDATA[omgponies]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1385</guid>
		<description><![CDATA[David Stein started this current blog meme. He passed the buck on to Brent Ozar, who shared a horrifying tale of his time in the trenches as a developer. Brent then thoughtfully pointed at me and demanded that I carry on the blog meme torch.
Blog memes are great. They give me an opportunity to pretend [...]]]></description>
			<content:encoded><![CDATA[<p>David Stein started this current <a href="http://www.made2mentor.com/2010/02/macgyver-moments/">blog meme</a>. He passed the buck on to Brent Ozar, who shared a horrifying tale of <a href="http://www.brentozar.com/archive/2010/02/my-macgyver-moment-meme-by-made2mentor/">his time in the trenches as a developer</a>. Brent then thoughtfully pointed at me and demanded that I carry on the blog meme torch.</p>
<p>Blog memes are great. They give me an opportunity to pretend to be inventive and creative, take someone else&#8217;s great idea and spin it in a centrifuge to extract the good stuff and then pass the detritus along to someone else to deal with. As a career developer turned developer berating apparatus, I have seen my fair share of cobbled together dung heaps. In fact, I would be <strong>proud</strong> to have someone call some of my solutions a cobbled together dung heap.</p>
<h3 id="bad_process_just_add_software">Bad Process? Just Add Software</h3>
<p>Many years ago I was asked to put together a simple proof of concept application showing code movement using VSS automation. The phrase &#8220;simple proof of concept&#8221; should have sent me running. Of course, I&#8217;m assuming that the me of 5 years ago had any sense in his head.</p>
<p>I&#8217;ll back up a minute and let you see the whole situation. This organization had a complex development lifecycle. Developers were frequently developing several releases into the future in a combination of major and minor releases. Hot fixes would go out in production and when the next major release went out the icon be cornflower blue but the hot fix would be nowhere to be found. The hot fix would be hot fixed into production and the icon would be back to alice blue. The situation was, in short, a nightmare. What makes the nightmare worse was that it was a process nightmare: development practices in this organization dictated that multiple releases be developed simultaneously <em>by separate teams</em>. </p>
<p>Think about complex, line of business, software. Important software. Software that is core to your business. Imagine that three separate teams of developers are actively developing new features and fixes at the same time in three separate source trees. This is exactly what was going on at this organization. My job was to automate the problem away with software.</p>
<h3 id="bad_software_just_add_more_software">Bad Software? Just Add More Software</h3>
<p>This organization was heavily invested in using Visual Source Safe. For those of you young enough to have worked with modern version control systems (such as a team of scribes working around the clock), let me tell you about VSS. VSS exists entirely on the client computer. VSS&#8217;s source control mojo operates through a network share using a combination of black magic and pure luck. Like all things that work with luck, it fails. It is safer to print your source code, shred it, and burn the paper shreds that to keep your code in VSS.</p>
<p>Despite the pain of VSS, VSS was the platform. How do you automate a platform when there is no server-side component? You install a VSS client on a server and you begin automating it. Thankfully VSS supplied an API &#8211; a poorly documented COM+ API. </p>
<p>I created a proof of concept application that showed code motion through various stages of development in VSS. The client was happy. The client signed a statement of work. We took their money and strode purposefully towards what appeared to be a set of rotating blades.</p>
<p>As the project unfolded it became very apparent that no amount of software could solve this problem. The problem was process, not software. Valiantly, foolishly, 26ishly, I soldiered forward. I worked 14 hour days. I build a cobbled together GUI that attempted to model a software development process that was beyond complicated. The GUI was cumbersome to use and brittle to code. A small change in one line of code meant that 17 other bugs showed up in various parts of the program. There were easily 100,000 lines of code in what should have been a simple management application. Edge cases lead to other edge cases. After one marathon 24 hour programming session (after four 18 hour days) the GUI tool finally worked. The users could configure a process. A process that potentially didn&#8217;t work.</p>
<h3 id="throwing_worse_code_after_bad">Throwing Worse Code After Bad</h3>
<p>The actual automation was a supposed to be easy. The users could apply VSS labels and the automated software would, in theory, pick up the changes within 15 minutes. The automated software would pick up the changes on a regular basis but it frequently exploded in a fiery error when confronted with real world problems. When two teams are actively developing against the same code base, code merges don&#8217;t go very well. </p>
<p>The process was intrinsically human but the client wanted automation. Being young and stupid, I didn&#8217;t know enough to say no. I cobbled together a working knowledge of text parsing and attempted out outfox the people who wrote the VSS Merge Tool. Armed with a fistful of academic papers, articles, and APIs I attempted to build a better merge tool using existing libraries. </p>
<p>At the end of the day, the tool built a log of errors using the unified diff format (which no human can read), collected the log and emailed a copy of it to the developers who committed the conflicting files. Or, it would have had anyone used the software.</p>
<h3 id="didn8217t_you_read_the_manual">Didn&#8217;t You Read the Manual</h3>
<p>I actually wrote a software manual. It was actually a good manual. Want to know how I know? I gave the manual to the project manager and had him create instructional videos. They worked.</p>
<p>The project sponsor was promoted before the project was completed. The primary users transferred to another department. The new users were too busy to read the manual and expected the software to work easily and obviously. Who wouldn&#8217;t, right?</p>
<p>The GUI tool looked like the directory structure in VSS, but it didn&#8217;t reflect the changes in VSS, it simply let the users configure how the tool should behave. Sound confusing? It was.</p>
<p>At the end of the day, I had written a complicated manual for a complex piece of software that <em>actually</em> worked. It was a cobbled together solution built out of several hundred thousand lines of buggy .NET 1.1 code sitting on top of a buggy COM+ API intended to solve a buggy process. It&#8217;s a miracle that this software abomination wasn&#8217;t fueled by the shattered dreams of orphans.</p>
<h3 id="silent_rage_would_be_better_than_this">Silent Rage Would Be Better Than This</h3>
<p>I said that was the end of the day. It wasn&#8217;t. I got one support call about the product about 3 months after it had been delivered, signed off, and paid for. I went back to the client&#8217;s location and sat down with the current team to learn their problems. None of them knew how to use the software. No original team members were around who had been involved in the original project. All of the original documentation had been lost in some kind of bit rot tar pit. </p>
<p>My beautiful, cobbled together, duct tape and baling wire solution would never see the light of day. It may have been ugly, but it worked. There&#8217;s nothing like feeling the triumph of having saved the day and then having that day get flushed right down the toilet.</p>
<h3 id="calling_other_macgyvers">Calling Other MacGyvers</h3>
<p>Since Brent Ozar stole my default victim, <a href="http://ihumanable.com">Matt Nowack</a>, I&#8217;m going to have to find more victims. I&#8217;m going to point the finger of shame at <a href="http://tjaybelt.blogspot.com/">TJay Belt</a>, <a href="http://scarydba.wordpress.com">Grant Fritchey</a>, and <a href="http://www.enginerding.com/">Alex Moore</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=7e8V4sfu-rI:Fba3zIHsPSg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=7e8V4sfu-rI:Fba3zIHsPSg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=7e8V4sfu-rI:Fba3zIHsPSg:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=7e8V4sfu-rI:Fba3zIHsPSg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=7e8V4sfu-rI:Fba3zIHsPSg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=7e8V4sfu-rI:Fba3zIHsPSg:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=7e8V4sfu-rI:Fba3zIHsPSg:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/7e8V4sfu-rI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/03/02/my-macgyver-moment/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/03/02/my-macgyver-moment</feedburner:origLink></item>
		<item>
		<title>Rounding to the Nearest X Minutes, the Lazy Way</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/e6TjKoPCLIs/rounding-to-the-nearest-x-minutes</link>
		<comments>http://facility9.com/2010/02/24/rounding-to-the-nearest-x-minutes#comments</comments>
		<pubDate>Wed, 24 Feb 2010 18:00:57 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[Application Development]]></category>
		<category><![CDATA[sql refactoring]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1368</guid>
		<description><![CDATA[A lot of people use calendar tables. I&#8217;ve blogged about it before. They&#8217;re incredibly helpful. Now, have you ever needed a table of minutes?
You&#8217;re probably asking, &#8220;Jeremiah, why the heck would I ever need a table of minutes?&#8221; Well, dear reader, I&#8217;m going to tell you that. Please stop interrupting.
Let&#8217;s say you have a report. [...]]]></description>
			<content:encoded><![CDATA[<p>A lot of people use calendar tables. I&#8217;ve blogged about it before. They&#8217;re incredibly helpful. Now, have you ever needed a table of minutes?</p>
<p>You&#8217;re probably asking, &#8220;Jeremiah, why the heck would I ever need a table of minutes?&#8221; Well, dear reader, I&#8217;m going to tell you that. Please stop interrupting.</p>
<p>Let&#8217;s say you have a report. This report shows the sum of sales per 5 minute increment. You could do a lot of trickery with math to make this report happen, doing things like this to get the 5 minute interval:</p>
<pre lang='tsql' class="brush:tsql">
SELECT
    (DATEPART(mi, CAST('2009-01-01 00:01:00' as datetime))+4) / 5 * 5 AS [05]
</pre>
<p>It works, but it&#8217;s ugly as sin. I said to myself, &#8220;Self, there has to be a better way.&#8221; Turns out that there is a better way: table valued functions! </p>
<p>I created a table valued function to return 60 rows, one for each minute. It also rounds to the nearest 5, 10, 15, and 30 minute intervals. This makes it possible to change the reporting interval very easily by using a join. Check it out:</p>
<pre lang='tsql' class="brush:tsql">
SELECT DATEPART(hh, s.SaleTime) AS TheHour,
  mt.Five AS NearestFive,
  SUM(s.SalesAmount) AS AmountSold
FROM dbo.Sales AS s
INNER JOIN dbo.MinutesTable() AS mt ON DATEPART(mi, s.SaleTime) = mt.[Minute]
WHERE -- something is true
GROUP BY DATEPART(hh, s.SaleTime), mt.Five
</pre>
<p>Why do I call this the lazy way to do this? Because now that I&#8217;ve written it once I never have to do it again. I can add new columns to dbo.MinutesTable() without having to worry about breaking anything or copying code incorrectly from one query to another.</p>
<p>Here&#8217;s the code to create the function:</p>
<pre lang='tsql' class="brush:tsql">
CREATE FUNCTION dbo.MinutesTable ()
RETURNS @minutes TABLE (
  [Minute] TINYINT,
  Five TINYINT,
  Ten TINYINT,
  Fifteen TINYINT,
  Thirty TINYINT
)
AS BEGIN

INSERT INTO @minutes VALUES (0,60,60,60,60)
                            (1,5,10,15,30),
                            (2,5,10,15,30),
                            /* you get the gist of it */
                            (59,60,60,60,60);

RETURN ;

END
</pre>
<p><strong>Update:</strong> Thanks to Brad Schulz this has gone for a single post about my laziness to an example of a refactoring you can make. If you ever see a table being generated like this, you can take a look at it and determine how you can change it into an inline select. The query optimizer is going to do something completely different for each plan. With the inline select, SQL Server is able to determine that there are 60 rows in our table and can build a much more efficient execution plan.</p>
<pre lang='tsql' class="brush:tsql">
CREATE FUNCTION [dbo].[MinutesTable] ()
RETURNS TABLE
AS 

RETURN
  SELECT  0 AS [Minute], 60 AS Five, 50 AS Ten, 60 AS Fifteen, 60 AS Thirty
  UNION ALL
  SELECT  1, 5, 10, 15, 30
  UNION ALL
  /* ... this still makes sense, right? ... */
  UNION ALL
  SELECT  59, 60, 60, 60, 60 ;
GO
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=e6TjKoPCLIs:pB2VnzmJUXg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=e6TjKoPCLIs:pB2VnzmJUXg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=e6TjKoPCLIs:pB2VnzmJUXg:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=e6TjKoPCLIs:pB2VnzmJUXg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=e6TjKoPCLIs:pB2VnzmJUXg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=e6TjKoPCLIs:pB2VnzmJUXg:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=e6TjKoPCLIs:pB2VnzmJUXg:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/e6TjKoPCLIs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/02/24/rounding-to-the-nearest-x-minutes/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/02/24/rounding-to-the-nearest-x-minutes</feedburner:origLink></item>
		<item>
		<title>A Simple Refactoring – Functions in the WHERE Clause</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/xJdyiT8-jCk/a-simple-refactoring-functions-in-the-where-clause</link>
		<comments>http://facility9.com/2010/02/17/a-simple-refactoring-functions-in-the-where-clause#comments</comments>
		<pubDate>Wed, 17 Feb 2010 14:00:22 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[performance tuning]]></category>
		<category><![CDATA[sql refactoring]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1350</guid>
		<description><![CDATA[Putting functions in the where clause of a SQL Statement can cause performance problems. If you aren&#8217;t careful, these problems can add up and bring a powerful production system to its knees.
For this example, I&#8217;m using the Northwind database, but you could do this on any database.
The first thing to do is put an index [...]]]></description>
			<content:encoded><![CDATA[<p>Putting functions in the where clause of a SQL Statement can cause performance problems. If you aren&#8217;t careful, these problems can add up and bring a powerful production system to its knees.</p>
<p>For this example, I&#8217;m using the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46A0-8DA2-EEBC53A68034&amp;displaylang=en" target="_blank">Northwind</a> database, but you could do this on any database.</p>
<p>The first thing to do is put an index on the OrderDate column:</p>
<pre class="brush:tsql">CREATE INDEX IX_Orders_OrderDate
ON dbo.Orders (OrderDate) ;</pre>
<p>Take a look at this first query:</p>
<pre class="brush:tsql">
SELECT  COUNT(*)
FROM    dbo.Orders AS o
WHERE   DATEADD(MM, 2, o.OrderDate) &lt; &#039;1997-05-04&#039; ;
</pre>
<p><div id="attachment_1351" class="wp-caption alignright" style="width: 160px"><a href="http://facility9.com/files/2010/02/date_scan.jpg"><img src="http://facility9.com/files/2010/02/date_scan-150x132.jpg" alt="" title="date_scan" width="150" height="132" class="size-thumbnail wp-image-1351" /></a><p class="wp-caption-text">Scanning the stars... or something.</p></div>This returns very quickly on the Northwind database because we have such a small volume of data, but a query like this could cause a lot of problems in production. Why? Well, it&#8217;s doing a full table scan. Don&#8217;t believe me? Take a look a the execution plan over there.</p>
<p>The database is forcing a table scan because of the use of the DATEADD function on an indexed column. SQL Server will have to compute the value of every OrderDate plus 2 months in the database and then compare it to May 4th, 1997. </p>
<p>What happens if we flip this around? What if we change our query so that we&#8217;re doing the math on our input value of May 4th, 1997?</p>
<pre class="brush:tsql">
SELECT  COUNT(*)
FROM    dbo.Orders AS o
WHERE   o.OrderDate &lt; DATEADD(MM, -2, &#039;1997-05-04&#039;) ;
</pre>
<p><div id="attachment_1352" class="wp-caption alignright" style="width: 160px"><a href="http://facility9.com/files/2010/02/date_seek.jpg"><img src="http://facility9.com/files/2010/02/date_seek-150x132.jpg" alt="" title="date_seek" width="150" height="132" class="size-thumbnail wp-image-1352" /></a><p class="wp-caption-text">Seek and ye shall find</p></div>It turns out that if we move the function from the table to the variable (although it&#8217;s really inlined in this case) we can get SQL Server to perform an index seek. This is going to be orders of magnitude faster than scanning every row in the table and comparing the values. </p>
<p>So, there you have it: another easy fix that can save you a lot of headache when you&#8217;re trying to tune queries.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=xJdyiT8-jCk:uA3ycgP_6vg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=xJdyiT8-jCk:uA3ycgP_6vg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=xJdyiT8-jCk:uA3ycgP_6vg:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=xJdyiT8-jCk:uA3ycgP_6vg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=xJdyiT8-jCk:uA3ycgP_6vg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=xJdyiT8-jCk:uA3ycgP_6vg:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=xJdyiT8-jCk:uA3ycgP_6vg:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/xJdyiT8-jCk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/02/17/a-simple-refactoring-functions-in-the-where-clause/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/02/17/a-simple-refactoring-functions-in-the-where-clause</feedburner:origLink></item>
		<item>
		<title>Installing PostgreSQL on Mac OS X</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/OtOQOTjfavM/installing-postgresql-on-mac-os-x</link>
		<comments>http://facility9.com/2010/02/15/installing-postgresql-on-mac-os-x#comments</comments>
		<pubDate>Mon, 15 Feb 2010 14:00:45 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[OS X]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1344</guid>
		<description><![CDATA[This is a pretty simple process, but one that I thought I would document because I ran into a few gotchas along the way.
I originally installed OS X using the one click installer from EnterpriseDB. Unfortunately, the installer hung while attempting to finish the installation process and they only thing to do was to roll [...]]]></description>
			<content:encoded><![CDATA[<p>This is a pretty simple process, but one that I thought I would document because I ran into a few gotchas along the way.</p>
<p>I originally installed OS X using the one click installer from EnterpriseDB. Unfortunately, the installer hung while attempting to finish the installation process and they only thing to do was to roll back the install. I attempted to build from macports, but that proved to be a huge pain in my ass and reminded me a little bit too much of using Linux, so I scrapped that idea as well. I started browsing the EnterpriseDB installation notes and came across an unattended install. Since my installation failed trying to launch the final interactive stage of the installation, I said to myself &#8220;Self, I bet we should try this.&#8221;</p>
<ol>
<li>Download PostgreSQL from EnterpriseDB <a href='http://www.enterprisedb.com/products/pgdownload.do#osx' target='_blank'>http://www.enterprisedb.com/products/pgdownload.do#osx</a></li>
<li>Mount the OS X disk image file</li>
<li>In the Terminal, change to the directory where the image file was mounted:<br />
<code> cd /Volumes/PostgreSQL\ 8.4.2-1/</code></li>
<li>Start the unattended installation<br />
<code> sudo ./postgresql-8.4.2-1-osx.app/Contents/MacOS/installbuilder.sh<br />
  --mode unattended</code></li>
<li>Once the installation has finished, add the following line to your .profile:<br />
<code>source /Library/PostgreSQL/8.4/pg_env.sh</code><br />
If you&#8217;ve never created your .profile you can do the following in a terminal window:</p>
<ol>
<li><code>touch ~/.profile</code><br />This will create the file if it doesn&#8217;t exist and will only change the last modification date if it does.</li>
<li><code>open /Applications/TextEdit.app .profile</code><br />This opens your .profile in the TextEdit application</li>
</ol>
</li>
<li>Save and close your .profile</li>
<li>Create a new database user.<br />
<code>createuser [YOUR NAME HERE] --pwprompt --username=postgres</code><div id="attachment_1346" class="wp-caption alignnone" style="width: 525px"><a href="http://facility9.com/files/2010/02/pg-new-user.jpg"><img src="http://facility9.com/files/2010/02/pg-new-user.jpg" alt="Alt text for the image, e.g. “The Mona Lisa”" title="pg-new-user" width="515" height="368" class="size-full wp-image-1346" /></a><p class="wp-caption-text">This could be anyone...</p></div></li>
<li>When you&#8217;re prompted for the &#8220;Password:&#8221;, use &#8220;postgres&#8221;. This is the default password for the postgres superuser. Because you&#8217;ve just created another superuser, you&#8217;ll never have to touch this account again, but you should probably look up some <a href="http://www.postgresql.org/docs/8.4/interactive/index.html" target="_blank">fantastic documentation</a> and learn how to change the password.<div id="attachment_1345" class="wp-caption alignnone" style="width: 516px"><a href="http://facility9.com/files/2010/02/pg-new-user-success.jpg"><img src="http://facility9.com/files/2010/02/pg-new-user-success.jpg" alt="" title="pg-new-user-success" width="506" height="367" class="size-full wp-image-1345" /></a><p class="wp-caption-text">I'm a real live boy!</p></div></li>
</ol>
<p>There you have it: how to set up and install PostgreSQL on OS X. If you want to continue forward and install a Ruby library to interact with PostgreSQL, just type<br />
<code>sudo gem install postgres-pr</code> to install the pure Ruby version PostgreSQL driver. If you want to install one of the C-based drivers, you&#8217;ll need to mess around with macports.</p>
<p><em>Note:</em> EnterpriseDB make and distribute a binary version of PostgreSQL for a variety of platforms. In addition, they provide paid support and also offer a variety of enterprise features. They have in no way paid me for this post.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=OtOQOTjfavM:yvN3lZ7w53c:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=OtOQOTjfavM:yvN3lZ7w53c:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=OtOQOTjfavM:yvN3lZ7w53c:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=OtOQOTjfavM:yvN3lZ7w53c:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=OtOQOTjfavM:yvN3lZ7w53c:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=OtOQOTjfavM:yvN3lZ7w53c:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=OtOQOTjfavM:yvN3lZ7w53c:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/OtOQOTjfavM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/02/15/installing-postgresql-on-mac-os-x/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/02/15/installing-postgresql-on-mac-os-x</feedburner:origLink></item>
		<item>
		<title>Links for the Week – 2010.02.12</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/YyUTxsbRMjo/links-for-the-week-2010-02-12</link>
		<comments>http://facility9.com/2010/02/13/links-for-the-week-2010-02-12#comments</comments>
		<pubDate>Sat, 13 Feb 2010 17:00:35 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[nonsense]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1338</guid>
		<description><![CDATA[This is more of a &#8220;what I&#8217;ve been reading&#8221; rather than a link dump from previous week&#8217;s RSS feed. 
A Plea for Plain English &#8211; Tony Davis&#8217;s &#8220;A Plea for Plain English&#8221; rings home with me. Far too much writing is full of heavy, pompous words used purely to make the author feel smarter. Joseph [...]]]></description>
			<content:encoded><![CDATA[<p>This is more of a &#8220;what I&#8217;ve been reading&#8221; rather than a link dump from previous week&#8217;s RSS feed. </p>
<p><a href='http://www.simple-talk.com/community/blogs/tony_davis/archive/2010/02/05/89543.aspx' target='<br />
_blank'>A Plea for Plain English</a> &#8211; Tony Davis&#8217;s &#8220;A Plea for Plain English&#8221; rings home with me. Far too much writing is full of heavy, pompous words used purely to make the author feel smarter. <a href='http://en.wikipedia.org/wiki/Joseph_Conrad' target='_blank'>Joseph Conrad</a> &#8211; one of the greatest writers of the English language &#8211; was not a native speaker. Yet he wrote with a simplicity, grace, and style that is still unequaled. While we all can&#8217;t be Joseph Conrad, we can all strive to write in clear, concise, readable prose. Technical writing doesn&#8217;t need to be dry, writing effective prose can be just as much an art form as creating a brilliant short story, novel, painting, photograph, or song.</p>
<p>I&#8217;ve been getting a lot more interested in mathematics. Not just how they related to computers, but also <a href='http://www.smashingmagazine.com/2010/02/09/applying-mathematics-to-web-design/' target='_blank'>how mathematics relate to design.</a> Design, art, and aesthetics are partially governed by universal principles. There are ratios that are more visually pleasing simply because we find them in nature. Being aware of these ratios helps us create effective designs that draw in the reader and hold them to the content.</p>
<p><a href='http://www.amctv.com/b-movies/scifi/' target='_blank'>B-movies.</a> I watch a lot of old slasher, exploitation, b-movies. </p>
<p><a href='http://www.zeldman.com/2010/02/01/flash-ipad-standards/' target='_blank'>Flash, iPad, Standards</a> &#8211; Jeffrey Zeldman talks about why the total lack of Flash on the iPad is a good thing: it provides an incredibly compelling, public, reason for designers and developers to abandon proprietary formats like Flash and Silverlight and focus on open standards. Some people would argue that a lack of Flash would kill the device but on the flip side what can you do in Flash that people <em>need</em> to do that you can&#8217;t do with JavaScript, HTML, and CSS? Combine that with the in browser relational data storage that HTML5 provides and there is no reason to use a proprietary graphics engine apart from vector graphics bullshittery/professional masturbation.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=YyUTxsbRMjo:EftDVygByiw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=YyUTxsbRMjo:EftDVygByiw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=YyUTxsbRMjo:EftDVygByiw:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=YyUTxsbRMjo:EftDVygByiw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=YyUTxsbRMjo:EftDVygByiw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=YyUTxsbRMjo:EftDVygByiw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=YyUTxsbRMjo:EftDVygByiw:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/YyUTxsbRMjo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/02/13/links-for-the-week-2010-02-12/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/02/13/links-for-the-week-2010-02-12</feedburner:origLink></item>
		<item>
		<title>A Simple Refactoring – Avoiding Table Scans</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/WbeL_dhIgP8/a-simple-refactoring</link>
		<comments>http://facility9.com/2010/02/11/a-simple-refactoring#comments</comments>
		<pubDate>Thu, 11 Feb 2010 15:30:51 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[Application Development]]></category>
		<category><![CDATA[performance tuning]]></category>
		<category><![CDATA[sql refactoring]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1326</guid>
		<description><![CDATA[Refactoring SQL code can be pretty easy. Just like refactoring any other programming language, sometimes you have to look around to find the culprit.
We have a slow running query that frequently times out when run by the users. A quick look at the query told me what was wrong. I found this clause in the [...]]]></description>
			<content:encoded><![CDATA[<p>Refactoring SQL code can be pretty easy. Just like refactoring any other programming language, sometimes you have to look around to find the culprit.</p>
<p>We have a slow running query that frequently times out when run by the users. A quick look at the query told me what was wrong. I found this clause in the middle of an otherwise simple query:</p>
<pre lang='tsql' class="brush:tsql">
        LEFT JOIN (
                   SELECT DISTINCT
                          key,
                          column_a
                   FROM   ImportantData
                   WHERE  FieldName = 'VALUES'
                   UNION ALL
                   SELECT DISTINCT
                          key,
                          column_a
                   FROM   ImportantData_History
                   WHERE  FieldName = 'VALUES'
                  ) AS t ON other.key = t.key
        LEFT JOIN (
                   SELECT DISTINCT
                          key,
                          column_b
                   FROM   ImportantData
                   WHERE  FieldName = 'VALUESXY'
                   UNION ALL
                   SELECT DISTINCT
                          key,
                          column_b
                   FROM   ImportantData_History
                   WHERE  FieldName = 'VALUESXY'
                  ) AS t2 ON other.key = t2.key
</pre>
<p>The problem with this query is that we&#8217;re reading each table twice for the same data. I checked in the execution plan and, sure enough, SQL Server was performing two scans on the underlying data. After some careful thought I realized that I could accomplish the same thing with a single query:</p>
<pre lang='tsql' class="brush:tsql">
        LEFT JOIN (
                   SELECT key,
                          VALUES AS column_a,
                          VALUESXY AS column_b
                   FROM   (
                           SELECT DISTINCT
                                  key,
                                  FieldName,
                                  CASE WHEN FieldName = 'VALUES'
                                       THEN column_a
                                       WHEN FieldName = 'VALUESXY'
                                       THEN column_b
                                  END AS content
                           FROM   ImportantData
                           WHERE  FieldName = 'VALUES'
                                  OR FieldName = 'VALUESXY'
                           UNION ALL
                           SELECT DISTINCT
                                  key,
                                  FieldName,
                                  CASE WHEN FieldName = 'VALUES'
                                       THEN column_a
                                       WHEN FieldName = 'VALUESXY'
                                       THEN column_b
                                  END AS content
                           FROM   ImportantData_History
                           WHERE  FieldName = 'VALUES'
                                  OR FieldName = 'VALUESXY'
                          ) AS source PIVOT( MAX(CONTENT) FOR FieldName IN ([VALUES],
                                                              [VALUESXY]) ) AS pvt
                  ) AS t ON other.key= t.key
</pre>
<p>The upside to this unreadable pile of junk is that it scans each table once and only once. This reduces the load on disk, the amount of data that needs to be read into memory, and it most likely reduces the amount of data stored in memory. And, while this only reduced the estimated query cost by 40 (580 down to 540), we all know that the query cost is only one factor in what actually affects the overall run time of a query.</p>
<p>Many readers are probably mortified that there&#8217;s a SELECT DISTINCT in this query. I am too. That being said, I plucked the low-hanging fruit and managed to get a huge performance boost as a result &#8211; query execution time went from over 1 minute to 14 seconds. With an improvement like that, removing that distinct isn&#8217;t on the radar any more.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=WbeL_dhIgP8:BRF2aiEMueA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=WbeL_dhIgP8:BRF2aiEMueA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=WbeL_dhIgP8:BRF2aiEMueA:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=WbeL_dhIgP8:BRF2aiEMueA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=WbeL_dhIgP8:BRF2aiEMueA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=WbeL_dhIgP8:BRF2aiEMueA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=WbeL_dhIgP8:BRF2aiEMueA:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/WbeL_dhIgP8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/02/11/a-simple-refactoring/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/02/11/a-simple-refactoring</feedburner:origLink></item>
		<item>
		<title>When is a Lookup not a Lookup?</title>
		<link>http://feedproxy.google.com/~r/facility9/~3/vD4ATQH9NRA/when-is-a-lookup-not-a-lookup</link>
		<comments>http://facility9.com/2010/02/02/when-is-a-lookup-not-a-lookup#comments</comments>
		<pubDate>Tue, 02 Feb 2010 06:00:10 +0000</pubDate>
		<dc:creator>Jeremiah Peschka</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[syndication]]></category>
		<category><![CDATA[Application Development]]></category>
		<category><![CDATA[performance tuning]]></category>

		<guid isPermaLink="false">http://facility9.com/?p=1314</guid>
		<description><![CDATA[Execution plans are great things. They give us an insight into how SQL Server is putting together queries and why they run slowly.
One immediate thing I look for in an execution plan is a Key Lookup. In a Key Lookup operation, SQL Server has to reference the clustered index on the table because a value [...]]]></description>
			<content:encoded><![CDATA[<p>Execution plans are great things. They give us an insight into how SQL Server is putting together queries and why they run slowly.</p>
<p>One immediate thing I look for in an execution plan is a Key Lookup. In a Key Lookup operation, SQL Server has to reference the clustered index on the table because a value it&#8217;s looking for is not present in the index that was used to find the row.</p>
<p>Normally, when you look at the Key Lookup, you will see a list of output columns. This is a great way to help you modify your indexes and make sure that you can avoid these extra disk hits by sacrificing a tiny bit of storage space.<br />
<div id="attachment_1315" class="wp-caption alignnone" style="width: 381px"><a href="http://facility9.com/files/2010/02/normal_output_list.png"><img src="http://facility9.com/files/2010/02/normal_output_list.png" alt="" title="normal_output_list" width="371" height="299" class="size-full wp-image-1315" /></a><p class="wp-caption-text">A Normal Output List from a Query Plan</p></div></p>
<p>Today, while troubleshooting a query that is never finishing, I ran across this gem.<br />
<div id="attachment_1316" class="wp-caption alignnone" style="width: 374px"><a href="http://facility9.com/files/2010/02/empty_output_list.png"><img src="http://facility9.com/files/2010/02/empty_output_list.png" alt="" title="empty_output_list" width="364" height="328" class="size-full wp-image-1316" /></a><p class="wp-caption-text">Empty. Bereft of Meaning. Nothing.</p></div></p>
<p>There&#8217;s no output list in the Key Lookup. I, wrongly, thought that Key Lookups would always include an output list. What&#8217;s going on here?</p>
<p>Well, here&#8217;s the scoop. I have the following, sample, table:</p>
<pre lang='tsql' class="brush:tsql">
CREATE TABLE dbo.ServiceList (
  ServiceListId BIGINT NOT NULL PRIMARY KEY,
  BillId BIGINT NOT NULL,
  ServiceMonth DATETIME
);
</pre>
<p>In this query, ServiceList is referenced through a CROSS APPLY&#8217;d inline function. The inline function references the BillId and ServiceListId. There&#8217;s an index on ServiceList that contains both of these columns:</p>
<pre lang='tsql' class="brush:tsql">
CREATE INDEX IX_ServiceList_BillId ON dbo.ServiceList
(
  BillId
)
INCLUDE (ServiceListId, ServiceMonth);
</pre>
<p>This index is correctly being used by the query optimizer but in the past it&#8217;s only been used to perform lookups and push data to screen (or somewhere). So, what we&#8217;re seeing here makes sense. The CROSS APPLY needs to reference the BillId so the compiler checks the situation out and decides to use IX_ServiceList_BillId in order get the BillId. Since the index only includes ServiceListId, it has to perform a Key Lookup. </p>
<blockquote><p><strong>Protip:</strong> included data is only included in the index; it is not indexed.</p></blockquote>
<p>To avoid this kind of behavior, I need to change this index to actually index on the combination of BillId and ServiceListId like so:</p>
<pre lang='tsql' class="brush:tsql">
CREATE INDEX IX_ServiceList_BillId ON dbo.ServiceList
(
  BillId,
  ServiceListId
)
INCLUDE (ServiceMonth);
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/facility9?a=vD4ATQH9NRA:w5TCYBc-mX0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/facility9?i=vD4ATQH9NRA:w5TCYBc-mX0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=vD4ATQH9NRA:w5TCYBc-mX0:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/facility9?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=vD4ATQH9NRA:w5TCYBc-mX0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/facility9?i=vD4ATQH9NRA:w5TCYBc-mX0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/facility9?a=vD4ATQH9NRA:w5TCYBc-mX0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/facility9?i=vD4ATQH9NRA:w5TCYBc-mX0:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/facility9/~4/vD4ATQH9NRA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://facility9.com/2010/02/02/when-is-a-lookup-not-a-lookup/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://facility9.com/2010/02/02/when-is-a-lookup-not-a-lookup</feedburner:origLink></item>
	</channel>
</rss>
