<?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>The Build</title>
	<atom:link href="http://thebuild.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://thebuild.com/blog</link>
	<description>programming, etc.</description>
	<lastBuildDate>Fri, 18 May 2012 14:08:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Running PostgreSQL on AWS</title>
		<link>http://thebuild.com/blog/2012/05/18/running-postgresql-on-aws/</link>
		<comments>http://thebuild.com/blog/2012/05/18/running-postgresql-on-aws/#comments</comments>
		<pubDate>Fri, 18 May 2012 14:08:49 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=405</guid>
		<description><![CDATA[My presentation from PGCon 2012, PostgreSQL on AWS with Reduced Tears, is now up.
]]></description>
			<content:encoded><![CDATA[<p>My presentation from PGCon 2012, <a href="http://thebuild.com/presentations/pg-aws.pdf">PostgreSQL on AWS with Reduced Tears</a>, is now up.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/05/18/running-postgresql-on-aws/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Of Pickups and Tractor-Trailers</title>
		<link>http://thebuild.com/blog/2012/04/25/of-pickups-and-tractor-trailers/</link>
		<comments>http://thebuild.com/blog/2012/04/25/of-pickups-and-tractor-trailers/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 02:30:59 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=400</guid>
		<description><![CDATA[Pickup trucks are great.

No, really. They are great vehicles. You can use them for all sorts of really useful things: Bringing your tools out to a construction gig. Delivering refrigerators. Helping your friend move a sofa. Carting away a reasonable amount of construction debris.

But if you need to deliver 75,000 pounds of steel beams to [...]]]></description>
			<content:encoded><![CDATA[<p>Pickup trucks are great.</p>

<p>No, really. They are great vehicles. You can use them for all sorts of really useful things: Bringing your tools out to a construction gig. Delivering refrigerators. Helping your friend move a sofa. Carting away a reasonable amount of construction debris.</p>

<p>But if you need to deliver 75,000 pounds of steel beams to a construction site, in a single run? A pickup truck will not do it. Not even a big pickup. Not even if you add a new engine. Not even if you are willing to get three pickups. You need equipment designed for that. (And, as a note, the equipment that could handle delivering the steel beams would be a terrible choice for helping a friend move their sofa.)</p>

<p>&#8220;But,&#8221; I hear you say, &#8220;I already know how to drive a pickup! And we have a parking space for it. Can&#8217;t we just use the pickup? You&#8217;re a truck expert; tell us how to get our pickup to pull that load!&#8221;</p>

<p>And I say, &#8220;Being a truck expert, I will tell you again, a pickup the wrong kind of truck. There are other trucks that will handle that load with no trouble, but a pickup isn&#8217;t one of them. The fact that you have a pickup doesn&#8217;t make it the right truck.&#8221;</p>

<p>We have many clients that run PostgreSQL, happily, on Amazon Web Services. </p>

<p>Some clients, however, are not happy. They are attempting to haul tractor-trailer loads (such as high volume data warehouses) using pickup trucks (Amazon EC2 instances). They wish us to fix their problem, but are not willing to move off of Amazon in order to get the problem fixed.</p>

<p>I like AWS for a lot of things; it has many virtues, which <a href="http://www.pgcon.org/2012/schedule/events/419.en.html">I will discuss in detail soon</a>. However, AWS is <em>not</em> the right solution for every problem. In particular, if you require a high read or write data rate in order to get the performance you need from your database, you will ultimately not be happy on AWS. AWS has a single block-device storage mechanism, Elastic Block Storage, which simply does not scale up to very high data rates.</p>

<p>That doesn&#8217;t mean that AWS is useless, it just means it isn&#8217;t the right tool for every job. The problem arises when AWS is considered the fixed point, like the pickup was the fixed point above. At some point, you have to decide:</p>

<ol>
<li>That being on AWS is so important (for whatever reason) that you are willing to sacrifice the performance you want; or,</li>
<li>The performance you want is so important that you will need to move off of AWS.</li>
</ol>

<p>Sadly, even the best of consultants do not have the magic engine in our back room that will cause EBS to perform as well as high-speed direct attached storage.</p>

<p>More soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/04/25/of-pickups-and-tractor-trailers/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Fixing the WWDC</title>
		<link>http://thebuild.com/blog/2012/04/25/fixing-the-wwdc/</link>
		<comments>http://thebuild.com/blog/2012/04/25/fixing-the-wwdc/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 16:01:49 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[IOS]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=397</guid>
		<description><![CDATA[WWDC is broken. It's time to fix it.]]></description>
			<content:encoded><![CDATA[<p>Well, I&#8217;m not going; are you? This year&#8217;s <a href="https://developer.apple.com/wwdc/">Apple World-Wide Developer&#8217;s Conference</a> was sold out by 8am Pacific Time, having gone on sale around 6am. (I missed the boat in 2011 and 2010, too.) I can&#8217;t imagine anyone except perhaps Apple thinks that the mad scramble to the keyboard that we&#8217;ve experienced in the last few years is a rational way to allocate tickets.</p>

<p>It&#8217;s time for Apple to admit that the traditional model of a singular WWDC either requires a venue that can handle the crowd, or split it into multiple, regional events. It would lose the &#8220;gathering of the tribe&#8221; aspect that has always been one of the best parts of WWDC, but that&#8217;s lost now, anyway; the &#8220;tribe&#8221; is not defined on who was by their keyboards for 90 minutes at 6am on a Wednesday.</p>

<p>If Apple views the WWDC as a way to pack people into seats to create excitement for their announcements early in the week, then I suppose the current system is as good as anything. From any other perspective, it&#8217;s time to find another way of doing this.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/04/25/fixing-the-wwdc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Two very cool things.</title>
		<link>http://thebuild.com/blog/2012/04/20/two-very-cool-things/</link>
		<comments>http://thebuild.com/blog/2012/04/20/two-very-cool-things/#comments</comments>
		<pubDate>Fri, 20 Apr 2012 16:37:50 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Language Issues]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=395</guid>
		<description><![CDATA[First, read this essay about the disaster that is PHP. Every word is correct.

Then, view this photo set.
]]></description>
			<content:encoded><![CDATA[<p>First, <a href="http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/">read this essay</a> about the disaster that is PHP. Every word is correct.</p>

<p>Then, <a href="http://www.flickr.com/photos/raindrift/sets/72157629492908038/">view this photo set</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/04/20/two-very-cool-things/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blah, Blah, Blah, First Half of 2012 Edition</title>
		<link>http://thebuild.com/blog/2012/04/18/blah-blah-blah-first-half-of-2012-edition/</link>
		<comments>http://thebuild.com/blog/2012/04/18/blah-blah-blah-first-half-of-2012-edition/#comments</comments>
		<pubDate>Thu, 19 Apr 2012 06:55:57 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=392</guid>
		<description><![CDATA[My speaking schedule, if for some unaccountable reason you want to hear me talk.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be speaking at the following conferences through July:</p>

<ul>
<li><a href="http://www.pgcon.org/2012/">PGCon</a>, Ottawa, Ontario, Canada, May 17-18.</li>
<li><a href="http://2012.djangocon.eu/">DjangoCon Europe</a>, Zurich, Switzerland, June 4-6.</li>
<li><a href="http://www.southeastlinuxfest.org/">Southwest LinuxFest</a>, Charlotte, North Carolina, June 8-10.</li>
<li><a href="https://ep2012.europython.eu/">EuroPython</a>, Florence, Italy, July 2-8.</li>
<li><a href="http://www.oscon.com/oscon2012">OSCON</a>, Portland, Oregon, USA, July 16-20.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/04/18/blah-blah-blah-first-half-of-2012-edition/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Elements of postgresql.conf Style</title>
		<link>http://thebuild.com/blog/2012/04/13/the-elements-of-postgresql-conf-style/</link>
		<comments>http://thebuild.com/blog/2012/04/13/the-elements-of-postgresql-conf-style/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 15:00:47 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=385</guid>
		<description><![CDATA[&#8230; or, inexcusable things I am tired of seeing in postgresql.conf files.

Do not mix &#8216;n&#8217; match override styles.

There are two valid styles for overriding the default values in postgresql.conf: Putting your changes as a cluster at the end, or uncommenting the defaults and overriding in place. Both have advantages and disadvantages. Having some settings one [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230; or, inexcusable things I am tired of seeing in postgresql.conf files.</p>

<h3>Do not mix &#8216;n&#8217; match override styles.</h3>

<p>There are two valid styles for overriding the default values in postgresql.conf: Putting your changes as a cluster at the end, or uncommenting the defaults and overriding in place. Both have advantages and disadvantages. Having some settings one way and some another is pure disadvantage. Do not do this.</p>

<h3>Use units.</h3>

<p>Quick, what is <code>log_min_duration_statement</code> set to here?</p>

<pre><code>log_min_statement_duration = 2000
</code></pre>

<p>Now, what is it set to here?</p>

<pre><code>log_min_statement_duration = 2s
</code></pre>

<p>Always use units with numeric values if a unit is available.</p>

<h3>Do not remove the default settings.</h3>

<p>If you strip out all of the defaults, it becomes impossible to tell what a particular value is set to. Leave the defaults in place, and if you comment out a setting, reset the value to the default (or at least include comments that make it clear what is going on).</p>

<h3>Do not leave junk postgresql.conf files scattered around.</h3>

<p>If you need to move postgresql.conf (and the other configuration files) to a different location from where the package for your system puts it, don&#8217;t leave the old, dead postgresql.conf lying around. Delete any trace of the old installation hierarchy.</p>

<hr />

<p>Thank you.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/04/13/the-elements-of-postgresql-conf-style/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Instagram&#8217;s Technology Stack</title>
		<link>http://thebuild.com/blog/2012/04/12/instagrams-technology-stack/</link>
		<comments>http://thebuild.com/blog/2012/04/12/instagrams-technology-stack/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 19:09:40 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=381</guid>
		<description><![CDATA[Instagram has been in the news lately. In this really great post on Tumblr, Instagram talks about its technology stack.

I have some acquaintance with the Instagram people, and they are among the smartest technologists I&#8217;ve met. Really nice, too. (Of course, they mention this blog in the post, so I&#8217;m biased.)
]]></description>
			<content:encoded><![CDATA[<p><a href="http://instagram.com/">Instagram</a> has been <a href="http://dealbook.nytimes.com/2012/04/12/the-instragram-deal-a-mark-zuckerberg-production/">in the news lately</a>. In this <a href="http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances-dozens-of">really great post on Tumblr</a>, Instagram talks about its technology stack.</p>

<p>I have some acquaintance with the Instagram people, and they are among the smartest technologists I&#8217;ve met. Really nice, too. (Of course, they mention this blog in the post, so I&#8217;m biased.)</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/04/12/instagrams-technology-stack/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Recipe for Django Transactions on PostgreSQL</title>
		<link>http://thebuild.com/blog/2012/03/19/a-recipe-for-django-transactions-on-postgresql/</link>
		<comments>http://thebuild.com/blog/2012/03/19/a-recipe-for-django-transactions-on-postgresql/#comments</comments>
		<pubDate>Mon, 19 Mar 2012 19:33:14 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=328</guid>
		<description><![CDATA[Here's a recipe for handling transactions sensibly in Django on PostgreSQL.]]></description>
			<content:encoded><![CDATA[<p>As <a href="http://thebuild.com/blog/2009/11/07/django-postgresql-and-transaction-management/">noted before</a>, Django has a lot of facilities for handling transactions, and it&#8217;s not at all clear how to use them.  In an attempt to cut through the confusion, here&#8217;s a recipe for handling transactions sensibly in Django applications on PostgreSQL.</p>

<p>The goals are:</p>

<ul>
<li>Database operations that do not modify the database aren&#8217;t wrapped in a transactions at all.</li>
<li>Database operations that modify the database are wrapped in a transactions.</li>
<li>We have a lot of fine-grained control over sections that modify the databse vs those that don&#8217;t.</li>
</ul>

<p>The bits of the recipe are:</p>

<ul>
<li>Use the <a href="https://docs.djangoproject.com/en/dev/ref/databases/#autocommit-mode">autocommit option</a> in your database configuration.</li>
<li><em>Do not</em> use the <a href="https://docs.djangoproject.com/en/dev/topics/db/transactions/#tying-transactions-to-http-requests">transaction middleware</a>.</li>
<li>Wrap the sections of code which modify the database in the <code>xact()</code> decorator / context manager below, using it like you would the <a href="https://docs.djangoproject.com/en/dev/topics/db/transactions/#controlling-transaction-management-in-views"><code>commit_on_success()</code></a> decorator.</li>
<li>Profit!</li>
</ul>

<p>The quick reasons behind each step:</p>

<ul>
<li>Turning on autocommit prevents <a href="http://initd.org/psycopg/">psycopg2</a> from automatically starting a new transaction on the first database operation on each connection; this means that the transaction only starts when we want it to.</li>
<li>Similarly, the transaction middleware will set the connection state to &#8220;managed,&#8221; which will defeat the autocommit option above, so we leave it out.</li>
<li>The <code>xact()</code> decorator will set up the connection so that a transaction <em>is</em> started in the relevant block, which is what we want for database-modifying operations.</li>
</ul>

<p>This recipe a few other nice features:</p>

<ul>
<li><code>xact()</code> operates like <code>commit_on_success()</code>, in that it will issue a rollback if an exception escapes from the block or function it is wrapping.</li>
<li><code>xact()</code> ignores the dirty flag on the Django connection. Since we&#8217;re deliberately wrapping stuff that modifies the database with it, the chance of it being dirty is near 100%, and a commit on a transaction that did not modify the database is no more expensive in PostgreSQL than a rollback. It also means you can do <a href="https://docs.djangoproject.com/en/dev/topics/db/sql/">raw SQL</a> inside an <code>xact()</code> block without the <a href="http://archives.postgresql.org/pgsql-hackers/2008-06/msg01101.php">foot-gun</a> of forgetting to call <code>set_dirty</code>.</li>
<li>Like the built-in Django transaction decorators, it can be used either as a decorator or as a context manager with the <code>with</code> statement.</li>
<li><code>xact()</code> can be nested, giving us nested transactions! If it sees that there is already a transaction open when it starts a new block, it will use a <a href="http://www.postgresql.org/docs/9.1/static/sql-savepoint.html">savepoint</a> to set up a nested transaction block.  (PostgreSQL does not have nested transactions as such, but you can use savepoints to get 99.9% of the way there.)</li>
<li>By not wrapping operations that do not modify the database, we get better behavior when using <a href="http://www.pgpool.net/">pgPool II</a> (more on that in a future post).</li>
<li><code>xact()</code> works around an <a href="https://code.djangoproject.com/ticket/16047">outstanding bug</a> in Django&#8217;s transaction handling on psycopg2.</li>
</ul>

<p><code>xact()</code> also supports the <code>using</code> parameter for <a href="https://docs.djangoproject.com/en/dev/topics/db/multi-db/">multiple databases</a>.</p>

<p>Of course, a few caveats:</p>

<ul>
<li><code>xact()</code> requires the <code>postgresql_psycopg2</code> backend, and PostgreSQL 8.2 or higher. It&#8217;s possible it can be hacked to work on other backends that support savepoints.</li>
<li><code>xact()</code> works just the way you want if it is nested <em>inside</em> a <code>commit_on_success()</code> block (it will properly create a savepoint insted of a new transaction). However, a <code>commit_on_success()</code> block nested inside of <code>xact()</code> will commit or rollback the entire transaction, somewhat defeating the outer <code>xact()</code>. To the extent possible, use only <code>xact()</code> in code you write.</li>
<li>Be sure you catch exceptions <em>outside of</em> the <code>xact()</code> block; otherwise, the automatic rollback will be defeated. Allow the exception to escape the <code>xact()</code> block, and then catch it. (Of course, if the intention is to always commit and to defeat the rollback, by all means catch the exception inside the block.)</li>
</ul>

<p>To use, just drop the source (one class definition, one function) into a file somewhere in your Django project (such as the omni-present <code>utils</code> application every Django project seems to have), and include it. </p>

<p>Examples:</p>

<pre><code>from utils.transaction import xact

@xact
def my_view_function1(request):
   # Everything here will be in a transaction.
   # It'll roll back if an exception escapes, commits otherwise.

def my_view_function2(request):
   # This stuff won't be in a transaction, so don't modify the database here.
   with xact():
      # This stuff will be, and will commit on normal completion, roll back on a exception

def my_view_function3(request):
   with xact():
      # Modify the database here (let's call it "part 1").
      try:
         with xact():
            # Let's call this "part 2."
            # This stuff will be in its own savepoint, and can commit or
            # roll back without losing the whole transaction.
      except:
         # Part 2 will be rolled back, but part 1 will still be available to
         # be committed or rolled back.  Of course, if an exception
         # inside the "part 2" block is not caught, both part 2 and
         # part 1 will be rolled back.
</code></pre>

<p>The source is <a href="https://github.com/Xof/xact/">available on GitHub</a>. It&#8217;s licensed under the <a href="http://www.postgresql.org/about/licence/">PostgreSQL License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/03/19/a-recipe-for-django-transactions-on-postgresql/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>PostgreSQL Performance When It&#8217;s Not Your Job</title>
		<link>http://thebuild.com/blog/2012/01/24/postgresql-performance-when-its-not-your-job/</link>
		<comments>http://thebuild.com/blog/2012/01/24/postgresql-performance-when-its-not-your-job/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 06:03:09 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=326</guid>
		<description><![CDATA[My presentation from SCALE 10x, &#8220;PostgreSQL Performance When It&#8217;s Not Your Job&#8221; is now available for download.
]]></description>
			<content:encoded><![CDATA[<p>My presentation from SCALE 10x, <a href="http://thebuild.com/presentations/not-my-job.pdf">&#8220;PostgreSQL Performance When It&#8217;s Not Your Job&#8221;</a> is now available for download.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2012/01/24/postgresql-performance-when-its-not-your-job/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>&#8220;Sharding &amp; IDs at Instagram&#8221;</title>
		<link>http://thebuild.com/blog/2011/09/30/sharding-ids-at-instagram/</link>
		<comments>http://thebuild.com/blog/2011/09/30/sharding-ids-at-instagram/#comments</comments>
		<pubDate>Sat, 01 Oct 2011 05:39:21 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=324</guid>
		<description><![CDATA[I&#8217;d like to recommend an interesting post, &#8220;Sharding &#38; IDs at Instagram&#8221;, about sharding using Postgres.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;d like to recommend an interesting post, <a href="http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram">&#8220;Sharding &amp; IDs at Instagram&#8221;</a>, about sharding using Postgres.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/09/30/sharding-ids-at-instagram/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cleaning up after your Bucardo goats</title>
		<link>http://thebuild.com/blog/2011/09/27/cleaning-up-after-your-bucardo-goats/</link>
		<comments>http://thebuild.com/blog/2011/09/27/cleaning-up-after-your-bucardo-goats/#comments</comments>
		<pubDate>Wed, 28 Sep 2011 05:25:20 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=313</guid>
		<description><![CDATA[A pure PL/pgSQL script for daily Bucardo maintenance.]]></description>
			<content:encoded><![CDATA[<p>If you are not familiar with it already, <a href="http://bucardo.org/wiki/Bucardo">Bucardo</a> is a nifty multi-master replication system for PostgreSQL, written by <a href="http://www.endpoint.com/team/greg_sabino_mullane">Greg Sabino Mullane</a>. Written in Perl, it is great if you need replication that doesn&#8217;t have the restrictions associated with PG 9&#8217;s <a href="http://www.postgresql.org/docs/9.1/static/warm-standby.html#STREAMING-REPLICATION">streaming replication</a>.</p>

<p>To keep your Bucardo installation clean and tidy, a few <a href="http://bucardo.org/wiki/Bucardo/Cron">regular cron jobs</a> are required. One of them cleans up the archived replicated data (stored in a separate database by Bucardo) once you know you are done with it. </p>

<p>The Bucardo page above has a recommended script using all sorts of <code>bash</code>ing, but I wanted something a bit more pure-PostgreSQL; it also doesn&#8217;t purge more than one old table at a time. So, I whipped up the following PL/pgSQL function.</p>

<p>(Note that this is for Bucardo 4.4. I haven&#8217;t played with the forthcoming Bucardo 5, so I&#8217;m not sure if this is still required.)</p>

<pre><code>CREATE OR REPLACE FUNCTION bucardo.purge_frozen_child_qs(far_back interval)
    RETURNS SETOF TEXT AS
$purge_frozen_child_qs$
DECLARE
    t TEXT;
    qt TEXT;
BEGIN

    IF far_back IS NULL THEN
        RAISE EXCEPTION 'Interval cannot be null.'
            USING HINT = 'So, do not do that.';
    END IF;

    IF (now() + far_back) &gt; now() THEN
        RAISE EXCEPTION 'Interval must be negative.'
            USING HINT = 'Consider using the "ago" form of intervals.';
    END IF;

    FOR t IN 
        SELECT tablename 
            FROM pg_tables
            WHERE schemaname='freezer' 
                  AND tablename like 'child_q_%' 
                  AND (replace(tablename, 'child_q_', '')::timestamp with time zone) &lt; now() + far_back::interval
            ORDER BY tablename
    LOOP
        qt := 'freezer.' || t;
        EXECUTE 'DROP TABLE ' || qt;
        RETURN NEXT qt;
    END LOOP;

    DELETE FROM bucardo.q 
        WHERE (started &lt; now() + far_back::interval 
                OR ended &lt; now() + far_back::interval 
                OR aborted &lt; now() + far_back::interval 
                OR cdate &lt; now() + far_back::interval) 
              AND (ended IS NULL OR aborted IS NULL);

    RETURN;

END
$purge_frozen_child_qs$
LANGUAGE plpgsql
    VOLATILE;
</code></pre>

<p>To use it, just call it repeatedly from a cron job with the appropriate argument, along the lines of:</p>

<pre><code>SELECT * FROM bucardo.purge_frozen_child_qs('7 days ago'::interval);
</code></pre>

<p>It returns the names of the tables it deleted.</p>

<p>This particular function doesn&#8217;t need to be run more often than once a day. And it keeps your Bucardo goats nice and clean.</p>

<p>(A &#8220;bucardo&#8221; is a <a href="http://en.wikipedia.org/wiki/Pyrenean_Ibex">now-extinct species of goat</a>. For why Bucardo is goat-related, ask Greg.)</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/09/27/cleaning-up-after-your-bucardo-goats/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Unbreaking Your Django Application</title>
		<link>http://thebuild.com/blog/2011/07/26/unbreaking-your-django-application/</link>
		<comments>http://thebuild.com/blog/2011/07/26/unbreaking-your-django-application/#comments</comments>
		<pubDate>Tue, 26 Jul 2011 21:14:59 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=310</guid>
		<description><![CDATA[My tutorial at OSCON 2011, Unbreaking Your Django Application, is now available for download.
]]></description>
			<content:encoded><![CDATA[<p>My tutorial at OSCON 2011, <a href="http://thebuild.com/presentations/unbreaking-django.pdf">Unbreaking Your Django Application</a>, is now available for download.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/07/26/unbreaking-your-django-application/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Life with Object-Relational Mappers</title>
		<link>http://thebuild.com/blog/2011/05/18/life-with-object-relational-mappers/</link>
		<comments>http://thebuild.com/blog/2011/05/18/life-with-object-relational-mappers/#comments</comments>
		<pubDate>Wed, 18 May 2011 18:31:21 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=307</guid>
		<description><![CDATA[The slides from my talk at PGCon 2011 are now available.
]]></description>
			<content:encoded><![CDATA[<p>The slides from my talk at PGCon 2011 are <a href="http://blog.thebuild.com/presentations/drstrangedata.pdf">now available</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/05/18/life-with-object-relational-mappers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Not Convenient.</title>
		<link>http://thebuild.com/blog/2011/03/28/not-convenient/</link>
		<comments>http://thebuild.com/blog/2011/03/28/not-convenient/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 16:49:02 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[IOS]]></category>
		<category><![CDATA[Mac OS X]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=304</guid>
		<description><![CDATA[DjangoCon Europe and the Apple WWDC are at the exact same time. This is going to be a tough call.

Update: Well, that was quick. WWDC sold out in 10 hours, while I was dithering.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://djangocon.eu/">DjangoCon Europe</a> and the <a href="http://developer.apple.com/wwdc/">Apple WWDC</a> are at the exact same time. This is going to be a tough call.</p>

<p>Update: Well, that was quick. WWDC sold out in 10 hours, while I was dithering.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/03/28/not-convenient/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What It Means to Be In Business</title>
		<link>http://thebuild.com/blog/2011/03/18/what-it-means-to-be-in-business/</link>
		<comments>http://thebuild.com/blog/2011/03/18/what-it-means-to-be-in-business/#comments</comments>
		<pubDate>Sat, 19 Mar 2011 01:08:19 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Tech Biz]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=295</guid>
		<description><![CDATA[To bring everyone up to date:


Justin Vincent wrote a post offering an opinion about the downsides of the chase of tech entrepreneurs over VC funding.
Amy Hoy wrote a post expanding on Mr Vincent&#8217;s post.
Alex Payne wrote a post criticizing this position, while finding it necessary to describe &#8220;long time acquaintance&#8221; Amy Hoy&#8217;s product as &#8220;duping [...]]]></description>
			<content:encoded><![CDATA[<p>To bring everyone up to date:</p>

<ul>
<li><a href="http://justinvincent.com/page/1392/entreporn-the-fallacy-that-wastes-your-life">Justin Vincent</a> wrote a post offering an opinion about the downsides of the chase of tech entrepreneurs over VC funding.</li>
<li><a href="http://unicornfree.com/2011/dont-let-the-bastards-grind-you-down/">Amy Hoy</a> wrote a post expanding on Mr Vincent&#8217;s post.</li>
<li><a href="http://news.ycombinator.com/item?id=2338911">Alex Payne</a> wrote a post criticizing this position, while finding it necessary to describe &#8220;long time acquaintance&#8221; Amy Hoy&#8217;s product as &#8220;duping credulous customers into overpaying for a time-tracking tool styled with this month&#8217;s CSS trends.&#8221;</li>
<li>Unaccountably, he seems to have been surprised by the negative reaction this post generated, so he posted an <a href="http://al3x.net/2011/03/18/not-a-waste.html">explanation and partial retraction</a> here.</li>
</ul>

<p>Sadly, I find his last post as incoherent as his first one is vitriolic.</p>

<p>Rather than go through it point by point, the crux of his argument is:</p>

<blockquote>
  <p>Building a business around maximizing your individual happiness is not particularly useful or admirable. That is my position, and I’m well aware that it may be unpopular with some.</p>
</blockquote>

<p>I am pleased to report, then, that Mr Payne has <em>absolutely nothing to worry about</em>, because no business that is built around the happiness of the owner as a primary goal has a hope of every getting anywhere, unless the business consists of the owner taking money out of one pocket and putting it in the other. Any business, unless it is operating in a grotesquely distorted marketplace, is primarily about pleasing its <em>customers</em> in exchange for their money.</p>

<p>I&#8217;m really not sure what these vaguely masturbatory companies Mr Payne is talking about do for a living, but every (successful) micro-business I know of is insanely, intensely focused on pleasing its customers. They have to be, because they don&#8217;t have an installed base, government-granted advantages, or (yes) piles of venture capital in the bank to fall back on if they fail to do so.</p>

<p>Mr Payne wants to run a big company. I wish him all the best. He seems to have his young heart in the right place. I have to say, though, that his emotional overreaction to the idea that someone might want to run a micro-business instead strikes me as the Puritan reacting to the idea that someone, somewhere, might be happy.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/03/18/what-it-means-to-be-in-business/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Transaction-Level Advisory Locks in PostgreSQL 9.1</title>
		<link>http://thebuild.com/blog/2011/03/13/transaction-level-advisory-locks-in-postgresql-9-1/</link>
		<comments>http://thebuild.com/blog/2011/03/13/transaction-level-advisory-locks-in-postgresql-9-1/#comments</comments>
		<pubDate>Sun, 13 Mar 2011 22:42:50 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=292</guid>
		<description><![CDATA[Advisory locks are one of the cool unsung features of PostgreSQL. In 9.1, they are getting even cooler with transaction level locks. Many details here.
]]></description>
			<content:encoded><![CDATA[<p>Advisory locks are one of the cool unsung features of PostgreSQL. In 9.1, they are getting even cooler with transaction level locks. <a href="http://www.depesz.com/index.php/2011/03/14/waiting-for-9-1-transaction-level-advisory-locks/">Many details here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/03/13/transaction-level-advisory-locks-in-postgresql-9-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Concern Troll is Concerned: Verifone vs Square</title>
		<link>http://thebuild.com/blog/2011/03/09/concern-troll-is-concerned-verifone-vs-square/</link>
		<comments>http://thebuild.com/blog/2011/03/09/concern-troll-is-concerned-verifone-vs-square/#comments</comments>
		<pubDate>Thu, 10 Mar 2011 06:25:24 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=289</guid>
		<description><![CDATA[Suppose a major manufacturer of computer keyboards announced a very serious security problem with a specific competitor&#8217;s keyboard: Someone could plug this keyboard into a computer running a malicious app, and cause a user to enter sensitive information. Thus, the manufacturer demands that their competitor recall all of these &#8220;insecure&#8221; keyboards.

Anyone with the technical sense [...]]]></description>
			<content:encoded><![CDATA[<p>Suppose a major manufacturer of computer keyboards announced a <em>very serious</em> security problem with a specific competitor&#8217;s keyboard: Someone could plug this keyboard into a computer running a malicious app, and cause a user to enter sensitive information. Thus, the manufacturer demands that their competitor recall all of these &#8220;insecure&#8221; keyboards.</p>

<p>Anyone with the technical sense of a rock would pause for a moment, and then burst out in laughter at the utter absurdity of this proclamation. No one would ever attempt to make such a ludicrous and obviously self-serving claim, would they?</p>

<p><a href="http://www.sq-skim.com/">Verifone would.</a> Verifone is <em>very very concerned</em> about <a href="https://squareup.com/">Square&#8217;s</a> iPhone card scanner, because someone could run a malicious app on the iPhone and collect card data using it. The fact that Square just announced <a href="https://squareup.com/pricing">new pricing</a> undercutting Verifone&#8217;s is, of course, completely coincidental.</p>

<p>Where to begin?</p>

<ul>
<li><p>It is true that Square&#8217;s attachment does not encrypt the card track information between the iPhone and the card reader. This is true of pretty much every single card reader in the entire world. It is not the job of the card reader to encrypt data, any more than it is the job of the keyboard to encrypt your password. Verifone seems unconcerned at all of the other card readers you can buy from, say, <a href="http://www.amazon.com/MagTek-Swipe-Reader-Keyboard-Emulation/dp/B0013A1VA4">Amazon</a> (just for example).</p></li>
<li><p>For Verifone&#8217;s apocalyptic scenario to occur, the iPhone into which the card reader is plugged must be running a malicious app. This pretty much requires the iPhone user to be in on the scam, which means that they could be using any hardware they wish to collect this card data. If the merchant is crooked, then they&#8217;ll find a way to collect the card data, since they <em>have possession of the card</em> (on which is printed essentially all of the relevant data that is on the mag tracks, plus the CVV printed on the back).</p></li>
<li><p>Verifone&#8217;s competing solution, if the brochure is to be believed, encrypts the data at swipe-time. That&#8217;s nice, but the chance of card data being compromised <em>between</em> the reader and the iPhone, or during that extremely limited time that it is sitting unencrypted in the iPhone&#8217;s memory, is essentially zero. Again, Verifone seems unconcerned that Square&#8217;s app works exactly like every other PC-based credit card processing application in the entire world; indeed, Square&#8217;s is considerably more secure than most, since the merchant doesn&#8217;t have access to the card information. (For example, on my completely certified, authorized, and every-spec-compliant Nurit wireless card processing terminal, I can retrieve credit card numbers from a batch with no hassle whatsoever.)</p></li>
</ul>

<p>In short, Verifone is bashing a competitor because the competitor&#8217;s pricing is more consumer-friendly than Verifone&#8217;s. Their technical arguments are nonsense, and they should be ashamed of launching a FUD campaign that plays on credit card security paranoia.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/03/09/concern-troll-is-concerned-verifone-vs-square/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django and PostgreSQL at PostgreSQL Conference East</title>
		<link>http://thebuild.com/blog/2011/03/09/django-and-postgresql-at-postgresql-conference-east/</link>
		<comments>http://thebuild.com/blog/2011/03/09/django-and-postgresql-at-postgresql-conference-east/#comments</comments>
		<pubDate>Thu, 10 Mar 2011 06:03:51 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=287</guid>
		<description><![CDATA[I&#8217;ll be giving a full day tutorial about developing Django applications using PostgreSQL. If you are just getting started with Django, this is a great introduction; it is intended for developers who are just getting into serious Django/PG development.

It&#8217;ll cover general development in Django, with a lot of PostgreSQL-specific details.

And, of course, the whole conference [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be giving a <a href="https://www.postgresqlconference.org/files/east_2011_schedule.html">full day tutorial</a> about developing Django applications using PostgreSQL. If you are just getting started with Django, this is a great introduction; it is intended for developers who are just getting into serious Django/PG development.</p>

<p>It&#8217;ll cover general development in Django, with a lot of PostgreSQL-specific details.</p>

<p>And, of course, the whole conference will be a fount of great PostgreSQL geekery.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/03/09/django-and-postgresql-at-postgresql-conference-east/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Anatomy of a Crushing&#8221;</title>
		<link>http://thebuild.com/blog/2011/03/08/anatomy-of-a-crushing/</link>
		<comments>http://thebuild.com/blog/2011/03/08/anatomy-of-a-crushing/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 01:52:51 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=284</guid>
		<description><![CDATA[A fun and interesting article about a sudden burst in traffic at Pinboard when Yahoo! announced they were shutting down Delicious. Relevant to app and DB designers everywhere.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://pinboard.in/blog/173/">A fun and interesting</a> article about a sudden burst in traffic at Pinboard when Yahoo! announced they were shutting down Delicious. Relevant to app and DB designers everywhere.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/03/08/anatomy-of-a-crushing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;10 Ways to Kill Performance&#8221;</title>
		<link>http://thebuild.com/blog/2011/02/25/10-ways-to-kill-performanc/</link>
		<comments>http://thebuild.com/blog/2011/02/25/10-ways-to-kill-performanc/#comments</comments>
		<pubDate>Sat, 26 Feb 2011 00:17:55 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=282</guid>
		<description><![CDATA[The slides from my talk, &#8220;10 Easy Ways to Destroy Performance&#8221; from PgDay at SCALE 9X are available.
]]></description>
			<content:encoded><![CDATA[<p>The slides from my talk, <a href="http://thebuild.com/presentations/10-ways-to-kill-performance.pdf">&#8220;10 Easy Ways to Destroy Performance&#8221;</a> from PgDay at SCALE 9X are available.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/02/25/10-ways-to-kill-performanc/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>&#8220;10 Easy Ways to Destroy Performance&#8221; at pgDay at SCALE-9X</title>
		<link>http://thebuild.com/blog/2011/02/15/10-easy-ways-to-destroy-performance-scale-9x/</link>
		<comments>http://thebuild.com/blog/2011/02/15/10-easy-ways-to-destroy-performance-scale-9x/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 05:22:19 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=276</guid>
		<description><![CDATA[I&#8217;ll be presenting a talk on &#8220;10 Easy Ways to Destroy Performance&#8221; at pgDay at SCALE-9X, on February 25th in Los Angeles.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be presenting a talk on &#8220;10 Easy Ways to Destroy Performance&#8221; at <a href="https://sites.google.com/site/pgdayla/">pgDay at SCALE-9X</a>, on February 25th in Los Angeles.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/02/15/10-easy-ways-to-destroy-performance-scale-9x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Django Development with PostgreSQL&#8221; at PostgreSQL Conference East</title>
		<link>http://thebuild.com/blog/2011/02/15/django-postgresql-postgresql-conference-east/</link>
		<comments>http://thebuild.com/blog/2011/02/15/django-postgresql-postgresql-conference-east/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 05:19:59 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=274</guid>
		<description><![CDATA[I&#8217;ll be presenting a full-day tutorial on Django Development with PostgreSQL at PostgreSQL Conference East, March 22-25 in New York!
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be presenting a full-day tutorial on <a href="https://www.postgresqlconference.org/content/django-development-postgresql">Django Development with PostgreSQL</a> at <a href="https://www.postgresqlconference.org/">PostgreSQL Conference East</a>, March 22-25 in New York!</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/02/15/django-postgresql-postgresql-conference-east/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PostgreSQL for Servoy Developers</title>
		<link>http://thebuild.com/blog/2011/02/04/postgresql-for-servoy-developers/</link>
		<comments>http://thebuild.com/blog/2011/02/04/postgresql-for-servoy-developers/#comments</comments>
		<pubDate>Fri, 04 Feb 2011 08:59:49 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=269</guid>
		<description><![CDATA[The slides from my presentation on PostgreSQL for Servoy Developers, presented at ServoyWorld 2011, are available here.
]]></description>
			<content:encoded><![CDATA[<p>The slides from my presentation on PostgreSQL for Servoy Developers, presented at <a href="http://servoy.com">ServoyWorld 2011</a>, are <a href="http://thebuild.com/presentations/pg-servoy.pdf">available here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2011/02/04/postgresql-for-servoy-developers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Nobody Here But Us Chickens: Google and Lies We Tell Ourselves</title>
		<link>http://thebuild.com/blog/2010/12/31/nobody-here-but-us-chickens-google-and-lies-we-tell-ourselves/</link>
		<comments>http://thebuild.com/blog/2010/12/31/nobody-here-but-us-chickens-google-and-lies-we-tell-ourselves/#comments</comments>
		<pubDate>Fri, 31 Dec 2010 20:50:59 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Tech Biz]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=249</guid>
		<description><![CDATA[If you make a tradeoff, be honest about it. Don't lie to yourself that you are making a positive architectural decision when you make a negative tradeoff.]]></description>
			<content:encoded><![CDATA[<p><strong>tl;dr</strong>: If you make a tradeoff, be honest about it. Don&#8217;t lie to yourself that you are making a positive architectural decision when you make a negative tradeoff.</p>

<p><span id="more-249"></span></p>

<hr />

<p>In a flash of snarkiness, I posted this to <a href="http://twitter.com/Xof/status/20620780811325440">my Twitter account</a>, based on a colleague&#8217;s attempt to solve a YouTube password problem:</p>

<blockquote>
  <p>Google doesn&#8217;t want to hear from its users any more than <a href="http://www.tyson.com/">Tyson</a> wants to hear from its chickens.</p>
</blockquote>

<p>The slightly-expanded message is: The users of Google&#8217;s free services are a product to be delivered to advertisers, not customers towards whom Google feels an obligation. I think this is more than just fair; I think it&#8217;s self-evident.</p>

<p>There was a certain amount of chatter form those who insist on viewing the world as a <a href="http://en.wikipedia.org/wiki/Manichaeism">Manichean</a> struggle between Apple and Google (which had nothing whatsoever to do with it), but it more productively resulting in <a href="http://twitter.com/mattcutts/status/20636038305157121">a reply</a> from no less that <a href="http://www.mattcutts.com/blog/">Matt Cutts</a> (and I appreciate his taking the time to bounce this around with me):</p>

<blockquote>
  <p>@Xof that&#8217;s certainly not the case.</p>
</blockquote>

<p><a href="http://twitter.com/Xof/status/20638091966414848">I replied</a>:</p>

<blockquote>
  <p>@mattcutts Glad to hear it. What&#8217;s the tech support number for YouTube users?</p>
</blockquote>

<p><a href="http://twitter.com/mattcutts/status/20717489180647424">Mr Cutts</a> replied:</p>

<blockquote>
  <p>@Xof phone lines are 1:1, which means other users can&#8217;t benefit from answers/feedback. The forum for YouTube is <a href="http://goo.gl/pApu">http://goo.gl/pApu</a></p>
</blockquote>

<p>And here we get to the lies we tell ourselves.</p>

<p>You can&#8217;t do everything all the time. No person, product or company can hit every single mark, can fulfill every single desire or request. No one should ever be ashamed of that; everyone has to prioritize.</p>

<p>Google&#8217;s prioritization is, &#8220;For our free services, we can&#8217;t provide individualized support because it would simply be too expensive. Instead, we mobsource our support. That&#8217;s what you are getting when you use our free services. Did we mention that they&#8217;re free?&#8221; That&#8217;s not insane, and you can agree with it (and use Google&#8217;s services), or disagree with it (and not, or do so anyway and whine about the terrible support, your choice). But that&#8217;s what you get.</p>

<p>But attempting to portray that decision as, &#8220;Forums are <em>so much cooler</em> than an actual human being on the phone who can actually address your particular item&#8221; is absurd. Can you imagine, say, a bank with that position? &#8221;An unexplained debit to your account? No problem! Post a comment to our Forum, and maybe someone has had a similar problem and you can share your experience. Sometimes, an employee might see the post and comment. It&#8217;s rad!&#8221;</p>

<p>Tech support forums are great, and every company should sponsor one for their products, but they are not a substitute for a support system that does not rely on the kindness of strangers and does involve someone who can safely access details relevant to your individual situation and who can access internal expertise within the company. I would hope that&#8217;s self-evident, too.</p>

<p>(And, of course, a rep can share their redacted experience from a call on a forum.)</p>

<p>I&#8217;m reminded of the apologia  for why <code>qmail</code> doesn&#8217;t send multiple messages on one SMTP connection, or the long diatribe in the <a href="http://oreilly.com/catalog/9780596000271">Camel Book</a> about why Perl 5 doesn&#8217;t have simple, reliable bytecode compilation. In both cases, a designer made a choice that feature was complex to implement and not a high priority; reasonable people can disagree with their choices, but they made them for what I assume are sound reasons. However, rather than just say, &#8220;Nope, not getting to that one right away,&#8221; what was a issue of priority was tarted up to look like a wise technical architecture decision, which neither one was. (Lots of MTAs can do just fine sending multiple messages on one connection, and if bytecode compilation for Perl was such a dumb idea, what&#8217;s up with <a href="http://www.parrot.org/">Parrot</a>?)</p>

<p>Every business (and person) needs to make choices. Nothing wrong with that. Just be honest with yourself about why you are doing it, so you can be honest with other people.</p>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2010/12/31/nobody-here-but-us-chickens-google-and-lies-we-tell-ourselves/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Extra columns when doing .distinct() in a Django QuerySet</title>
		<link>http://thebuild.com/blog/2010/12/22/extra-columns-when-doing-distinct-in-a-django-queryset/</link>
		<comments>http://thebuild.com/blog/2010/12/22/extra-columns-when-doing-distinct-in-a-django-queryset/#comments</comments>
		<pubDate>Wed, 22 Dec 2010 22:54:05 +0000</pubDate>
		<dc:creator>Xof</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://thebuild.com/blog/?p=239</guid>
		<description><![CDATA[If you are doing a <code>.distinct()</code> query and limiting the results using <code>.values()</code> or <code>.values_list()</code>, you may be in for a surprise if your model has a default ordering using the Meta value <code>ordering</code>. You probably want to clear the ordering using <code>.order_by()</code> with no parameters.]]></description>
			<content:encoded><![CDATA[<p><strong>tl;dr</strong>: If you are doing a <code>.distinct()</code> query and limiting the results using <code>.values()</code> or <code>.values_list()</code>, you may be in for a surprise if your model has a default ordering using the Meta value <code>ordering</code>. You probably want to clear the ordering using <code>.order_by()</code> with no parameters.</p>

<p><span id="more-239"></span></p>

<hr />

<p>If a model is ordered, either by <code>.order_by()</code> on the QuerySet or a Meta <code>ordering</code> value, it will always include that field in the QuerySet. This is true <em>even if the query uses <code>.distinct()</code></em>. To quote <a href="http://docs.djangoproject.com/en/1.2/ref/models/querysets/#distinct">the documentation</a>:</p>

<blockquote>
  <p>Any fields used in an<code>order_by()</code> call are included in the SQL SELECT columns. This can sometimes lead to unexpected results when used in conjunction with <code>distinct()</code>.</p>
</blockquote>

<p>(The documentation as written implies that is only problem with related models, but as we&#8217;ll see, it&#8217;s a problem in general. <a href="http://code.djangoproject.com/ticket/14942">A documentation patch</a> is probably in order here.)</p>

<p>By way of illustration, let&#8217;s assume you have the following models:</p>

<pre><code>from django.db import models

class Publisher(models.Model):
    name = models.TextField()

    class Meta:
        ordering = [ 'name', ]

class Book(models.Model):
    title = models.TextField()
    topic = models.TextField()
    publisher = models.ForeignKey(Publisher)

    class Meta:
        ordering = [ 'title', ]
</code></pre>

<p>And we create some rows:</p>

<pre><code>pub = Publisher(name="Strange But True Publications")
pub.save()
</code></pre>

<p>And some books:</p>

<pre><code>book1 = Book(title="New Topics in Industrial Meringue Production",
             topic="Cooking",
             publisher=pub)
book1.save()

book2 = Book(title="Your Chicken's First Song Book",
             topic="Animal Husbandry",
             publisher=pub)
book2.save()
</code></pre>

<p>Now, we want to get the list of IDs of the publishers, and we&#8217;re using the <a href="http://thebuild.com/blog/2010/12/22/getting-the-id-of-related-objects-in-django/">cool optimization that I described earlier</a>, with the optimization a commenter suggested (thanks!):</p>

<pre><code>&gt;&gt;&gt; q = Book.objects.values_list('publisher_id', flat=True).distinct()
&gt;&gt;&gt; print q
[1, 1]
</code></pre>

<p>Um, wait.  That&#8217;s not right.  Why would it return <code>1</code> twice when we said <code>.distinct()</code>?  Let&#8217;s look at the SQL (you <em>are</em> doing a <code>tail -f</code> on the PostgreSQL logs while  you develop, right?):</p>

<pre><code>LOG:  statement: SELECT DISTINCT "x_book"."publisher_id", "x_book"."title" FROM "x_book" ORDER BY "x_book"."title" ASC LIMIT 21
</code></pre>

<p>And there we have it.  It includes the <code>title</code> field in the query, even though it doesn&#8217;t return it.  Since the <code>DISTINCT</code> thus applies to both, we have two distinct rows, rather than one.</p>

<p>The fix, fortunately, is easy; just clear the ordering with a <code>.order_by()</code> without any parameters:</p>

<pre><code>&gt;&gt;&gt; q = Book.objects.values_list('publisher_id', flat=True).distinct().order_by()
&gt;&gt;&gt; print q
[1]
</code></pre>

<p>And the query:</p>

<pre><code>LOG:  statement: SELECT DISTINCT "x_book"."publisher_id" FROM "x_book" LIMIT 21
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://thebuild.com/blog/2010/12/22/extra-columns-when-doing-distinct-in-a-django-queryset/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

