<?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"
	>

<channel>
	<title>Mike Willbanks</title>
	<atom:link href="http://blog.digitalstruct.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.digitalstruct.com</link>
	<description>Getting inside the mind of a php developer.</description>
	<pubDate>Mon, 23 Jun 2008 05:24:34 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>My Desktop Welcomes Kubuntu</title>
		<link>http://blog.digitalstruct.com/2008/06/22/my-desktop-welcomes-kubuntu/</link>
		<comments>http://blog.digitalstruct.com/2008/06/22/my-desktop-welcomes-kubuntu/#comments</comments>
		<pubDate>Mon, 23 Jun 2008 05:24:34 +0000</pubDate>
		<dc:creator>Mike Willbanks</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<category><![CDATA[kubuntu]]></category>

		<guid isPermaLink="false">http://blog.digitalstruct.com/?p=57</guid>
		<description><![CDATA[Well, finally was able to get a project I have been meaning to do for a while out of the way this weekend.  However, it was fairly complex to actually get Kubuntu or any linux distribution up and running on my desktop.  Actually, one mouse died during the experience (I must note that [...]]]></description>
			<content:encoded><![CDATA[<p>Well, finally was able to get a project I have been meaning to do for a while out of the way this weekend.  However, it was fairly complex to actually get Kubuntu or any linux distribution up and running on my desktop.  Actually, one mouse died during the experience (I must note that it was already misbehaving and in need of a replacement).  </p>
<p>The hardest thing about getting this install done, as most technologists, is that I do not have an average computer setup.  Currently it has 3 SATA drives including 2 WD Raptures and another drive for simply storage.  Since the rapture drives operate at 10,000 RPM and have 36GB each they are great fits for what needs to be fast vs the slower 7,200 120 GB which is great for all of my storage.  On top of that running my older AMD Athlon 3200+ with the 2GB ECC registered memory and a nice PCI-E XFX GeForce 8400 and not to mention the 2 cd/dvd burners it was a pain to get it all up and running correctly.  On top of that nForce 4 boards can be a pain to get running right.</p>
<p>After about 15 hours of investing and researching I was finally able to find all of the flags to pass to the kernel.  Before I found all of these flags I was plagued with freezes and could hardly get anything.  It is very nice to have this complete and I am loving it.  Now if I could get my dual monitors to work without crashing that is the next step.</p>
<p>Next projects on the list:</p>
<ol>
<li>Finish setting up my Linux environment for development.</li>
<li>Start writing the next blog post for performance (hopefully a little more thorough).</li>
<li>Start to get a preview version of a current project I want to release at some point (should be helpful to organizations that deal with development).</li>
<li>Start writing a book (maybe, eventually).</li>
</ol>
<p>Who knows, there are so many things to do and just simply not enough time.  In case you are interested in the flags that I had to use for my install of Kubuntu and you are looking to do the same thing:</p>
<pre>noapic nolapic acpi=off irqpoll pci=noacpi pnpbios=off</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.digitalstruct.com/2008/06/22/my-desktop-welcomes-kubuntu/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHP Performance Series: Maximizing Your MySQL Database</title>
		<link>http://blog.digitalstruct.com/2008/06/18/php-performance-series-maximizing-your-mysql-database/</link>
		<comments>http://blog.digitalstruct.com/2008/06/18/php-performance-series-maximizing-your-mysql-database/#comments</comments>
		<pubDate>Thu, 19 Jun 2008 05:57:10 +0000</pubDate>
		<dc:creator>Mike Willbanks</dc:creator>
		
		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.digitalstruct.com/?p=55</guid>
		<description><![CDATA[In the first article of the PHP Performance Series, I focused on PHP Caching Techniques.  This time I want to talk about maximizing your database.  This article will deal mostly with MySQL, however, you should be able to note many of the different aspects even if you do not directly utilize MySQL.
Application SQL [...]]]></description>
			<content:encoded><![CDATA[<p>In the first article of the PHP Performance Series, I focused on <a href="/2008/02/27/php-performance-series-caching-techniques/">PHP Caching Techniques</a>.  This time I want to talk about maximizing your database.  This article will deal mostly with MySQL, however, you should be able to note many of the different aspects even if you do not directly utilize MySQL.</p>
<h2>Application SQL Performance</h2>
<p>Application level SQL performance is much different than the performance of the SQL query itself but rather how it has been designed to work in the application.  Many of the items I will be addressing in this area is designing your application to make less queries thus improving scalability and likely performance.  However, performance does not always equal scalability as the same with scalability does not always equal performance.</p>
<p>If you have read my blog before you may notice that I have used some of this content before but putting in this section for terms of completeness.</p>
<h3>Lazy Connections</h3>
<p>Utilizing lazy connections for your database is a great step in applications that do not need to utilize the database through a full request or even if it needs to be utilized at all.  The concept here is to not initialize the connection to the database unless absolutely essential to keep your connection pool free of massive amounts of sleeping connections.</p>
<h4>Simple Lazy Connection Example</h4>
<p>While not a full example, I believe this shows you a simple technique in handling lazy connections.</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #000000; font-weight: bold;">class</span> My_Db <span style="color: #66cc66;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #ff0000">$_connected</span> <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #ff0000">$_connection</span><span style="color: #66cc66;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> connect<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$host</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$user</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$pass</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$db</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
		<span style="color: #808080; font-style: italic;">//method will simply set the connection variables</span>
	<span style="color: #66cc66;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> _connect<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$this</span><span style="color: #66cc66;">-&gt;</span>_connection <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_connect</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
			<span style="color: #ff0000">$this</span><span style="color: #66cc66;">-&gt;</span>_connected <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">;</span>
		<span style="color: #66cc66;">&#125;</span>
	<span style="color: #66cc66;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> query<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$query</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">!</span><span style="color: #ff0000">$this</span><span style="color: #66cc66;">-&gt;</span>_connected<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
			<span style="color: #ff0000">$this</span><span style="color: #66cc66;">-&gt;</span>_connect<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
		<span style="color: #66cc66;">&#125;</span>
		<span style="color: #000066;">mysql_query</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$query</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$this</span><span style="color: #66cc66;">-&gt;</span>_connection<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
	<span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p></p>
<h3>Iterating Queries</h3>
<p>This is one of the most common items I usually see when looking over another developers code or even several of the open source projects out there.  I am defining iterating queries as a query that executes on a loop.  These can be very expensive and often times are definitely not needed.</p>
<h4>An Iterating Query Example</h4>
<p>
<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000066;">isset</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'ids'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'ids'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #ff0000">$id</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
        <span style="color: #ff0000">$rs</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_query</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'SELECT * FROM my_table WHERE my_id = '</span> <span style="color: #66cc66;">.</span> <span style="color: #66cc66;">&#40;</span>int<span style="color: #66cc66;">&#41;</span> <span style="color: #ff0000">$id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
        <span style="color: #ff0000">$row</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_fetch_assoc</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$rs</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
        <span style="color: #000066;">print_r</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$row</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p></p>
<h4>Fixing The Iterating Query Example</h4>
<p>
<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000066;">isset</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'ids'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #ff0000">$ids</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">array_map</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'intval'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'ids'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #ff0000">$ids</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">implode</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">','</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$ids</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #ff0000">$rs</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_query</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'SELECT * FROM my_table WHERE my_id IN ('</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000">$ids</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000;">')'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$row</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_fetch_assoc</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$rs</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
        <span style="color: #000066;">print_r</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$row</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p></p>
<h3>Need Based Selects</h3>
<p>There is no need to select information that you do not need.  For starters this increases the memory usage on the request as well as the I/O time in fetching all of the record data from the columns that are not being utilized and transferring them through PHP.  The more data you select the slower the query and larger the memory footprint.  This is especially true with the TEXT and BLOG column types.</p>
<h4>SELECT * IS BAD!</h4>
<p>This actually is bad in 2 different areas.  First and of a higher concern is what is actually being utilized from the query if you ever need to change something in the application?  Say you have a large application with thousands of files that utilize a select query and you will have no idea where the variables are without actually researching each and every area of the application that has the wonderful SELECT *.  Basically your maintainability slowly dies.  Secondly as I stated before, there is also a performance and memory hit here, simply stated, do not use SELECT *.</p>
<p>One question that is commonly asked after this comment is what if I am using all of the columns?  Still, are you going to be using all of the columns in 3 months, 6 months, 1 year, 5 years?</p>
<h3>Use the Correct Data Type (Don&#8217;t Quote Everything)</h3>
<p>Yes, utilizing the correct type of data in your query does matter.  You can cause the database to miss indexes or come back with invalid results.  Besides that aspect it is slower since the database has to convert the data into the correct type.</p>
<h4>Example of Incorrect Data Types</h4>
<p>
<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000066;">isset</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'id'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #ff0000">$id</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_real_escape_string</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'id'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #ff0000">$rs</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_query</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;SELECT * FROM my_table WHERE my_id = '{$id}'&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p></p>
<h4>Example of Correct Data Types</h4>
<p>
<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000066;">isset</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'id'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #ff0000">$id</span> <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span>int<span style="color: #66cc66;">&#41;</span> <span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'id'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">;</span>
    <span style="color: #ff0000">$rs</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_query</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'SELECT * FROM my_table WHERE my_id = '</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000">$id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p></p>
<p>By the way, the 2nd one is also quicker because we only had to type cast for the numeric instead of running it through mysql_real_escape_string.</p>
<h4>Hierarchical Data</h4>
<p>When utilizing navigation trees, you should ensure that you are utilizing a proper technique and not pushing your database for it.  Further, cache it instead of hitting it every request at the same time!  There is already a great article over at <a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html" onclick="window.open(this.href, '_blank');return false;">MySQL on Managing Hierarchical Data</a> so I am not going to go deep into this.  But anytime you are managing a tree of data please spare other developers and utilize it correctly.</p>
<h2>Database Design</h2>
<p>Database design is typically the first area that you find problems start.  A bad data model can plague your application with both performance and maintainability concerns.  However, also note, the more performance driven that you make your database, the less maintainable that it can become (debatable - can really depend on size and scale).</p>
<p>Please note that this is not an all encompassing list as I wanted to give a little more of an idea from a developer point of view on the optimization techniques in database design rather than providing a full guide.  If you are looking for a deep level of information I invite you to please go to the <a href="http://dev.mysql.com/doc/refman/5.0/en/optimizing-database-structure.html" onclick="window.open(this.href, '_blank');return false;">MySQL Manual on Database Design</a> Feel free to add recommendations in the comments.</p>
<h3>Normalization</h3>
<p>Normalization is a technique utilized for minimizing the duplication of information.  This is typically the best thing to start out with, if you are currently having problems and your database is not well normalized focus on that first.  Likely you have tables, columns or data that shouldn&#8217;t need to work as it currently is.</p>
<h4>Columns instead of Table Example</h4>
<p>A common problem that many applications you find have is that they store the data into just columns instead of actually making a one-to-many table.  Take for instance the following table:</p>
<table>
<caption><strong>app_user</strong></caption>
<thead>
<tr>
<th>Column Name</th>
<th>Column Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>user_id</td>
<td>integer</td>
</tr>
<tr>
<td>user_email</td>
<td>varchar</td>
</tr>
<tr>
<td>user_website</td>
<td>varchar</td>
</tr>
<tr>
<td>user_website_2</td>
<td>varchar</td>
</tr>
<tr>
<td>user_website_3</td>
<td>varchar</td>
</tr>
</tbody>
</table>
<p>What you are likely seeing here is a user requested to have up to 3 websites and the developer working on it figured there would never need to be anymore.  Now this is a focus for gaining further modularity as well as normalization.</p>
<h4>Table instead of Columns Example</h4>
<p>Using a table instead of columns would better support this feature as well as allow for further growth in the future.</p>
<table>
<caption><strong>app_user</strong></caption>
<thead>
<tr>
<th>Column Name</th>
<th>Column Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>user_id</td>
<td>integer</td>
</tr>
<tr>
<td>user_email</td>
<td>varchar</td>
</tr>
</tbody>
</table>
<table>
<caption><strong>app_user_website</strong></caption>
<thead>
<tr>
<th>Column Name</th>
<th>Column Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>website_id</td>
<td>integer</td>
</tr>
<tr>
<td>user_id</td>
<td>integer</td>
</tr>
<tr>
<td>website_url</td>
<td>varchar</td>
</tr>
</tbody>
</table>
<p>You might be thinking, what does this have to do with performance?  Well it has to deal with maintainability, better handling of your indexes, as well as lowering the table size in the initial table.  Size of your tables does matter definitely when you need to start adding more indexes to columns that you might not need to.  Take both examples and attempt to find users without a website entered without an index on the user_website columns.  This becomes very slow instead of doing a simple select au.user_id from app_user au where au.user_id NOT IN (select distinct user_id from app_user_website) instead of having to add an additional index instead of simply using the foreign key that you would likely have defined in the app_user_website table for the user_id.</p>
<h3>Denormalization</h3>
<p>Denormalization is the concept of copying data into other tables in order to reduce the amount of joins that you need to create.  These should typically always be handled with triggers and if you are unable to do triggers, please ensure that anything that creates, modifies or deletes handles through a layer of encapsulation.  Otherwise you will end up with stale records.</p>
<p>You will only need to do this when you have exhausted all of the other routes such as checking and creating indexes, if data access was really needed and lastly there was no other method for the needs that you were going after.</p>
<h3>Table Types</h3>
<p>Use the correct table type for what you are doing or attempting to do.  I suggest setting up a matrix of what you need your table to do as well as your database as a whole.  This first step is often neglected by many developers.</p>
<table>
<caption>Example List</caption>
<thead>
<tr>
<th>Feature</th>
<th>Option</th>
</tr>
</thead>
<tbody>
<tr>
<td>Read vs. Write &gt; 15%</td>
<td>Yes/No</td>
</tr>
<tr>
<td>Transactions</td>
<td>Yes/No</td>
</tr>
<tr>
<td>Foreign Key Support</td>
<td>Yes/No</td>
</tr>
<tr>
<td>Full-Text Indexes</td>
<td>Yes/No</td>
</tr>
</tbody>
</table>
<p>The list above is by far no means a full list but you should document what you need and what you are using the database for.  For example if you are reading and writing on the same database table, MyISAM is likely a bad idea if you have greater than 15% of reads or writes.  MyISAM tables will easily lock when there is a long read and a subsequent insert with a table lock thus not allowing any further reads until that insert has completed.  So make a list and figure out what needs to be there.  This will certainly help you with furthering your database.</p>
<h2>SQL Query Optimizations</h2>
<p>Optimizing your SQL to perform is not rocket science, however, this seems to be one area where applications seem to start crumbling down from the point of an application hitting popularity.  Simply the features that are developed and time change the database is rarely taken into effect in what might be affected.</p>
<p>A simple rule to follow is when utilizing your database to design your queries to your database architecture and current rules, when those cannot be achieved refactor and adjust the database to be able to handle the new situations.</p>
<h3>The Simple Rules</h3>
<ul>
<li>Use your explain/execution plan</li>
<li>The less joins the better</li>
<li>Ensure you are utilizing your indexes (see first bullet)</li>
<li>Temporary tables can be good when doing operations on complex data sets</li>
<li>Stay away from derived tables and non-materialized views (see above bullet)</li>
<li>Roll up data that can be aggregated</li>
<li><strong>Select the columns you need, not SELECT *</strong></li>
</ul>
<p>If you are looking for ways to better optimize your queries, again, please go to the <a href="http://dev.mysql.com/doc/refman/5.0/en/query-speed.html" onclick="window.open(this.href, '_blank');return false;">MySQL Manual on Query Optimization</a></p>
<h2>Exit(0);</h2>
<p>You may have noticed that this blog post has taken me quite a while to push this out.  Besides in  the middle of purchasing a home, some resource constraints at work, a couple side projects and maintaining my life I just didn&#8217;t have much time to finish writing a more complete post.</p>
<p>To go a little further, I&#8217;ve cut down the contents in this blog as you may have been sick of reading already as well as the amount of information that could have been potentially written here could easily have been a full book if you wanted to get into each and every aspect.  I figured for my sanity as well as yours I should cut it shorter.  If you have any information to add please submit comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digitalstruct.com/2008/06/18/php-performance-series-maximizing-your-mysql-database/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHP Performance Series: Caching Techniques</title>
		<link>http://blog.digitalstruct.com/2008/02/27/php-performance-series-caching-techniques/</link>
		<comments>http://blog.digitalstruct.com/2008/02/27/php-performance-series-caching-techniques/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 06:36:43 +0000</pubDate>
		<dc:creator>Mike Willbanks</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.digitalstruct.com/2008/02/27/php-performance-series-caching-techniques/</guid>
		<description><![CDATA[Welcome to the first edition of the PHP performance series, a new series that I will be explaining ways to gain efficiencies and squeezing more performance out of your applications.  This first edition, caching techniques, focuses on ways to cache data to optimize your current sites.  Some of the concepts here are fairly [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the first edition of the PHP performance series, a new series that I will be explaining ways to gain efficiencies and squeezing more performance out of your applications.  This first edition, caching techniques, focuses on ways to cache data to optimize your current sites.  Some of the concepts here are fairly easy to implement while others may take strategic design in the architecture of your application.  Whether you are working on a high profile web application or simply a web development farm these concepts apply to the masses.</p>
<h2>Opcode Caching</h2>
<p>Opcode caching is likely one of the most simple and effective ways of increasing performance in PHP.  By utilizing an Opcode cache you will eliminate many unneeded inefficiencies that happen during the execution process.  Opcode caches solve this by storing the opcodes in memory in order to not compile files on each step in the process.</p>
<p>There are many opcode caches available for consumption.  You have <a href="http://www.php.net/manual/en/ref.apc.php" onclick="window.open(this.href);return false;">APC</a>, <a href="http://xcache.lighttpd.net/" onclick="window.open(this.href);return false;">XCache</a>, <a href="http://www.eaccelerator.net/" onclick="window.open(this.href);return false;">eAccelerator</a> and <a href="http://www.zend.com/en/products/platform/" onclick="window.open(this.href);return false;">Zend Platform</a>.  You make your choice up of what you like the best as they all have advantages and disadvantages which is out of the scope of this article.</p>
<h3>File Priming</h3>
<p>This is typically more relevant to larger scale companies that have release processes.  When you are pushing out a new release, typically you do not want to have your caching system waiting until each page is hit until it is processed in the opcode cache.  Instead what can be done, is to run a utility script after the release is pushed out to run each file through the opcode caching extensions compile function.  There is an example of this on my performance overview post which has a section about <a href="http://blog.digitalstruct.com/2008/01/31/performance-tuning-overview/" onclick="window.open(this.href);return false;">file priming for APC</a>  Each of the different opcode caches typically have a way to prime the files, so just look into the API documents.</p>
<h3>Caching Variables</h3>
<p>Many opcode caches also allow for you to place variable data, also known as user land data, into the cache (typically in memory).  This is useful for storing your configuration values or data that is expensive to get and will likely not change.</p>
<p><strong>Example: APC Variables</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$config</span> <span style="color: #66cc66;">=</span> apc_fetch<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'config'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">===</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">require</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/path/to/includes/config.php'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    apc_store<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'config'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$config</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

</p>
<p>A practical example of this was using the Zend Framework and simply running an ab bench after storing the results of the XML configuration file in the cache.  This saved parsing time as well as extremely quick access to the configuration file.</p>
<p><strong>Figure: APC Variables in Use</strong></p>
<p><em>The Code</em></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$conf</span> <span style="color: #66cc66;">=</span> apc_fetch<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'pbs_config'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">===</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #ff0000">$conf</span> <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Config_Xml<span style="color: #66cc66;">&#40;</span>PB_PATH_CONF <span style="color: #66cc66;">.</span> <span style="color: #ff0000;">'/base.xml'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'production'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    apc_store<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'pbs_config'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$conf</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

</p>
<p><em>The Benchmark Command</em><code><br />
ab -t30 -c5 http://www.example.com/<br />
</code></p>
<p><em>Results Without The APC Variable</em><br /><code><br />
Concurrency Level:      5<br />
Time taken for tests:   30.33144 seconds<br />
Complete requests:      684<br />
Failed requests:        0<br />
Write errors:           0<br />
</code></p>
<p><em>Results With The APC Variable</em><br /><code><br />
Concurrency Level:      5<br />
Time taken for tests:   30.12173 seconds<br />
Complete requests:      709<br />
Failed requests:        0<br />
Write errors:           0<br />
</code></p>
<p>As you could see we had approximately a 3-4% gain in performance by simply caching our configuration file.  There is many other areas that could be added into these areas of memory thus increasing your overall performance.  Find a few of these and you will certainly see increases in the amount of requests handled.  <em>Note that the server that is being tested on is an older box and including a mass amount of files using the Zend Framework.</em></p>
<p>Make sure to check the documentation on each opcode cache to ensure what you can store in the variable scope (some will not support automatically serializing objects so be careful).  Further, ensure you have enough memory allocated in order to do this in specific areas.  Lastly I did not include the other op code cache examples here; I simply wanted to give an example to show what common usage would be like.</p>
<h2>File Caching</h2>
<p>Many times there are areas where the server is processing the same page of content that has not changed.  There are always opportunities to cache this type of content, whether in part or in full.  I&#8217;ll attempt to address both areas here from a simplistic point of view, rather than discussing techniques of generating static content that could be utilized by running a static web server.</p>
<p>For the sake of time and being practical with pre-existing tools, I will be showing the examples in the <a href="http://pear.php.net/package/Cache_Lite" onclick="window.open(this.href);return false;">Pear::Cache_Lite</a> package.</p>
<h3>Full File Caching</h3>
<p>Full file caching is rather hard to achieve on many different sites when we are pulling data for different reasons and sometimes from different sources.  However, while that may be true, there are certainly cases where you do not need to have the &#8220;most&#8221; up to date data available at that very second.  Even a 5-10 minute delay on extremely high traffic sites will award you a performance increase.  It is always good to ensure that you are checking your site for these types of areas and creating an easy way to allow for future modification.</p>
<p>While you always have to come at caching with different angles, this is quite possibly the quickest way to add it in and is certainly not flawless. The following example simply takes a snapshot of the page and stores it for use again.  This is not a complete logical approach but may be good for certain users.</p>
<p><em>I do not recommend this for a long term solution</em> but if you need something that is short term and this meets your needs, implement if you like but sooner or later you will see the drawbacks to this method.  Such as no content is ever dynamic or certain pieces of content need to be updated sooner than others.</p>
<p><strong>The Bootstrap Cache Example:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">require</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/path/to/pear/Cache/Lite/Output.php'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #ff0000">$options</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">array</span><span style="color: #66cc66;">&#40;</span>
	<span style="color: #ff0000;">'cacheDir'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #ff0000;">'/tmp/'</span><span style="color: #66cc66;">,</span>
	<span style="color: #ff0000;">'lifeTime'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #cc66cc;">10</span>
<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #ff0000">$cache</span> <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Cache_Lite_Output<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$options</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">!</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$cache</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">start</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$_SERVER</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'REQUEST_URI'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
	<span style="color: #b1b100;">require</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/path/to/bootstrap.php'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
	<span style="color: #ff0000">$cache</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">end</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

</p>
<p><strong>The .htaccess Cache Example:</strong>
</p>
<p><em>.htaccess</em><code><br />
php_value auto_prepend_file /path/to/cache_start.php<br />
php_value auto_append_file /path/to/cache_end.php<br />
</code></p>
<p><em>cache_start.php</em></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">require</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Cache/Lite/Output.php'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #ff0000">$options</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">array</span><span style="color: #66cc66;">&#40;</span>
    <span style="color: #ff0000;">'cacheDir'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #ff0000;">'/tmp/'</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">'lifeTime'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #cc66cc;">10</span>
<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #ff0000">$cache</span> <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Cache_Lite_Output<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$options</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$cache</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">start</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$_SERVER</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'REQUEST_URI'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #000066;">exit</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

</p>
<p><em>cache_end.php</em></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #ff0000">$cache</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">end</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span></pre></div></div>

</p>
<p>Cache Lite does a lot of the heavy work for you such as file locking, deciding on how to save the content through the parameter given (here we are just using the REQUEST URI).  You may need to take in consideration the $_POST variables, $_COOKIE variables or even the $_SESSION variables depending on what you are attempting to achieve.</p>
<h3>Partial File Caching</h3>
<p>Partial file caching is typically the route that you will likely see the most benefits overall.  You likely have quite a bit of content that does not need to be real-time, however, you would like it to be updated once in a while.  Or secondly, you have specific portions of the site that simply do not need to be updated at all.  This is where the partial caching comes in and really allows you to see quite a bit of performance gains across the board.</p>
<p><strong>Caching Contents Of A String</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">require</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Cache/Lite.php'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #ff0000">$options</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">array</span><span style="color: #66cc66;">&#40;</span>
    <span style="color: #ff0000;">'cacheDir'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #ff0000;">'/tmp/'</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">'lifeTime'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #cc66cc;">3600</span> <span style="color: #808080; font-style: italic;">//1 hour</span>
<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #ff0000">$cache</span> <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Cache_Lite<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$options</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$categories</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000">$cache</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">get</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'categories'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">===</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #ff0000">$rs</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_query</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'SELECT category_id, category_name FROM category'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #ff0000">$categories</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'&lt;ul class=&quot;category&quot;&gt;'</span><span style="color: #66cc66;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$row</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_fetch_assoc</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$rs</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
        <span style="color: #ff0000">$categories</span> <span style="color: #66cc66;">.=</span> <span style="color: #ff0000;">'&lt;li&gt;&lt;a href=&quot;category.php?id='</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000">$row</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'category_id'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000;">'&quot;&gt;'</span> <span style="color: #66cc66;">.</span>
                                <span style="color: #ff0000">$row</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'category_name'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000;">'&lt;/a&gt;&lt;/li&gt;'</span><span style="color: #66cc66;">;</span>
    <span style="color: #66cc66;">&#125;</span>
    <span style="color: #ff0000">$categories</span> <span style="color: #66cc66;">.=</span> <span style="color: #ff0000;">'&lt;/ul&gt;'</span><span style="color: #66cc66;">;</span>
    <span style="color: #ff0000">$cache</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$categories</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'categories'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span>
<span style="color: #000066;">echo</span> <span style="color: #ff0000">$categories</span><span style="color: #66cc66;">;</span></pre></div></div>

</p>
<p>While this is a highly simplistic example, it shows the flexibility to store contents.  You could even store an array instead in order to cycle through it at a later time.</p>
<p><strong>Caching An Array Of Results</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #b1b100;">require</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Cache/Lite.php'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #ff0000">$options</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">array</span><span style="color: #66cc66;">&#40;</span>
    <span style="color: #ff0000;">'cacheDir'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #ff0000;">'/tmp/'</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">'lifeTime'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #cc66cc;">3600</span><span style="color: #66cc66;">,</span> <span style="color: #808080; font-style: italic;">//1 hour</span>
    <span style="color: #ff0000;">'automaticSerialization'</span> <span style="color: #66cc66;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span>
<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #ff0000">$cache</span> <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Cache_Lite<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$options</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$categories</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000">$cache</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">get</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'categories'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">===</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #ff0000">$rs</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_query</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'SELECT category_id, category_name FROM category'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #ff0000">$categories</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">array</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$row</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_fetch_assoc</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$rs</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
        <span style="color: #ff0000">$categories</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000">$row</span><span style="color: #66cc66;">;</span>
    <span style="color: #66cc66;">&#125;</span>
    <span style="color: #ff0000">$cache</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$categories</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'categories'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #66cc66;">&#125;</span>
<span style="color: #000066;">var_dump</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$categories</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span></pre></div></div>

</p>
<p>As you can see, you can store different types of data through the cache.  However, with file caching I would be reluctant to store database data as there are better solutions for that type of role which I will be talking about shortly.</p>
<h2>Memory Caching</h2>
<p>There are a few different ways to produce caches in memory including: memcached, database memory tables, utilizing RAM disk and another option is using the opcode caches memory caching from the beginning of this article.  It is best to keep things in memory that are utilized most often and often have a small footprint.</p>
<h3>Memcached</h3>
<p>From the <a href="http://www.danga.com/memcached/" onclick="window.open(this.href); return false;">memcached website</a>:<br />
<blockquote>memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.</p></blockquote>
<p>Essentially what this is saying is that it is able to be stored on a central server with many servers accessing it, it is not tied into your web server such as an opcode cache as it runs it&#8217;s own daemon and it is typically utilized for caching database results (doesn&#8217;t mean there aren&#8217;t additional things it is good for such as session handling &#8212; it is already integrated if you just cache the session handler to &#8220;memcache&#8221; and change your session.save_path to the server with memcached).</p>
<p><strong>Memcache Example</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #ff0000">$post_id</span> <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span>int<span style="color: #66cc66;">&#41;</span> <span style="color: #ff0000">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'post_id'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">;</span>
<span style="color: #ff0000">$memcached</span> <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Memcache<span style="color: #66cc66;">;</span>
<span style="color: #ff0000">$memcached</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">connect</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'hostname'</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">11211</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$row</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000">$memcached</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">get</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'post_id_'</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000">$post_id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">===</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">//yes this is safe, we type casted it already ;)</span>
    <span style="color: #ff0000">$rs</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_query</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'SELECT * FROM post WHERE post_id = '</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000">$post_id</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$rs</span> <span style="color: #66cc66;">&amp;&amp;</span> <span style="color: #000066;">mysql_num_rows</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$rs</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
        <span style="color: #ff0000">$row</span> <span style="color: #66cc66;">=</span> <span style="color: #000066;">mysql_fetch_assoc</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$rs</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
        <span style="color: #808080; font-style: italic;">// cache compressed for 1 hour</span>
        <span style="color: #ff0000">$memcached</span><span style="color: #66cc66;">-&gt;</span><span style="color: #006600;">set</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'post_id_'</span> <span style="color: #66cc66;">.</span> <span style="color: #ff0000">$post_id</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000">$row</span><span style="color: #66cc66;">,</span> MEMCACHE_COMPRESSED<span style="color: #66cc66;">,</span> <span style="color: #000066;">time</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">3600</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
<span style="color: #000066;">var_dump</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000">$row</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">;</span></pre></div></div>

</p>
<p>This is a fairly typical example of memcached.  We stored a single item in memory for future usage that might be accessed quite a bit.  I recommend using this for records that are accessed the most, thats what a cache is all about.</p>
<p><strong>Memcache Session Example</strong>
<pre>
session.save_handler = memcache
session.save_path    = "tcp://hostname:11211"
</pre>
</p>
<p>As you can see session handling is quite easy.  For multiple memcached servers comma separate the save_path value with each server.</p>
<h3>Database Memory Tables</h3>
<p>Database memory tables, while I am not going to give an example, can be useful for session data.  You can easily create a table with the storage engine of memory using MySQL.  Create your own session handler and provide the data that way.  This is a quick way to boost performance on sessions as well as keeping them distributed between multiple web servers.  Personally, if you can, I would go the memcached route to keep the load off of the database server and let it work on serving other requests.</p>
<h3>RAM Disk</h3>
<p>While utilizing your RAM as a disk is not distributed it can easily be a quick adjustment to make your site perform faster.  However, you might want to note the amount of memory you are going to be utilizing and ensure that on reboot that this directory is put back on the RAM Disk.  Remember that information placed in RAM is lost on reboot or power failure.</p>
<p><strong>Bind RAM to a Directory</strong>
<pre>
mount --bind -ttmpfs /path/to/site/tmp /path/to/site/tmp
</pre>
</p>
<p>I attempt to avoid this route as I believe that the risk outweighs the gains, unless you are dealing with massive servers.  But there are better tools such as memcached that I would trust more.</p>
<h2>exit(0);</h2>
<p>I hope that this was informative to some of you regarding caching techniques in PHP.  I didn&#8217;t fully cover all of the potential caching techniques such as database caching that the RDBMS&#8217;s do and some of the other items such as Squid.  I may cover more of these at a later time, if I attempt to get into it all now this post will never see the light of day.  If you have anything to add send in a comment.  Please note, I do not deploy these tactics on everything and anything but decide on certain logistics when and where these need to be implemented.  Take into consideration the scale of the project, current overall impact and if you are just optimizing it just for the sake of doing it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.digitalstruct.com/2008/02/27/php-performance-series-caching-techniques/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
