<?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>Straylight Run &#187; mysql</title>
	<atom:link href="http://blog.straylightrun.net/tag/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.straylightrun.net</link>
	<description>Software, Technology, PHP</description>
	<lastBuildDate>Tue, 11 May 2010 03:53:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Clearing The Linux Buffer Cache</title>
		<link>http://blog.straylightrun.net/2009/12/03/clearing-the-linux-buffer-cache/</link>
		<comments>http://blog.straylightrun.net/2009/12/03/clearing-the-linux-buffer-cache/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 19:22:45 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[buffer cache]]></category>
		<category><![CDATA[disk]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://blog.straylightrun.net/2009/12/03/clearing-the-linux-buffer-cache/</guid>
		<description><![CDATA[According to these Munin memory graphs, the large orange area is the OS buffer cache – a buffer the OS uses to cache plain ol’ file data on disk.&#160; The graph below shows one of our web servers after we upgraded its memory.&#160; 
 
It makes sense that most of the memory not used by [...]]]></description>
			<content:encoded><![CDATA[<p>According to these <a href="http://munin.projects.linpro.no/">Munin</a> memory graphs, the large orange area is the OS buffer cache – a buffer the OS uses to cache plain ol’ file data on disk.&#160; The graph below shows one of our web servers after we upgraded its memory.&#160; </p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Web server memory usage" border="0" alt="Web server memory usage" src="http://blog.straylightrun.net/wp-content/uploads/2009/12/zsweb001memorymonth.png" width="495" height="408" /> </p>
<p>It makes sense that most of the memory not used by apps would be used by the OS to improve disk access.&#160; So seeing the memory graphs filled with orange is generally a good thing.&#160; After a few days, I watched the orange area grow and thought, “Great!&#160; LInux is putting all that extra memory to use.”&#160; I thought in my head that maybe it was caching images and CSS files to serve to Apache.&#160; But was that true?</p>
<p><strong><u>Looking At A Different Server</u></strong></p>
<p>Here is a memory graph from one of our database servers after the RAM upgrade.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Database server memory usage" border="0" alt="Database server memory usage" src="http://blog.straylightrun.net/wp-content/uploads/2009/12/zsdb001memorymonth.png" width="495" height="408" /> </p>
<p>Again, I first thought that the OS was caching all that juicy database data from disk.&#160; The problem is that we don’t have 12GB of data, and that step pattern growth was suspiciously consistent.</p>
<p>Looking again at the web server graph, I saw giant downward spikes of blue color, where the buffer cache was emptied.&#160; (The blue is unused memory.)&#160; These occurred every day at 4 am, and on Sundays there’s a huge one.&#160; What happens every day at 4 am?&#160; The logs are rotated.&#160; And on Sundays, the granddaddy log of them all – the Apache log – is rotated.</p>
<p><strong><u>The Problem</u></strong></p>
<p>It was starting to make sense.&#160; Log files seem to take up most of the OS buffer cache on the web servers.&#160; Not optimal, I’m sure.&#160; And when they’re rotated, the data in the cache is invalidated and thus freed.</p>
<p>Here is a memory graph for one of our other database servers.</p>
<p> <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Database server memory usage" border="0" alt="Database server memory usage" src="http://blog.straylightrun.net/wp-content/uploads/2009/12/zsdb002memorymonth.png" width="495" height="408" />
</p>
<p>That step pattern growth is missing!&#160; In fact, most of RAM is unused.&#160; What is the difference between the first database server and this one?&#160; The first has the <code>`mysqldump`</code> backup.&#160; It occurs every night at 2:30 am, right when those step changes occur on its memory usage graph.</p>
<p>It was clear to me that most of the OS buffer cache was wasted on logs and backups and such.&#160; There had to be a way to tell the OS not to cache a file.&#160; </p>
<p><strong><u>The Solution</u></strong></p>
<p>Google gave me this page: <a href="http://insights.oetiker.ch/linux/fadvise.html">Improving Linux performance by preserving Buffer Cache State</a>.&#160; I copied the little C program into a file and ran it on all the <code>`mysqldump`</code> backups.&#160; Here is the what happened to the memory usage.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Database server memory usage" border="0" alt="Database server memory usage" src="http://blog.straylightrun.net/wp-content/uploads/2009/12/zsdb001memoryweek.png" width="495" height="408" /> </p>
<p>Quite a bit of buffer cache was freed.&#160; On that night’s backup, I logged the buffer cache size before the backup and after.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% cat 2008.08.21.02.30.log
Starting at Thu Aug 21 02:30:03 EDT 2008
=========================================
Cached:        4490232 kB
Cached:        5350908 kB
=========================================
Ending at Thu Aug 21 02:30:55 EDT 2008</pre></div></div>

<p>Just under a gigabyte increase in buffer cache size.&#160; What was the size of the new backup file?</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% ll 2008.08.21.02.30.sql
-rw-r--r-- 1 root root 879727872 Aug 21 02:30 2008.08.21.02.30.sql</pre></div></div>

<p>About 900MB.</p>
<p><strong><u>Did It Work?</u></strong></p>
<p>I used the C program on that page to ensure no database backups were cached by the OS.&#160; I did the same on the web servers in the <code>logrotate</code> config files.&#160; A couple days later, I checked the memory graph on the database server that performed the backup.&#160; Notice how the buffer cache did not fill up.&#160; It looked like the program worked, and the OS was free to cache more important things.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Database server memory usage" border="0" alt="Database server memory usage" src="http://blog.straylightrun.net/wp-content/uploads/2009/12/zsdb001memoryweek2.png" width="495" height="408" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.straylightrun.net/2009/12/03/clearing-the-linux-buffer-cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip Of The Day: Avoid MySQL Functions</title>
		<link>http://blog.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/</link>
		<comments>http://blog.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/#comments</comments>
		<pubDate>Wed, 23 Sep 2009 18:45:00 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[query cache]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/</guid>
		<description><![CDATA[Since I knew that the MySQL Query Cache used the literal queries as keys, it made sense that MySQL did not cache queries with certain SQL functions in them, such as this one:

1
$sql = &#34;select event_id from events where event_dt &#62;= curdate()&#34;;

Because MySQL knows that this query run today is not the same query when [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.straylightrun.net/2009/03/13/mysql-query-cache-or-vertical-partitioning-intro/">Since I knew</a> that the MySQL Query Cache used the literal queries as keys, it made sense that MySQL did not cache queries with certain SQL functions in them, such as this one:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;select event_id from events where event_dt &gt;= curdate()&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Because MySQL knows that this query run today is not the same query when it is run tomorrow. There are other SQL functions such as <code>rand()</code> and <code>unix_timestamp()</code> that will bypass the query cache. These are <a href="http://dev.mysql.com/doc/refman/5.0/en/query-cache-how.html">listed here</a>.</p>
<p>So I avoid these functions when possible by calculating the value in PHP. For example, I’d rewrite the above query as:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$date</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;select event_id from events where event_dt &gt;= '<span style="color: #006699; font-weight: bold;">$date</span>'&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.straylightrun.net/2009/09/23/tip-of-the-day-avoid-mysql-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Storing Apache Virtual Hosts In A Database</title>
		<link>http://blog.straylightrun.net/2009/07/31/storing-apache-virtual-hosts-in-a-database/</link>
		<comments>http://blog.straylightrun.net/2009/07/31/storing-apache-virtual-hosts-in-a-database/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 20:29:04 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[apr]]></category>
		<category><![CDATA[dbd]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[redhat enterprise]]></category>
		<category><![CDATA[rhel]]></category>
		<category><![CDATA[virtual host]]></category>

		<guid isPermaLink="false">http://blog.straylightrun.net/?p=219</guid>
		<description><![CDATA[At work, we had set up some wildcard virtual hosts in Apache config, and that got us by for quite some time.  But the time came when we needed finer-grained control of where to send incoming requests for different domains.  I needed to store my virtual hosts in a Mysql database, mapping domains to project [...]]]></description>
			<content:encoded><![CDATA[<p>At work, we had set up some wildcard virtual hosts in Apache config, and that got us by for quite some time.  But the time came when we needed finer-grained control of where to send incoming requests for different domains.  I needed to store my virtual hosts in a Mysql database, mapping domains to project directories.</p>
<p>I&#8217;ll spare you the problems I ran into and overcame, and just list the steps to get this done.  These instructions are based on a 64-bit, RHEL 5 server running the pre-packaged Apache server.  So if you follow these instructions on a different setup, of course, filenames, directories, versions, etc. may differ.</p>
<p><strong><span style="text-decoration: underline;">Install mod_vhost_dbd</span></strong></p>
<p>Download <a href="http://code.google.com/p/dbd-modules/"><code>dbd-modules</code></a> from Google Code.  This is a great piece of code in the form of an Apache module that uses <a href="http://httpd.apache.org/docs/2.2/mod/mod_dbd.html"><code>mod_dbd</code></a> and a DBD Mysql (or other database) driver to fetch the <code>DocumentRoot </code>for a given domain from a database.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% wget http://dbd-modules.googlecode.com/files/dbd-modules-1.0.5.zip</pre></div></div>

<p>Unzip the archive in a directory. As indicated on the website, <a href="http://code.google.com/p/dbd-modules/wiki/Building">build and install the module</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% apxs -c mod_vhost_dbd.c
% apxs -i mod_vhost_dbd.la</pre></div></div>

<p>This places <code>mod_vhost_dbd.so </code>in <code>/usr/lib64/httpd/modules</code>.  Enable both this module and <code>mod_dbd </code>by adding two lines to <code>httpd.conf</code>, or equivalently creating a new include file in<code> /etc/httpd/conf.d</code> containing these lines.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">LoadModule dbd_module modules/mod_dbd.so
LoadModule vhost_dbd_module modules/mod_vhost_dbd.so</pre></div></div>

<p>In true unit fashion, now might be a good time to restart Apache, just so you can be sure everything is working up to this point.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% service httpd restart</pre></div></div>

<p><strong><span style="text-decoration: underline;">Install Mysql DBD Driver to APR</span></strong></p>
<p>Unfortunately, on my system, the Mysql DBD driver was nowhere to be found.  I had to rebuild Apache Portable Runtime (APR) utils with the Mysql driver enabled.</p>
<p>Download <a href="http://apr.apache.org/"><code>apr</code></a> and <a href="http://apr.apache.org/"><code>apr-util</code></a> from Apache.  Note these are not the latest versions, but the versions that <span style="text-decoration: line-through;">matched the packages in</span> worked for RHEL 5.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% wget http://archive.apache.org/dist/apr-1.2.8.tar.bz2
% wget http://archive.apache.org/dist/apr-util-1.2.8.tar.bz2</pre></div></div>

<p>Unpack and untar these archives in the same parent directory.</p>
<p>Build and install APR.  Now, I do not think this is absolutely necessary, but it seems like a good idea to keep the versions in sync.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% ./configure --prefix=/usr
% make
% make install</pre></div></div>

<p>Build and install <code>apr-util</code>.  Due to licensing issues, <code>apr-util </code>does not actually contain the Mysql DBD driver until <code>apr-util-1.2.12</code>.  Prior to that version, it must be downloaded separately, and the configure script rebuilt.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% wget http://apache.webthing.com/svn/apache/apr/apr_dbd_mysql.c
% ./buildconf --with-apr=../apr-1.2.7</pre></div></div>

<p>Now for the three commands every Linux admin loves.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% ./configure --prefix=/usr --with-apr=/usr --libdir=/usr/lib64 --with-expat=builtin --with-ldap-include=/usr/include --with-ldap-lib=/usr/lib64 --with-ldap=ldap --with-mysql
% make
% make install</pre></div></div>

<p>The first time I tried this, Apache could not find any LDAP-related modules.  Adding those configure switches seemed to do the trick.  Restart Apache.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">% service httpd restart</pre></div></div>

<p>Apache should now be able to query a Mysql database to get the <code>DocumentRoot </code>for a domain.  My <code>VirtualHost</code> block looked something like this.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">&lt;VirtualHost *:80&gt;
    ServerName *.example.com
    DocumentRoot &quot;/path/to/default/document/root&quot;
&nbsp;
    DBDriver mysql
    DBDParams host=localhost,user=root,pass=secret,dbname=vhosts
&nbsp;
    DBDocRoot &quot;SELECT path FROM vhosts WHERE host = %s&quot;  HOSTNAME
&lt;/VirtualHost&gt;</pre></div></div>

<p>For more details and instructions on <a href="http://code.google.com/p/dbd-modules/wiki/mod_vhost_dbd"><code>mod_vhost_dbd</code> configuration directives, read the project wiki</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.straylightrun.net/2009/07/31/storing-apache-virtual-hosts-in-a-database/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Who Needs A Database Abstraction Layer Anyway?</title>
		<link>http://blog.straylightrun.net/2009/04/30/who-needs-a-database-abstraction-layer-anyway/</link>
		<comments>http://blog.straylightrun.net/2009/04/30/who-needs-a-database-abstraction-layer-anyway/#comments</comments>
		<pubDate>Thu, 30 Apr 2009 16:30:19 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[database abstraction]]></category>
		<category><![CDATA[database access]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[pdo]]></category>

		<guid isPermaLink="false">http://blog.straylightrun.net/2009/04/30/who-needs-a-database-abstraction-layer-anyway/</guid>
		<description><![CDATA[The typical argument for database abstraction is database portability. By abstracting the database, you are free to switch from one RDBMS to another effortlessly. Popular database abstraction layers are PEAR MDB2, ADOdb, and built-in PHP PDO library (not quite a database abstraction layer, but we&#8217;ll throw it in there anyway).
But there are three problems with [...]]]></description>
			<content:encoded><![CDATA[<p>The typical argument for database abstraction is database portability. By <i>abstracting </i>the database, you are free to switch from one RDBMS to another effortlessly. Popular database abstraction layers are <a href="http://pear.php.net/package/MDB2">PEAR MDB2</a>, <a href="http://adodb.sourceforge.net/">ADOdb</a>, and built-in <a href="http://php.net/pdo">PHP PDO</a> library (not quite a database abstraction layer, but we&#8217;ll throw it in there anyway).
<p>But there are three problems with that logic.
<ol>
<li>How often are you going to switch databases in the life of your application anyway? I don&#8217;t know if I&#8217;ve ever switched a database out from under an application. Ever.
<li>To achieve <i>true </i>database independence, you&#8217;ll need to avoid using <i>all </i>the little syntax nuances that vary from DB to DB (e.g. the MySQL LIMIT clause) and avoid <i>any </i>feature in that database that makes it interesting (e.g. say goodbye to <a href="http://blog.straylightrun.net/2009/02/09/tip-of-the-day-on-duplicate-key-update/">ON DUPLICATE KEY UPDATE</a>). Chances are, you haven&#8217;t done these things. So to switch databases, your biggest problem will<i> not </i>be having to change all the <i>mysql_* </i>calls to <i>ora_*</i> or whatever.
<li>As with any layer, when you add another layer, there will always be <i>some </i>performance impact. </li>
</ol>
<p>In light of these reasons, database dependence can be a <i>good </i>thing. You can take advantage of features in the RDBMS. And if you can make native calls directly to the extension, you&#8217;re saving a lot of code from being executed.
<p>But still, something feels wrong from having all those native function calls throughout the codebase. The solution is <i>database access abstraction</i>, which does not attempt to abstract away the entire database, but attempts to abstract away <i>access </i>to the database.
<p>Practically, this means building a wrapper class around your database code.&nbsp; Then, your application can use this wrapper class for its database needs. This is somewhat the best of both worlds. If you do need to switch DB&#8217;s, all your native functions calls will at least be in one file. You can also insert any system-wide logic pertaining to DB&#8217;s in this one class. For example, if you move to a replicated MySQL environment, you&#8217;ll need to direct READ queries to connect to one of multiple slave servers, and direct WRITE queries to the master server.&nbsp; This seems like an obvious thing to do, but a lot of people assume using a DBAL is enough abstraction already.
<p>At work, my biggest motivation was performance. Running tests on our current DBAL, ADOdb, against using the mysqli_* functions in PHP revealed significant performance gains in going without the DBAL, which makes sense.
<p><a href="http://terrychay.com/blog/article/database-abstraction-vs-data-access.shtml">This blog</a> repeats much of the thinking here, but is a more comprehensive looks at the topic (though the language is confusing at times.)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.straylightrun.net/2009/04/30/who-needs-a-database-abstraction-layer-anyway/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MySQL Query Cache, Or Vertical Partitioning Intro</title>
		<link>http://blog.straylightrun.net/2009/03/13/mysql-query-cache-or-vertical-partitioning-intro/</link>
		<comments>http://blog.straylightrun.net/2009/03/13/mysql-query-cache-or-vertical-partitioning-intro/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 14:12:05 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[partitioning]]></category>
		<category><![CDATA[query cache]]></category>

		<guid isPermaLink="false">http://blog.straylightrun.net/2009/03/13/mysql-query-cache-or-vertical-partitioning-intro/</guid>
		<description><![CDATA[The MySQL Query Cache is not very hard to understand. It is at its most basic a giant hash where the literal queries are the keys and the array of result records are the values. So this query:

SELECT event_name FROM events WHERE event_id = 8;

is different from this query:

SELECT  event_name FROM events WHERE event_id [...]]]></description>
			<content:encoded><![CDATA[<p>The MySQL Query Cache is not very hard to understand. It is at its most basic a giant hash where the <em>literal queries </em>are the keys and the array of result records are the values. So this query:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> event_name <span style="color: #993333; font-weight: bold;">FROM</span> events <span style="color: #993333; font-weight: bold;">WHERE</span> event_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">8</span>;</pre></div></div>

<p>is different from this query:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>  event_name <span style="color: #993333; font-weight: bold;">FROM</span> events <span style="color: #993333; font-weight: bold;">WHERE</span> event_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">10</span>;</pre></div></div>

<p>Important note!&nbsp; This means that even though your parameterized queries may look the same without the parameters, to the query cache, they are not! </p>
<p>As with all caches, the query cache is concerned about freshness of data. It takes perhaps the simplest approach possible to this problem by keeping track of any tables involved in your cached query. If <em>any </em>of these tables changes, it invalidates the query and removes it from the cache. This means that if your query returns frequently-changing data in its results, the query cache will invalidate the query frequently, leading to thrashing. For example, if you had a query that returned a view count of an event: </p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> event_name<span style="color: #66cc66;">,</span> views <span style="color: #993333; font-weight: bold;">FROM</span> events <span style="color: #993333; font-weight: bold;">WHERE</span> event_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">8</span>;</pre></div></div>

<p>Every time that event is viewed, the cached query will be invalidated. What&#8217;s the solution? </p>
<p>In general, write queries so that their result sets do not change often. In specific, mixing static attributes with frequently updated fields in a single table leads to thrashing, so separate out things like view counts and analytics into their own tables. The frequently updated data can be read with a separate query, or perhaps cached in your application in a data structure that periodically flushes to the DB. </p>
<p>This <a href="http://en.wikipedia.org/wiki/Partition_(database)">vertical partitioning</a><em> </em>of a single table&#8217;s columns into multiple tables helps immensely with the query cache. What&#8217;s more is that the table with the unchanging data can be further optimized for READS, and the frequently updated table can be optimized for UPDATES.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.straylightrun.net/2009/03/13/mysql-query-cache-or-vertical-partitioning-intro/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tip Of The Day: ON DUPLICATE KEY UPDATE</title>
		<link>http://blog.straylightrun.net/2009/02/09/tip-of-the-day-on-duplicate-key-update/</link>
		<comments>http://blog.straylightrun.net/2009/02/09/tip-of-the-day-on-duplicate-key-update/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 21:38:19 +0000</pubDate>
		<dc:creator>gerard</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.straylightrun.net/?p=111</guid>
		<description><![CDATA[In MySQL (and MySQL only AFAIK), INSERT has a clause called ON DUPLICATE KEY UDPATE. When ON DUPLICATE KEY UPDATE is used with INSERT, the insert will update the record if a value for a unique or primary key already exists, or else create a record if the value does not exist. So now when [...]]]></description>
			<content:encoded><![CDATA[<p>In MySQL (and MySQL only AFAIK), INSERT has a clause called ON DUPLICATE KEY UDPATE. When <a href="http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html">ON DUPLICATE KEY UPDATE</a> is used with INSERT, the insert will update the record if a value for a unique or primary key already exists, or else create a record if the value does not exist. So now when a form can either create a new something or edit an existing something, you can use one query to do it, and not have to query to see if the something exists already. </p>
<p>So instead of this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$num</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getone</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;select count(*) from events where event_id = 15&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$num</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
   <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;update events set name = 'New name' where event_id = 15&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span>
<span style="color: #009900;">&#123;</span>
   <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;insert into events (event_id, name) values (null, 'New name')&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>you can do something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #009900; font-weight: bold;">null</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;insert into events (event_id, name) values (<span style="color: #006699; font-weight: bold;">$id</span>, 'New name') on duplicate key update name = 'New name'&quot;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Neat, eh?</p>
<p>In case you&#8217;re wondering what the difference is between ON DUPLICATE KEY UPDATE and a REPLACE query, a REPLACE fires a DELETE followed by an INSERT query, as opposed to a real UPDATE.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.straylightrun.net/2009/02/09/tip-of-the-day-on-duplicate-key-update/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->