<?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>Thinking In Rails &#187; Database</title>
	<atom:link href="http://thinkinginrails.com/category/database/feed/" rel="self" type="application/rss+xml" />
	<link>http://thinkinginrails.com</link>
	<description>A Perl Programmer&#039;s Exploration of The World of Ruby on Rails</description>
	<lastBuildDate>Thu, 12 Apr 2012 03:37:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>DataMapper 1.0 Interview</title>
		<link>http://thinkinginrails.com/2010/07/datamapper-1-0-interview/</link>
		<comments>http://thinkinginrails.com/2010/07/datamapper-1-0-interview/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 20:45:33 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=598</guid>
		<description><![CDATA[My buddy Dan Kubb has a nice interview on the recent DataMapper 1.0 Milestone.  DM is something that I have been wanting to look at forever, everytime Dan does his &#8220;let me just show you how to do this in DM instead of ActiveRecord&#8221; stints, I&#8217;m always amazed at how fast and easy he does [...]]]></description>
			<content:encoded><![CDATA[<p>My buddy Dan Kubb has a nice interview on the recent <a href="http://www.infoq.com/news/2010/07/datamapper-1.0">DataMapper 1.0 Milestone</a>.  DM is something that I have been wanting to look at forever, everytime Dan does his &#8220;let me just show you how to do this in DM instead of ActiveRecord&#8221; stints, I&#8217;m always amazed at how fast and easy he does things.  Of course, I&#8217;m also amazed at how fast and easy things are done in ActiveRecord by people who are proficient in it <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Time to break out the Rails 3 and see how fast and easy the integration of DM into it is!</p>
<p>Anyway, a great interview and well worth the read.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/07/datamapper-1-0-interview/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Datamapper 1.0 Released</title>
		<link>http://thinkinginrails.com/2010/06/datamapper-1-0-released/</link>
		<comments>http://thinkinginrails.com/2010/06/datamapper-1-0-released/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 18:42:06 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[DataMapper]]></category>
		<category><![CDATA[Gem]]></category>
		<category><![CDATA[ORM]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=563</guid>
		<description><![CDATA[Well, as of right now there aren&#8217;t any release notes or website update, but Dan Kubb (@dkubb) has tagged the 1.0 release of DataMapper.  This is for the talk at RailsConf today that Dirkjan Bussink (@dbussink) will be giving in about 15 minutes. A huge congrats to my friend Dan and the rest of the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://thinkinginrails.com/wp-content/uploads/2010/06/dm-1-release.png"><img class="alignright size-medium wp-image-564" title="DataMapper 1.0 release" src="http://thinkinginrails.com/wp-content/uploads/2010/06/dm-1-release-248x300.png" alt="DataMapper 1.0 release" width="248" height="300" /></a>Well, as of right now there aren&#8217;t any release notes or website update, but Dan Kubb (@<a href="http://twitter.com/dkubb">dkubb</a>) has tagged the 1.0 release of <a href="http://datamapper.org">DataMapper</a>.  This is for the talk at <a href="http://www.railsconf.com/">RailsConf</a> today that Dirkjan Bussink (@<a href="http://twitter.com/dbussink">dbussink</a>) will be giving in about 15 minutes.</p>
<p>A huge congrats to my friend Dan and the rest of the DataMapper team as I know this has been a colossal amount of work to get a project like this to the 1.0 state, especially with the amount of stability and test coverage that the project has.</p>
<p><strong>Update:</strong> The slides from the talk are <a href="http://www.slideshare.net/dbussink/datamapper-railsconf2010">up here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/06/datamapper-1-0-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Database and Performance In Web Applications</title>
		<link>http://thinkinginrails.com/2010/05/database-and-performance-in-web-applications/</link>
		<comments>http://thinkinginrails.com/2010/05/database-and-performance-in-web-applications/#comments</comments>
		<pubDate>Mon, 17 May 2010 12:33:32 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Design]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=478</guid>
		<description><![CDATA[This is sort of a follow up to my last post about caching.  One thing I discovered after chatting with @dkubb was that while caching was a fantastic help to make the site faster, but it was really just covering up the actual issue. As he&#8217;s a bit of a database guy, he looked at [...]]]></description>
			<content:encoded><![CDATA[<p>This is sort of a follow up to my last <a href="http://thinkinginrails.com/2010/05/when-and-where-to-use-caching-in-rails/">post about caching</a>.  One thing I discovered after chatting with <a href="http://twitter.com/dkubb">@dkubb</a> was that while caching was a <em>fantastic</em> help to make the site faster, but it was really just covering up the <strong>actual</strong> issue.</p>
<p>As he&#8217;s a bit of a <a href="http://datamapper.org">database guy</a>, he looked at some of the things I was doing and showed me some good performance testing tools (more on that in a second) and discovered that there was a <em>lot</em> of slowdown from things like repetitive DB calls and repetitive DB calls on unindexed data.  Anyway, it was fairly eye opening to someone who hasn&#8217;t done a huge amount of work with high-traffic sites, and has been blindly believing that since it seems to &#8220;just work&#8221; it should &#8220;just work&#8221; no matter what the situation is.  I figure I&#8217;d list out a few techniques and commands you can use to deal with your own scaling problems <em>before</em> they become problems.</p>
<p>As always, I&#8217;d suggest you actually ignore the rest of this post as it&#8217;s going to be a lot of naval gazing, and instead go and watch the <a href="http://railslab.newrelic.com/scaling-rails">Scaling Rails podcast</a> series <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>How Do I Tell If There&#8217;s a Problem</strong></p>
<p><a href="http://thinkinginrails.com/wp-content/uploads/2010/05/database-integration.jpg"><img class="alignright size-medium wp-image-490" title="database-integration" src="http://thinkinginrails.com/wp-content/uploads/2010/05/database-integration-300x225.jpg" alt="" width="300" height="225" /></a>First thing I did was enable the <a href="http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html">slow query log in MySQL</a>, assuming that&#8217;s your database of choice.  If you have a modern version, set the threshold very low, I have mine set for 0.05.  This means that any query that takes more than 50 milliseconds will be logged.  If you have an older MySQL you may need to <a href="http://hackmysql.com/microsecond_slow_logs">patch it to allow microsecond support</a> older versions only support down t0 1 second.  Depending on how bad things are, even a resolution of 1 second or slower can be a huge help.</p>
<p>When MySQL is restarted, the logs may look something like this (possibly, as it was in my case, <strong>lots</strong> of messages like these):</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"># <span style="color: #993333; font-weight: bold;">USER</span>@Host: db<span style="color: #66cc66;">&#91;</span>db<span style="color: #66cc66;">&#93;</span> @ localhost <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span>
# Query_time: <span style="color: #cc66cc;">0</span>  Lock_time: <span style="color: #cc66cc;">0</span>  Rows_sent: <span style="color: #cc66cc;">1</span>  Rows_examined: <span style="color: #cc66cc;">37</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> id
<span style="color: #993333; font-weight: bold;">FROM</span>   page_content
<span style="color: #993333; font-weight: bold;">WHERE</span>  <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span> content_order <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span> <span style="color: #993333; font-weight: bold;">AND</span> page_id <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> content_order;</pre></div></div>

<p>This shows you the database (helpful if you have more than one), how long it took (I assume to a resolution of seconds), how many rows the query looked at (more on this in a second) and the actual db that was run.</p>
<p>Ok, not bad, now we have two things, first is a metric to run by.  If you don&#8217;t know how to determine how bad things are, it&#8217;s really hard to figure out if you&#8217;ve fixed it.  In this case I used the slow query log as the metric, if it was empty, the issue is &#8220;fixed&#8221;, if there are entries going into there, that means that the queries are slow and there is something to go after, either through design or database indexes.</p>
<p><strong>Using &#8220;Explain&#8221; and Database Indexes</strong></p>
<p>The first thing I saw in my case was that each time I loaded an item, to get it&#8217;s image it had to make one of these queries.  Kinda sucky.  Now realize that the gallery is showing 48 images on each page.  So 48 items each looking through 5600+ rows to get their thumbnails.  I&#8217;ll let you do the math, but it equals<em>really sucky</em> however you do it.  So how to determine exactly where the error is and how to fix it, or at least make it better.</p>
<p>So the above error in the slow log tells us the most important thing, the query being run.  So what I did was take that and run it in the MySQL command line.  Unsurprisingly, it displayed the one row that was expected.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">SELECT</span> id <span style="color: #993333; font-weight: bold;">FROM</span>
   page_content <span style="color: #993333; font-weight: bold;">WHERE</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>content_order <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span> <span style="color: #993333; font-weight: bold;">AND</span> page_id <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
   <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> content_order;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+</span>
<span style="color: #66cc66;">|</span> id <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+</span>
<span style="color: #66cc66;">|</span>  <span style="color: #cc66cc;">5</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+</span>
<span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">ROW</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.00</span> sec<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Next step, why did it take so long.  Running the MySQL built in command &#8216;explain&#8217; before your query will give you some interesting information.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">EXPLAIN</span> <span style="color: #993333; font-weight: bold;">SELECT</span> id <span style="color: #993333; font-weight: bold;">FROM</span>
    page_content <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>content_order <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span> <span style="color: #993333; font-weight: bold;">AND</span> page_id <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> content_order;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+---------------+------+---------+------+------+-------------+</span>
<span style="color: #66cc66;">|</span> id <span style="color: #66cc66;">|</span> select_type <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">TABLE</span>        <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">TYPE</span> <span style="color: #66cc66;">|</span> possible_keys <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">|</span> key_len <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">REF</span>  <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">ROWS</span> <span style="color: #66cc66;">|</span> Extra       <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+---------------+------+---------+------+------+-------------+</span>
<span style="color: #66cc66;">|</span>  <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span> SIMPLE      <span style="color: #66cc66;">|</span> page_content <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">ALL</span>  <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span>          <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">|</span>    <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">|</span>   <span style="color: #cc66cc;">37</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">USING</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+---------------+------+---------+------+------+-------------+</span>
<span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">ROW</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.00</span> sec<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>What does this mean?  It means that to find the content entry for this page, the database had to go through 37 rows of data, and there were no possible keys (database indexes) for it to try to look through.  Another thing <a href="http://dev.mysql.com/doc/refman/5.0/en/using-explain.html">I&#8217;m told to watch out</a> for is &#8220;filesort&#8221; in the &#8220;extra&#8221; column, which means the system is doing extra work that will slow it down.</p>
<p><strong>How To Fix This</strong></p>
<p>Let me prefix this next bit of discussion  by saying I&#8217;m not a <a href="http://en.wikipedia.org/wiki/DBA">DBA</a>, and know there&#8217;s  way more to things like creating database indexes than what I&#8217;m  presenting here, and that depending on what you do, you could make  performance <em>worse</em> if you add too many indexes.</p>
<p>Now 37 isn&#8217;t all that bad, but it&#8217;s a scaling issue, so lets say the client puts more and more content on it, with no indexes on the database you get what&#8217;s called an On problem.  That is, the more database rows you have, the more it has to search through.  In fact, it&#8217;s pretty much the definition of &#8220;doesn&#8217;t scale&#8221; <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>A database index basically is a look-up table for queries.  It lets the database say &#8220;give me the data for conditions XYZ&#8221; and the database simply hands back the correct data.  Without indexes the database has to go through each row in the table to find the data matching the given conditions.   In this case I had of course an index on the primary key of this content table, but I had forgotten that it would be accessed primarily through the main &#8220;content_id&#8221; field, which does not have an index on it.  Oops, lets rectify this now:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">INDEX</span> page_content_page_id_index
    <span style="color: #993333; font-weight: bold;">ON</span> page_content<span style="color: #66cc66;">&#40;</span>page_id<span style="color: #66cc66;">&#41;</span>;
Query OK<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">37</span> <span style="color: #993333; font-weight: bold;">ROWS</span> affected <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.05</span> sec<span style="color: #66cc66;">&#41;</span>
Records: <span style="color: #cc66cc;">37</span>  Duplicates: <span style="color: #cc66cc;">0</span>  Warnings: <span style="color: #cc66cc;">0</span></pre></div></div>

<p>And run the &#8220;explain&#8221; command again:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">EXPLAIN</span> <span style="color: #993333; font-weight: bold;">SELECT</span> id <span style="color: #993333; font-weight: bold;">FROM</span>
    page_content <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>content_order <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span> <span style="color: #993333; font-weight: bold;">AND</span> page_id <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> content_order;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+----------------------------+----------------------------+---------+-------+------+-------------+</span>
<span style="color: #66cc66;">|</span> id <span style="color: #66cc66;">|</span> select_type <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">TABLE</span>        <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">TYPE</span> <span style="color: #66cc66;">|</span> possible_keys              <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">KEY</span>                        <span style="color: #66cc66;">|</span> key_len <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">REF</span>   <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">ROWS</span> <span style="color: #66cc66;">|</span> Extra       <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+----------------------------+----------------------------+---------+-------+------+-------------+</span>
<span style="color: #66cc66;">|</span>  <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span> SIMPLE      <span style="color: #66cc66;">|</span> page_content <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">REF</span>  <span style="color: #66cc66;">|</span> page_content_page_id_index <span style="color: #66cc66;">|</span> page_content_page_id_index <span style="color: #66cc66;">|</span>       <span style="color: #cc66cc;">4</span> <span style="color: #66cc66;">|</span> const <span style="color: #66cc66;">|</span>    <span style="color: #cc66cc;">2</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">USING</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+----------------------------+----------------------------+---------+-------+------+-------------+</span>
<span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">ROW</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.00</span> sec<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>So the big thing to look at here is the number of rows examined, 2.  Pretty damn good, but why were there 2?  This is because there are two rows with page_id = 1 and only 1 with content_order = 1.  A further optimization we can do is to add this index:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">INDEX</span> page_content_page_id_content_order_index
    <span style="color: #993333; font-weight: bold;">ON</span> page_content<span style="color: #66cc66;">&#40;</span>page_id<span style="color: #66cc66;">,</span>content_order<span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>This creates an index on the page_id <em>and</em> content_order fields.  Now when we do our query (slightly edited for width) we get:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">EXPLAIN</span> <span style="color: #993333; font-weight: bold;">SELECT</span> id <span style="color: #993333; font-weight: bold;">FROM</span>
    page_content <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>content_order <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span> <span style="color: #993333; font-weight: bold;">AND</span> page_id <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> content_order;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+--------------------------------+------------------------------------------+---------+-------------+------+-------------+</span>
<span style="color: #66cc66;">|</span> id <span style="color: #66cc66;">|</span> select_type <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">TABLE</span>        <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">TYPE</span> <span style="color: #66cc66;">|</span> possible_keys                  <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">KEY</span>                                      <span style="color: #66cc66;">|</span> key_len <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">REF</span>         <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">ROWS</span> <span style="color: #66cc66;">|</span> Extra       <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+--------------------------------+------------------------------------------+---------+-------------+------+-------------+</span>
<span style="color: #66cc66;">|</span>  <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span> SIMPLE      <span style="color: #66cc66;">|</span> page_content <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">REF</span>  <span style="color: #66cc66;">|</span> page_content_page_id_index<span style="color: #66cc66;">,...</span> <span style="color: #66cc66;">|</span> page_content_page_id_content_order_index <span style="color: #66cc66;">|</span>       <span style="color: #cc66cc;">8</span> <span style="color: #66cc66;">|</span> const<span style="color: #66cc66;">,</span>const <span style="color: #66cc66;">|</span>    <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">USING</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+-------------+--------------+------+--------------------------------+------------------------------------------+---------+-------------+------+-------------+</span></pre></div></div>

<p>Now the number of rows examined to find the results of the query is 1, down from 2, so a win right?  Well, yes and no.  Down this path <em>could</em> lie madness.  You don&#8217;t want to create indexes on every single combination because as you increase the number of indexes you up the time that the database takes to find the results.  Or something like that, I&#8217;m honestly a bit fuzzy on the whole thing, but I do know that you don&#8217;t want to add a bazillion database indexes if you can avoid it.</p>
<p><strong>Conclusion</strong></p>
<p>As I said above, I&#8217;m by no means a database expert (as you can clearly see from the original blunders I made), but the point of this was more providing you with some tips and pointers on how to do some of the troubleshooting and get yourself onto the path of better performance.  To sum it all up:</p>
<ul>
<li> Keep an eye on your logs to keep an eye out for large numbers of database queries.</li>
<li>Enable slow query logging and watch for queries that are going over a large number of rows.  Anything that&#8217;s taking more than a second (on the high end) is a big red flag.</li>
<li>Learn to love the &#8216;explain&#8217; command in MySQL and add indexes appropriately.</li>
<li>Don&#8217;t add <em>too</em> many indexes <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<p>Hope that helps you!  More tips and pointers as always, appreciated.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/05/database-and-performance-in-web-applications/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>When and Where to use Caching In Rails</title>
		<link>http://thinkinginrails.com/2010/05/when-and-where-to-use-caching-in-rails/</link>
		<comments>http://thinkinginrails.com/2010/05/when-and-where-to-use-caching-in-rails/#comments</comments>
		<pubDate>Tue, 11 May 2010 21:08:11 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Help]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=455</guid>
		<description><![CDATA[(Alternative title to this post: Rails Caching Enlightenment Through Perl) This entire post will either make you think I’m a horrible web programmer, or hopefully, show you the deep and meaningful insights that I’ve managed to eke out from the experience. Server Crashes Are Bad Last night I was up coding, but sadly, not rails [...]]]></description>
			<content:encoded><![CDATA[<p>(Alternative title to this post: <em>Rails Caching Enlightenment Through Perl</em>)</p>
<p><a href="http://thinkinginrails.com/wp-content/uploads/2010/05/copypaper.gif"></a>This entire post will either make you think I’m a horrible web programmer, or hopefully, show you the deep and meaningful insights that I’ve managed to eke out from the experience.</p>
<p><strong>Server Crashes Are Bad</strong><br />
<a href="http://thinkinginrails.com/wp-content/uploads/2010/05/6a0112796e0b0a28a40120a725222d970b.gif"><img class="alignright size-full wp-image-463" title="Angry Client" src="http://thinkinginrails.com/wp-content/uploads/2010/05/6a0112796e0b0a28a40120a725222d970b.gif" alt="" width="181" height="231" /></a>Last night I was up coding, but sadly, not rails code. Yesterday I had a call from a client telling me that the website had crashed, and <em>their</em> clients were pissed off because this happened just when they had put out their weekly newsletter. The server (a virtual hosted system hosted at GoDaddy) had locked up tight, rendering all the sites that were on the server un-reachable.</p>
<p>The server was rebooted, and digging into it there was no clear reason why it had crashed, which is of course not what they wanted to hear. I had a development server set up at home, so I did a bit of testing to see if I could duplicate it. The server was old and slow (not even dual core), but usable as a Linux workstation, so I figured that if I could make the site feel faster here, the gains on the production server would be huge.</p>
<p><strong>Determining A Baseline</strong><br />
First was to hit it with the trusted <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">Apache Benchmark</a> utility, I started with a perfectly reasonable 10 concurrent connections for 1000 hits hitting the landing page that was sent out in the newsletter, and probably one of the more intensive pages DB and logic wise on the site.</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ ab -c 10 -n 1000 “http://site.com/page.html?id=117”</pre></div></div>

<p>Looking at my system monitor, I immediately saw my CPU use jump to 100%, disk access go from a blip here and there to constant, and the machine ground to a halt.</p>
<p>I hit ctrl-c pretty fast.</p>
<p>OK, problem found, the site is a vampire and sucks the life out of the server. I played with a few different settings and eventually ended up using 5 concurrent connections and 20 hits “-c 5 -n 20” which gave me an average 2000-4000ms to serve pages, about 1 request a second.</p>
<p>Horrible right? Before you put me against the wall to keep me from doing <em>any</em> web programming again, remember this is a really old server. Please? Maybe one smoke before it’s time for me to go?</p>
<p><strong>Small Fixes, Small Gains</strong><br />
So there were three things that I figured I needed to look at:</p>
<ol>
<li> Use the <a href="http://developer.yahoo.com/yslow/">YSlow </a><a href="http://developer.yahoo.com/yslow/">plugin</a> to find some small gains</li>
<li> Finally see if there are any just bad code that could be refactored out, loops within loops, useless re-calculation, etc.</li>
<li> Re-examine the number of queries going on on the page</li>
</ol>
<p>YSlow gave me a <a href="http://developer.yahoo.com/performance/rules.html">few things to do</a>. Setting the expires header for images, moving CSS and JS to the top and bottom of the page, and a couple of other minor things that gave me no real gains via ab.</p>
<p>Surprisingly, there weren’t any low hanging fruit for bad code or useless loops within loops. This sucked, mostly because that meant me going through and re-looking at SQL and refactoring that, which I’m not sure about you, but that doesn’t sound like fun to me.<br />
Somewhat more surprisingly there were only a couple of extra queries, mostly related to the ORM I was using, <a href="http://search.cpan.org/dist/Class-DBI/">Class::DBI</a> and some just silly things. Sadly none of these gave me any more gains.</p>
<p>One thing I did find was where the issues were. When I commented out the main grid of items that is the focus on the page, the page response went from 2000-4000ms response time to 200. Hmm&#8230;, so what to do with this.  What if I could make it so the time to generate the main product grid didn&#8217;t happen?  So I commented out the dynamic code, and copied in the HTML produced (from the view source window in firefox) to see if it was the dynamic generation (which wasn&#8217;t <em>really</em> that complex from what I could see).  Again, 200-400ms time, serving 9-10 requests a second, with almost no CPU or disk impact.</p>
<p>OK, so I thought what if there was a way to pre-generate the HTML periodically, and then have the perl code load that instead of doing it dynamically each time.  That almost sounds like&#8230;.. &#8220;<strong>caching</strong>&#8220;.  Huh, almost like something that should be built in.</p>
<p><strong>Enter Caching</strong><br />
<a href="http://thinkinginrails.com/wp-content/uploads/2010/05/copypaper.gif"><img class="alignright" title="Copy Paper" src="http://thinkinginrails.com/wp-content/uploads/2010/05/copypaper-300x202.gif" alt="" width="300" height="202" /></a>Honestly my experiences with caching have been minimal, most of the time I am trying to <strong>prevent</strong> caching (for re-uploaded images with the same filename, that sort of thing), and also it just hadn&#8217;t come up yet, probably because most of the sites I have worked on don&#8217;t get huge enough traffic to require it.  Luckily I had just read something about Caching in the <a href="http://www.masonhq.com/docs/manual/Devel.html">HTML::Mason developer docs</a> while finding some information for something else.</p>
<p>HTML::Mason has the concept of &#8220;components&#8221;, similar to partials in the rails world.  You&#8217;d call something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;">blah blah
<span style="color: #339933;">&lt;</span> <span style="color: #339933;">&amp;</span> <span style="color: #ff0000;">&quot;/comp/gallery.mc&quot;</span><span style="color: #339933;">,</span> id <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$id</span><span style="color: #339933;">,</span> page <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$cur_page</span><span style="color: #339933;">,</span> title <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">&quot;TiR&quot;</span> <span style="color: #339933;">&amp;&gt;</span>
blah blah</pre></div></div>

<p>When the page is rendered it would call the gallery.mc component with the given arguments, render it, running whatever code is in there (<a href="http://www.masonhq.com/">HTML::Mason</a> isn&#8217;t the nice separated MVC that Rails is, so there&#8217;s potentially lots of controller code in your pages and components) and replacing the &lt; &amp; &amp;&gt; with the output.  The documents have a nice section on the built in page and component (think fragment) <a href="http://www.masonhq.com/docs/manual/Devel.html#data_caching">caching</a> where all you need to do is to add this code to the top of your component&#8217;s &#8220;init&#8221; section:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #000066;">return</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">$m</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">cache_self</span><span style="color: #009900;">&#40;</span>key <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'fookey'</span><span style="color: #339933;">,</span> expires_in <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'3 hours'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>other options<span style="color: #339933;">...</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This lets your component see if it&#8217;s already in the cache, and not expired, and if it is, serves that, and if not, renders and then caches itself with the given key.  The only tricky part is figuring out the right cache key to ensure it&#8217;s unique for each section of code.  I ended up writing something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #0000ff;">$key</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;gallery|$id|$cur_page|$title&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">return</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">$m</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">cache_self</span><span style="color: #009900;">&#40;</span>key <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$key</span><span style="color: #339933;">,</span> expires_in <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'10 minutes'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>other options<span style="color: #339933;">...</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This makes the cache key a hash of the arguments sent to the component, ensuring that each differently rendered version of the page will get a different cache key. Not perfect I&#8217;m sure, but a nice mix of good caching and safety.</p>
<p>Running &#8216;ab&#8217; again I found that while the first couple of requests still took 2000-4000ms to run, subsequent pages were served in the 200-400ms range, and the CPU and disk load was <em>way</em> down.</p>
<p><strong>WTF &#8211; This is a Rails Blog</strong><br />
So why am I telling you all this Perl stuff? It’s because this is related more to web programming and programmer mindset than Perl or HTML::Mason.  You could replace &#8220;perl&#8221; with &#8220;ruby&#8221;, &#8220;component&#8221; with &#8220;partial&#8221; and &#8220;HTML::Mason&#8221; with &#8220;Rails&#8221; and get the same idea.</p>
<p>Because everything ran fine when the site was under development and only two or three people were hitting it I didn&#8217;t have to worry about caching or performance issues.  In fact, I didn&#8217;t even <strong>think</strong> about performance because thigns &#8220;just worked&#8221;.  When things did go badly (again, server crashes == pissed off clients), I had to scramble to find a solution (luckily only one night of work).</p>
<p>I&#8217;m still doing testing with the new caching code, but I expect to put it online tonight or tomorrow, and look forward to the before and after numbers on the production server.</p>
<p><strong>Lessons Learned</strong><br />
My lessons learned:</p>
<ul>
<li> Watch <strong>from the start</strong> for cachable pieces of code.  Big complex SQL queries or complex logic that can be created once a week, day or even every minute is a candidate.  In Rails it can be as simple as surrounding the code with &lt; % cache do %&gt; .. &lt; % end %&gt;.</li>
<li> Test performance from the onset.  Learn to love <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">Apache Benchmark</a> and start hitting your sites potential hot pages from the start, and watch and learn what causes reponsiveness to go down.</li>
</ul>
<p><strong>Resources</strong><br />
For those of you wanting some actual <em>rails</em> resources to learn more about this stuff, have a look at the following:</p>
<ul>
<li> <a href="http://www.cyberciti.biz/tips/howto-performance-benchmarks-a-web-server.html">Understanding &#8216;ab&#8217; results</a> &#8211; Nice resource for how to read that output.</li>
<li> <a href="http://guides.rails.info/caching_with_rails.html">Caching with Rails</a> &#8211; The rails guides documentation with details on page, fragment, action caching and everything in between.</li>
<li> <a href="http://thewebfellas.com/blog/2008/6/9/rails-2-1-now-with-better-integrated-caching">Rails 2.1 Caching</a> &#8211; A bit older, but a nice list of the caching capabilities introduced and available in Rails 2.1, still pretty relevant.</li>
<li> <a href="http://railslab.newrelic.com/scaling-rails">The Scaling Rails Podcast Series</a> &#8211; Fantastic information in here, I recommend watching all of them, if you can&#8217;t, hit #2, 3, 5, 6, 7 for caching, and then #15 and 16 for load testing with ab and friends.</li>
</ul>
<div>Any other resources or hints as to how to deal with caching in Rails (or Perl for that matter! <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ?</div>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/05/when-and-where-to-use-caching-in-rails/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>More on Using Enums For Constant Data in Rails</title>
		<link>http://thinkinginrails.com/2010/04/more-on-using-enums-for-constant-data-in-rails/</link>
		<comments>http://thinkinginrails.com/2010/04/more-on-using-enums-for-constant-data-in-rails/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 04:53:55 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Database]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=277</guid>
		<description><![CDATA[So I got around to rollowing tip #3 on using Enums in AR, and found it worked&#8230;. mostly.  The problem comes in where the value isn&#8217;t already set.  I started with this in my model: # game.rb # at the top of the file, define the list of genders GENDERS = %w&#40; boy girl coed [...]]]></description>
			<content:encoded><![CDATA[<p>So I got around to rollowing <a href="http://zargony.com/2008/04/28/five-tips-for-developing-rails-applications">tip #3</a> on using Enums in AR, and found it worked&#8230;. <em>mostly</em>.  The problem comes in where the value isn&#8217;t already set.  I started with this in my model:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># game.rb</span>
  <span style="color:#008000; font-style:italic;"># at the top of the file, define the list of genders</span>
  GENDERS = <span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#40;</span> boy girl coed <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#008000; font-style:italic;"># and validations for it</span>
  validates_inclusion_of <span style="color:#ff3333; font-weight:bold;">:gender</span>,   :<span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">Game::GENDERS</span>, <span style="color:#ff3333; font-weight:bold;">:on</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:create</span>, <span style="color:#ff3333; font-weight:bold;">:message</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;extension %s is not included in the list&quot;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># finally define the gender as a symbol for lookups</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> gender
     read_attribute<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:gender</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_sym</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> gender=<span style="color:#006600; font-weight:bold;">&#40;</span>value<span style="color:#006600; font-weight:bold;">&#41;</span>
    write_attribute<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:gender</span>, value.<span style="color:#5A0A0A; font-weight:bold;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This works fine until you have a nil value for gender.  OK, next step, just check if the value is nil before you read it and return nil if it is.  Only thing is that if you were to add something like</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">gender</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">nil</span></pre></div></div>

<p>But then you get an ugly &#8220;stack level too deep&#8221; error, because when you call &#8216;self.gender&#8217; it&#8217;s calling the gender method, which checks to see if self.gender is nil, which calls the gender method, which&#8230; well, you get the picture.</p>
<p>Took a bit of looking, and I&#8217;m not sure if this is the &#8220;correct&#8221; solution, but it does work properly.  I just modified the gender method as such:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#game.rb</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> gender
    attributes = attributes_before_type_cast
    <span style="color:#9966CC; font-weight:bold;">if</span> attributes<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;gender&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      read_attribute<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:gender</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_sym</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#0000FF; font-weight:bold;">nil</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This uses the <a href="http://apidock.com/rails/ActiveRecord/Base/attributes_before_type_cast">attributes_before_type_cast</a> grabs all attributes into a hash (before they are mangled by whatever ActiveRecord does), checks to see if the &#8216;gender&#8217; attribute is filled in and either returns it or nil.  Depending on if you&#8217;re learning or not, you may want to just check out the <a href="http://github.com/zargony/activerecord_symbolize">activerecord_symbolize</a> plugin though <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>All working, and ready to commit to the main branch.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/04/more-on-using-enums-for-constant-data-in-rails/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Quick Way To Experiment With ActiveRecord</title>
		<link>http://thinkinginrails.com/2010/04/quic-way-to-experiment-with-activerecord/</link>
		<comments>http://thinkinginrails.com/2010/04/quic-way-to-experiment-with-activerecord/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 05:36:42 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Database]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=226</guid>
		<description><![CDATA[A while back I spent a fair amount of time with the Pro Active Record book, learning all about dynamic finders, associations, validations, and all the other magic it has, sometimes it was a bit of a pain to set everything up by hand, typing out the .rb model files, creating the databases, etc.  I [...]]]></description>
			<content:encoded><![CDATA[<p>A while back I spent a fair amount of time with the Pro Active Record book, learning all about dynamic finders, associations, validations, and all the other magic it has, sometimes it was a bit of a pain to set everything up by hand, typing out the .rb model files, creating the databases, etc.  I figured, why do all that work (yea yea, I know it&#8217;s just typing out some text) when you have the power of rails, generators and rake at your disposal.  So what I&#8217;d do is simply use the rails generators.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ rails <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #7a0874; font-weight: bold;">test</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
$ script<span style="color: #000000; font-weight: bold;">/</span>generate model User name:string age:integer
<span style="color: #7a0874; font-weight: bold;">&#91;</span>...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
$ rake db:create <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> rake db:migrate
$ <span style="color: #c20cb9; font-weight: bold;">vi</span> app<span style="color: #000000; font-weight: bold;">/</span>models<span style="color: #000000; font-weight: bold;">/</span>user.rb <span style="color: #666666; font-style: italic;"># optional</span>
$ script<span style="color: #000000; font-weight: bold;">/</span>console</pre></div></div>

<p><a href="http://www.amazon.ca/gp/product/1590598474?ie=UTF8&amp;tag=k2bl-20&amp;linkCode=as2&amp;camp=15121&amp;creative=330641&amp;creativeASIN=1590598474"><img src="/images/51SIrXLuMxL._SL160_.jpg" border="0" alt="" align="right" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.ca/e/ir?t=k2bl-20&amp;l=as2&amp;o=15&amp;a=1590598474" border="0" alt="" width="1" height="1" /></p>
<p>Voila!  Four commands and you&#8217;re in an interactive shell that will let you manipulate your models, add data, run finds, etc.  No need to deal with anything other than an already set up database and model file, and you have a nice interactive shell to boot.</p>
<p>Best part?  Just do an &#8220;rm -rf &lt;directory&gt;&#8221; when you&#8217;re done to nuke the directory and either start again or try out the next experiment.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/04/quic-way-to-experiment-with-activerecord/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Querying Multiple Tables With ActiveRecord</title>
		<link>http://thinkinginrails.com/2010/04/querying-multiple-tables-with-activerecord/</link>
		<comments>http://thinkinginrails.com/2010/04/querying-multiple-tables-with-activerecord/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 21:42:58 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=200</guid>
		<description><![CDATA[The other day at work I was doing some data mining for our business intelligence folks. They needed to get some stats from the last year of billing transactions, and the task came to me. I had to hack up a perl script to query the archived data to find a certain type of transaction. [...]]]></description>
			<content:encoded><![CDATA[<p>The other day at work I was doing some data mining for our business intelligence folks.  They needed to get some stats from the last year of billing transactions, and the task came to me.  I had to hack up a perl script to query the archived data to find a certain type of transaction.  Easy enough, the only minor issue was that since the data set was both huge and old, the table were broken up by month.</p>
<p>My perl script looked something like this (cleaned up for brevity):</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #0000ff;">@months</span> <span style="color: #339933;">=</span> <span style="color: #000066;">qw</span><span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">200901</span> <span style="color: #cc66cc;">200902</span> <span style="color: #cc66cc;">200903</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;"># up to 201004</span>
<span style="color: #0000ff;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;select * from BillingMONTH where resultCode=40&quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$month</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">@months</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #0000ff;">$sql_full</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$sql</span><span style="color: #339933;">;</span>
<span style="color: #0000ff;">$sql_full</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/MONTH/$month/</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;"># change the table name for each record</span>
<span style="color: #0000ff;">$sth</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$dbh</span><span style="color: #339933;">-</span><span style="color: #0000ff;">&amp;gt</span><span style="color: #339933;">;</span>prepare<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$sql_full</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">or</span> <span style="color: #000066;">die</span><span style="color: #339933;">;</span>
<span style="color: #0000ff;">$sth</span><span style="color: #339933;">-</span><span style="color: #0000ff;">&amp;gt</span><span style="color: #339933;">;</span>execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900;">&#93;</span> <span style="color: #666666; font-style: italic;"># retrieve the data, save/process it</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I started wondering if these sorts of quick and dirty, but non-trivial scripts were easily doable in Ruby using Active Record.</p>
<p>I set up a similar situation on my system, a mysql database with 3 tables and a couple of rows of garbage data in them.  I knew that I could get a database connection set up very fast by making a throwaway rails app, setting up the models in it, and then using script/console as my interface, but I&#8217;ve honestly never use activerecord in a <em>scripting</em> environment.</p>
<p>After some messing around I came up with this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#!/usr/bin/ruby</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'active_record'</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">establish_connection</span><span style="color:#006600; font-weight:bold;">&#40;</span>
   <span style="color:#ff3333; font-weight:bold;">:adapter</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;mysql&quot;</span>,
   <span style="color:#ff3333; font-weight:bold;">:username</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;root&quot;</span>,
   <span style="color:#ff3333; font-weight:bold;">:password</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;password&quot;</span>,
   <span style="color:#ff3333; font-weight:bold;">:database</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;test&quot;</span>
<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;">Test</span> <span style="color:#006600; font-weight:bold;">&amp;</span>lt; <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span> 
<span style="color:#9966CC; font-weight:bold;">end</span> 
&nbsp;
<span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#40;</span> Archive201001 Archive201002 Archive201003 <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>tablename<span style="color:#006600; font-weight:bold;">|</span>
   res = <span style="color:#CC00FF; font-weight:bold;">Test</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:from</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; tablename, <span style="color:#ff3333; font-weight:bold;">:conditions</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;name like 'test%'&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>;
   <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Total results from #{tablename}: #{res.size.to_s}&quot;</span>
   <span style="color:#008000; font-style:italic;"># [...] other awesome processing on the res object</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Running it gives me:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">alan@phoenix:~/code/ruby$ ./testdb.rb
Total results from Archive201001: 3
Total results from Archive201002: 6
Total results from Archive201003: 3</pre></div></div>

<p>Whohoo!  The one thing I couldn&#8217;t figure out is how to get rid of having to create a sub-class of the ActiveRecord::Base class.  I technically can do it with:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">connection</span>.<span style="color:#9900CC;">execute</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;select * from #{tablename}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>But I don&#8217;t know how to get this into the &#8220;object oriented&#8221; version to use the :conditions and <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder and such.  However, the main point of can I replace perl and DBI for quick and dirty database scripting has most definitively been answered.</p>
<p>Next step: seeing how to do the same thing in <a href="http://datamapper.org/">Data Mapper</a> (to keep <a href="http://twitter.com/dkubb">@dkubb</a> happy) <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/04/querying-multiple-tables-with-activerecord/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating Rails Database Initialization Files</title>
		<link>http://thinkinginrails.com/2010/04/creating-rails-database-initialization-files/</link>
		<comments>http://thinkinginrails.com/2010/04/creating-rails-database-initialization-files/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 05:48:10 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=163</guid>
		<description><![CDATA[When I first started learning Rails, my database setup and migrations looked something like this: $ script/generate model Person name:string dob:date $ rake db:migrate &#91;... oh crap, I guess I need login credentials too...&#93; $ script/generate migration add_username_and_password_to_person username:string password:string $ rake db:migrate &#91;... better do it right, and make it properly salted like I [...]]]></description>
			<content:encoded><![CDATA[<p>When I first started learning Rails, my database setup and migrations looked something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">$ script<span style="color:#006600; font-weight:bold;">/</span>generate model Person name:<span style="color:#CC0066; font-weight:bold;">string</span> dob:date
$ rake db:migrate
<span style="color:#006600; font-weight:bold;">&#91;</span>... <span style="color:#9900CC;">oh</span> crap, I guess I need login credentials too...<span style="color:#006600; font-weight:bold;">&#93;</span>
$ script<span style="color:#006600; font-weight:bold;">/</span>generate migration add_username_and_password_to_person username:<span style="color:#CC0066; font-weight:bold;">string</span> password:<span style="color:#CC0066; font-weight:bold;">string</span>
$ rake db:migrate
<span style="color:#006600; font-weight:bold;">&#91;</span>... <span style="color:#9900CC;">better</span> <span style="color:#9966CC; font-weight:bold;">do</span> it right, <span style="color:#9966CC; font-weight:bold;">and</span> make it properly salted like I should...<span style="color:#006600; font-weight:bold;">&#93;</span>
$ script<span style="color:#006600; font-weight:bold;">/</span>generate migration add_salt_to_person salt:<span style="color:#CC0066; font-weight:bold;">string</span>
$ rake db:migrate
<span style="color:#006600; font-weight:bold;">&#91;</span>... <span style="color:#9900CC;">oops</span>, there are a couple of other fields I need too...<span style="color:#006600; font-weight:bold;">&#93;</span>
$ script<span style="color:#006600; font-weight:bold;">/</span>generate migration add_misc_to_person notes:text is_admin:boolean is_manager:boolean
$ rake db:migrate
<span style="color:#006600; font-weight:bold;">&#91;</span>... <span style="color:#9900CC;">no</span>, need to <span style="color:#9966CC; font-weight:bold;">do</span> better role based management...<span style="color:#006600; font-weight:bold;">&#93;</span>
$ script<span style="color:#006600; font-weight:bold;">/</span>generate migration remove_is_admin_and_is_manager_from_person
$ script<span style="color:#006600; font-weight:bold;">/</span>generate migration add_role_to_person role_id:<span style="color:#CC0066; font-weight:bold;">integer</span>
$ rake db:migrate</pre></div></div>

<p>Ugh!</p>
<p>And that&#8217;s just to get the start of the project!  I&#8217;m sure I&#8217;m not the only one this has happened to as well.  The downsides are that at the end of the day you end up with a messy set of files in your db/migrate, it <em>feels</em> messy, and lets face it, it&#8217;ll make things harder to figure out when you go back and look at this in six months.</p>
<p>Someone suggested to me a while back to just use the initial migration file, and then going back and editing it, using db:rollback or db:reset to remove changes from your database (the latter would assume that right now there aren&#8217;t any other migrations you have to worry about).  You may need the <a href="http://dizzy.co.uk/ruby_on_rails/cheatsheets/rails-migrations">migrations cheat sheet</a> to get some of the subtle points, but the &#8220;thinking&#8221; process above would look something like:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">$ script<span style="color:#006600; font-weight:bold;">/</span>generate model Person name:string dob:date
$ rake db:migrate
<span style="color:#006600; font-weight:bold;">&#91;</span>...<span style="color:#006600; font-weight:bold;">&#93;</span>
$ rake db:rollback <span style="color:#008000; font-style:italic;"># undo the last migration</span>
$ vi db<span style="color:#006600; font-weight:bold;">/</span>migration<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006666;">20100407161025</span>_create_people.<span style="color:#9900CC;">rb</span>
$ rake db:migrate <span style="color:#008000; font-style:italic;"># re-run the migration</span>
<span style="color:#006600; font-weight:bold;">&#91;</span>...<span style="color:#006600; font-weight:bold;">&#93;</span>
$ rake db:rollback
$ !vi <span style="color:#008000; font-style:italic;"># repeat the last vi command</span>
$ rake db:migrate
<span style="color:#006600; font-weight:bold;">&#91;</span>...<span style="color:#006600; font-weight:bold;">&#93;</span>
$ rake db:rollback
etc....</pre></div></div>

<p>At the end everything would be based off of that one migration file &#8220;20100407161025_create_people.rb&#8221;.  Note that you can find the current version of the scheme in the db/schema.rb file.</p>
<p>This isn&#8217;t perfect, as you may want to target a specific file or model.  IE: just keep on testing and rebuilding your Person model with new fields.  To do this you want to be able to find the target version to migrate up/down to.  You&#8217;d have to (I think anyway, please let me know if there&#8217;s a better way to do this) run the &#8220;rake db:migrate:down VERSION=xxx&#8221; (in this case xxx = 20100407161025, the number from the filename above) to delete anything in that file (in this case you&#8217;d want to have your full Person model defined) and then &#8220;rake db:migrate:up VERSION=xxx&#8221; to re-do that specific set of database additions (anything in the &#8216;up&#8217; function).</p>
<p>Best part is that because you&#8217;re targeting a specific version and telling the system to up/down it, you aren&#8217;t resetting the version number the system knows the database is up to, so you can add other migrations after and not worry about issues running &#8220;rake db:migrate&#8221; after.  IE: The system will do The Right Thing.</p>
<p>Sadly it looks like you can&#8217;t just rename your migration file &#8220;001_people.rb&#8221; as the name of the file is closely matched to what&#8217;s inside.  With the 001_people filename it will complain about &#8220;uninitialized constant People&#8221; unless you change the class inside the file to match the &#8220;railsy&#8221; naming convention.  Check out the <a href="http://guides.rubyonrails.org/migrations.html#running-migrations">Ruby Guide on migrations</a> for some more of the grisley details.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/04/creating-rails-database-initialization-files/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Deeper Into ActiveRecord</title>
		<link>http://thinkinginrails.com/2010/03/deeper-into-activerecord/</link>
		<comments>http://thinkinginrails.com/2010/03/deeper-into-activerecord/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 18:00:30 +0000</pubDate>
		<dc:creator>alan</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://thinkinginrails.com/?p=105</guid>
		<description><![CDATA[Things have been progressing nicely for me. As I said before, creating a new controller, action, model, or association has gone from scary black magic to &#8220;type it in without checking the syntax first&#8221;. Well, mostly anyway. The new big challenge I&#8217;m having now is getting the data out from non-trivial (though not hugely complex) [...]]]></description>
			<content:encoded><![CDATA[<p>Things have been progressing nicely for me. As I said before, creating a new controller, action, model, or association has gone from scary black magic to &#8220;type it in without checking the syntax first&#8221;.  Well, mostly anyway.</p>
<p>The new big challenge I&#8217;m having now is getting the data out from non-trivial (though not hugely complex) data model associations.  I have to find valid users&#8217; games.  Clubs have Fields, Fields have Games, and games have an Agegroup (ie: peewee, junior, etc).  Users belong to a Club and have an Agegroup.  My challenge is to connect those two sets of associations so that basically I can say:</p>
<blockquote><p>Give me all games with the same agegroup as a given user has, in the same club as the given user is in.</p></blockquote>
<p>First I had to get all the associations setup, just simple &#8220;has_one&#8221;, &#8220;has_many&#8221;, and &#8220;belongs_to&#8221; in the models.  I got it to the point that I could do things like:</p>
<p><code>Club.first.fields.first.games</code></p>
<p>This lets me know that a) my models are set up right (and honestly I thought I had them set up until I came up with this example while typing this up and found it didn&#8217;t work, and had to add a missing &#8220;has_many&#8221; to my Field model).</p>
<p>The next step was <a href="http://en.wikipedia.org/wiki/Interactive_Ruby_Shell">IRB</a>, in fact, living in IRB for a night.  Well, a bit more than a night actually.  This lets you do the code/test/results/try-again cycle way faster than editing a controller and reloading a webpage.  Man I wish we had this thing for my Perl programming with the <a href="http://search.cpan.org/dist/Class-DBI/lib/Class/DBI.pm">Class::DBI</a> <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">ORM</a>.</p>
<p>The next thing I found that&#8217;s been a big help was from <a href="http://weblog.jamisbuck.org/2007/1/8/watching-activerecord-do-it-s-thing">this James Buck</a> post on ActiveRecord logging.  It&#8217;s important to run this as the first command when you start up IRB, and it&#8217;ll display the SQL being executed, a <em>huge</em> help for seeing how things like :joins and :includes affect your queries.</p>
<p>Now don&#8217;t get me wrong, I can get the data out easily.  I can either hardcode the SQL and it&#8217;s ugly joins into the Model, or I can do it all in &#8220;pure&#8221; ActiveRecord with multiple calls and arrays (ie: get a list of fields, get a list of games from that, iterate through the list of games and grab the ones matching the age condition), but my real goal here (other than getting deeper into ActiveRecord of course) is to see if I can do this in &#8220;pure&#8221; ActiveRecord, in one line (must be the Perl programmer in me).</p>
<p>The secret it turns out, is reversing your thinking.  Instead of trying to figure out how the queries and relationships work &#8220;up&#8221; the chain, from the games, finding the fields they belong to, and if they belong to the club, I wondered why I couldn&#8217;t just get a list of all the games in a club.  This was the key.</p>
<p>I couldn&#8217;t relate a club to it&#8217;s games directly, because they belonged to an intermediate model, fields.  I had to relate a club to it&#8217;s games <strong><em>through</em></strong> another model.  So after adding this to the Club model:</p>
<p><code>has_many   :games, :through =&gt; :fields</code></p>
<p>I could run</p>
<p><code>Club.first.games</code></p>
<p>and get a result, and from there it was an easy step to:</p>
<p><code>User.first.club.games.find_by_age_id(1)</code></p>
<p>Which is ugly, but when it&#8217;s put into &#8220;real&#8221; code it&#8217;ll look somewhat nicer, something along the lines of:</p>
<p><code><br />
@user = User.find_by_id(params[:user])<br />
@games = @user.club.games.find( :all, :conditions =&gt; { :age_id =&gt; @user.age_id } )<br />
</code></p>
<p>Oddly enough, &#8220;find.all( &#8230; )&#8221; <em>doesn&#8217;t</em> work, but that&#8217;s a battle for another day <img src='http://thinkinginrails.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://thinkinginrails.com/2010/03/deeper-into-activerecord/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

