<?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>MaisonBisson.com &#187; optimization</title>
	<atom:link href="http://maisonbisson.com/blog/post/tag/optimization/feed/" rel="self" type="application/rss+xml" />
	<link>http://maisonbisson.com</link>
	<description>A bunch of stuff I would have emailed you about.</description>
	<lastBuildDate>Sat, 14 Nov 2009 20:14:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Systems Wrangling Session At WordCamp Developer Day</title>
		<link>http://maisonbisson.com/blog/post/13938/systems-wrangling-session-at-wordcamp-developer-day/</link>
		<comments>http://maisonbisson.com/blog/post/13938/systems-wrangling-session-at-wordcamp-developer-day/#comments</comments>
		<pubDate>Sun, 31 May 2009 21:13:21 +0000</pubDate>
		<dc:creator>Casey</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[systems]]></category>
		<category><![CDATA[WordCamp]]></category>
		<category><![CDATA[WordCamp 2009]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/?p=13938</guid>
		<description><![CDATA[
What is the current status of web servers&#8230;Is Apache 2.x “fast enough?”
Automattic uses Lightspeed (for PHP), nginx (for static content), and Apache (for media uploads). For WordPress-generated content, all server options are approximately the same speed.
What about APC?
Automattic uses beta versions of APC, and provides a 3-5x performance increase. It&#8217;s tied closely to the PHP [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-13938"><!-- &nbsp; --></abbr>
<p><a title="Ask your questions here « Server Q&amp;A — WordCamp Dev Day" href="http://serverqa.wordpress.com/2009/05/31/ask-your-questions-here/#comment-2">What is the current status of web servers&#8230;Is Apache 2.x “fast enough?”</a><br />
Automattic uses Lightspeed (for PHP), nginx (for static content), and Apache (for media uploads). For WordPress-generated content, all server options are approximately the same speed.</p>
<p><a title="Ask your questions here « Server Q&amp;A — WordCamp Dev Day" href="http://serverqa.wordpress.com/2009/05/31/ask-your-questions-here/#comment-3">What about APC?</a><br />
Automattic uses beta versions of APC, and provides a 3-5x performance increase. It&#8217;s tied closely to the PHP version, so Automattic recently switched from PHP 4 to PHP 5.</p>
<p><a title="Ask your questions here « Server Q&amp;A — WordCamp Dev Day" href="http://serverqa.wordpress.com/2009/05/31/ask-your-questions-here/#comment-4">Databases?</a><br />
MySQL scales well and is easy enough to use that there&#8217;s little reason to consider other DBs for WordPress content. Other applications may have different needs. Note: <a title="How FriendFeed uses MySQL to store schema-less data - Bret Taylor's blog" href="http://bret.appspot.com/entry/how-friendfeed-uses-mysql">FriendFeed uses MySQL to store schema-less data</a>. Single-table key lookups in MySQL are faster than getting the data from Memcached.</p>
<p><a title="Ask your questions here « Server Q&amp;A — WordCamp Dev Day" href="http://serverqa.wordpress.com/2009/05/31/ask-your-questions-here/#comment-7">Caching?</a><br />
Automattic uses <a title="WordPress › Batcache « WordPress Plugins" href="http://wordpress.org/extend/plugins/batcache/">Batcache</a> for full-page caching (.002 to .003 second), <a title="Revision 121652: /memcached" href="http://svn.wp-plugins.org/memcached/">Memcached</a> persistent object cache, very limited MySQL query cache (never larger than 256MB), sufficiently large key buffer.</p>
<p><a title="Ask your questions here « Server Q&amp;A — WordCamp Dev Day" href="http://serverqa.wordpress.com/2009/05/31/ask-your-questions-here/#comment-14">HyperDB?</a><br />
<a title="WordPress › HyperDB « WordPress Plugins" href="http://wordpress.org/extend/plugins/hyperdb/">HyperDB</a> solves DB scaling problems.</p>
<p><a title="Ask your questions here « Server Q&amp;A — WordCamp Dev Day" href="http://serverqa.wordpress.com/2009/05/31/ask-your-questions-here/#comment-25">Backups</a><br />
User-data backed up every hour, if something changed. Every blog backed up every 12 hours. Dedicated MySQL slaves do LVM snapshots for backups.</p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/13938/systems-wrangling-session-at-wordcamp-developer-day/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Slow Query Log Analysis</title>
		<link>http://maisonbisson.com/blog/post/13525/mysql-slow-query-log-analysis/</link>
		<comments>http://maisonbisson.com/blog/post/13525/mysql-slow-query-log-analysis/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 16:17:24 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Dispatches]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[slow query log]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/?p=13525</guid>
		<description><![CDATA[
Peter at MySQL Performance Blog pointed out this sweet perl script to analyze MySQL&#8217;s slow query logs. (This is supposedly a PHP port.)
The script does a good job of aggregating similar queries (those that only differ in their query values) and displaying overall stats for them. The following two queries are showing up a lot [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-13525"><!-- &nbsp; --></abbr>
<p>Peter at <a title="MySQL Performance Blog" href="http://www.mysqlperformanceblog.com/">MySQL Performance Blog</a> <a title="Slow Query Log analyzes tools | MySQL Performance Blog" href="http://www.mysqlperformanceblog.com/2006/09/06/slow-query-log-analyzes-tools/">pointed out</a> this <a title="http://www.mysqlperformanceblog.com/files/utils/mysql_slow_log_parser" href="http://www.mysqlperformanceblog.com/files/utils/mysql_slow_log_parser">sweet perl script</a> to analyze MySQL&#8217;s <a title="MySQL :: MySQL 5.0 Reference Manual :: 5.2.4 The Slow Query Log" href="http://dev.mysql.com/doc/refman/5.0/en/slow-query-log.html">slow query logs</a>. (<a title="mysql-log-filter - Google Code" href="http://code.google.com/p/mysql-log-filter/">This is supposedly a PHP port</a>.)</p>
<p>The script does a good job of aggregating similar queries (those that only differ in their query values) and displaying overall stats for them. The following two queries are showing up a lot in my WPMU installation because I also have it set to log queries that don&#8217;t use indexes. They&#8217;re not necessarily slow (MySQL &lt; 5.1 logs execution times to the nearest second, with a one second minimum), but the fact that they&#8217;re appearing a lot probably means the value isn&#8217;t being cached in Memcached.</p>
<p>The first SQL line shows the prototype for the query, the second is a real example from the log.</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">### 90379 Queries
### Total time: 90556, Average time: 1.00195841954436
### Taking 1  to 6  seconds to complete
### Rows analyzed 744 - 587874
SELECT COUNT(ID) FROM wp_XXX_posts WHERE post_status = 'XXX' and post_type = 'XXX';
&nbsp;
SELECT COUNT(ID) FROM wp_7_posts WHERE post_status = 'publish' and post_type = 'post';</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">### 8768 Queries
### Total time: 9033, Average time: 1.03022354014599
### Taking 1  to 4  seconds to complete
### Rows analyzed 0 - 199
SELECT option_name, option_value FROM wp_XXX_options FORCE INDEX(PRIMARY) ORDER BY option_id ASC;
&nbsp;
SELECT option_name, option_value FROM wp_4_options FORCE INDEX(PRIMARY) ORDER BY option_id ASC;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/13525/mysql-slow-query-log-analysis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5,848 (max), 656 (avg) MySQL Queries Per Second</title>
		<link>http://maisonbisson.com/blog/post/13456/5848-max-656-avg-mysql-queries-per-second/</link>
		<comments>http://maisonbisson.com/blog/post/13456/5848-max-656-avg-mysql-queries-per-second/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 05:00:33 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Dispatches]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[batcache]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[scriblio]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/?p=13456</guid>
		<description><![CDATA[

The above graph is far from typical, but I love that the box (the top one in this picture) can do the job when it needs to. This activity is a result of bulk record imports, web activity results in relatively little database traffic due to my use of Memcached and Batcache.
]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-13456"><!-- &nbsp; --></abbr>
<p><a title="5,848 (max), 656 (avg) MySQL Queries Per Second by misterbisson, on Flickr" href="http://www.flickr.com/photos/maisonbisson/3290635584/"><img src="http://farm4.static.flickr.com/3549/3290635584_af00ed2ef3.jpg" alt="5,848 (max), 656 (avg) MySQL Queries Per Second" width="500" height="72" /></a></p>
<p>The above graph is far from typical, but I love that the box (<a href="http://flickr.com/photos/scriblio/388446468/">the top one in this picture</a>) can do the job when it needs to. This activity is a result of bulk record imports, web activity results in relatively little database traffic due to my use of <a href="http://www.danga.com/memcached/">Memcached</a> and <a href="http://wordpress.org/extend/plugins/batcache/">Batcache</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/13456/5848-max-656-avg-mysql-queries-per-second/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon To Offer Content Delivery Services</title>
		<link>http://maisonbisson.com/blog/post/12613/amazon-to-offer-content-delivery-services/</link>
		<comments>http://maisonbisson.com/blog/post/12613/amazon-to-offer-content-delivery-services/#comments</comments>
		<pubDate>Thu, 18 Sep 2008 12:55:42 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[amazon web services]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[CDN]]></category>
		<category><![CDATA[content delivery networks]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[website optimization]]></category>
		<category><![CDATA[website performance]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/?p=12613</guid>
		<description><![CDATA[
Via an email from the Amazon Web Services group today:
&#8230;we are excited to share some early details with you about a new offering we have under development here at AWS — a content delivery service.
This new service will provide you a high performance method of distributing content to end users, giving your customers low latency [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-12613"><!-- &nbsp; --></abbr>
<p>Via an email from the Amazon Web Services group today:</p>
<blockquote><p>&#8230;we are excited to share some early details with you about a new offering we have under development here at AWS — a content delivery service.</p>
<p>This new service will provide you a high performance method of distributing content to end users, giving your customers low latency and high data transfer rates when they access your objects. The initial release will help developers and businesses who need to deliver popular, publicly readable content over HTTP connections. Our goal is to create a content delivery service that:</p>
<ul>
<li>Lets developers and businesses get started easily – there are no minimum fees and no commitments. You will only pay for what you actually use.</li>
<li>Is simple and easy to use – a single, simple API call is all that is needed to get started delivering your content.</li>
<li>Works seamlessly with Amazon S3 – this gives you durable storage for the original, definitive versions of your files while making the content delivery service easier to use.</li>
<li>Has a global presence – we use a global network of edge locations on three continents to deliver your content from the most appropriate location.</li>
</ul>
<p>You&#8217;ll start by storing the original version of your objects in Amazon S3, making sure they are publicly readable. Then, you&#8217;ll make a simple API call to register your bucket with the new content delivery service. This API call will return a new domain name for you to include in your web pages or application. When clients request an object using this domain name, they will be automatically routed to the nearest edge location for high performance delivery of your content. It&#8217;s that simple.</p>
<p>We&#8217;re currently working with a small group of private beta customers, and expect to have this service widely available before the end of the year.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/12613/amazon-to-offer-content-delivery-services/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Steve Souders On Website Performance</title>
		<link>http://maisonbisson.com/blog/post/12238/steve-souders-on-website-performance/</link>
		<comments>http://maisonbisson.com/blog/post/12238/steve-souders-on-website-performance/#comments</comments>
		<pubDate>Sat, 16 Aug 2008 17:23:56 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[Steve Souders]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/?p=12238</guid>
		<description><![CDATA[
Steve Souders: 10% of the problem is server performance, 90% of problem is browser activity after the main html is downloaded. He wrote the book and developed YSlow, so he should know.
JavaScripts are downloaded serially and block other activity. Most JavaScript functions aren&#8217;t used at OnLoad. We could split the JS and only load essential [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-12238"><!-- &nbsp; --></abbr>
<p><a href="http://stevesouders.com/">Steve Souders</a>: 10% of the problem is server performance, 90% of problem is browser activity after the main html is downloaded. He wrote <a href="http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309/?tag=maisonbisson-20">the book</a> and developed <a href="http://developer.yahoo.com/yslow/">YSlow</a>, so he should know.</p>
<p>JavaScripts are downloaded serially and block other activity. Most JavaScript functions aren&#8217;t used at OnLoad. We could split the JS and only load essential functions up front, and load all the rest later. How much might that help? He says 25% to 50%. This quickly gets complex, but he&#8217;s got a simple plan that considers three questions:</p>
<ul>
<li>Is the script URL on the same host as the main HTML?</li>
<li>Should the browser indicate it&#8217;s busy, or not?</li>
<li>Does script execution order mater?</li>
</ul>
<p>And at that point things started to get too interesting to take publishable notes. I clearly need to pay more attention to this guy.</p>
<p>Stats he mentioned without being specific about the source:</p>
<ul>
<li>Google: 200ms longer download time cut revenue by 20%</li>
<li>Yahoo: 100ms of latency costs &#8230; big.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/12238/steve-souders-on-website-performance/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Optimizing Inserts/Updates On MySQL Tables</title>
		<link>http://maisonbisson.com/blog/post/12159/optimizing-insertsupdates-on-mysql-tables/</link>
		<comments>http://maisonbisson.com/blog/post/12159/optimizing-insertsupdates-on-mysql-tables/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 18:32:05 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[ALTER TABLE]]></category>
		<category><![CDATA[DISABLE KEYS]]></category>
		<category><![CDATA[ENABLE KEYS]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/?p=12159</guid>
		<description><![CDATA[
When doing a bulk insert/update/change to a MySQL table you can temporarily disable index updates like this:

ALTER TABLE $tbl_name DISABLE KEYS

&#8230;do stuff&#8230;

ALTER TABLE $tbl_name ENABLE KEYS

From the docs:
ALTER TABLE ... DISABLE KEYS tells MySQL to stop updating non-unique indexes. ALTER TABLE ... ENABLE KEYS then should be used to re-create missing indexes. MySQL does this [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-12159"><!-- &nbsp; --></abbr>
<p>When doing a bulk insert/update/change to a MySQL table you can temporarily disable index updates like this:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql mysql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ALTER TABLE</span> $tbl_name D<span style="color: #66cc66;">IS</span>ABLE <span style="color: #993333; font-weight: bold;">KEYS</span></pre></div></div>

<p>&#8230;do stuff&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="mysql mysql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ALTER TABLE</span> $tbl_name ENABLE <span style="color: #993333; font-weight: bold;">KEYS</span></pre></div></div>

<p>From <a href="http://dev.mysql.com/doc/refman/5.0/en/alter-table.html">the docs</a>:</p>
<blockquote><p><code>ALTER TABLE ... DISABLE KEYS</code> tells MySQL to stop updating non-unique indexes. <code>ALTER TABLE ... ENABLE KEYS</code> then should be used to re-create missing indexes. MySQL does this with a special algorithm that is much faster than inserting keys one by one, so disabling keys before performing bulk insert operations should give a considerable speedup. Using <code>ALTER TABLE ... DISABLE KEYS</code> requires the <code>INDEX</code> privilege in addition to the privileges mentioned earlier.<br />
While the non-unique indexes are disabled, they are ignored for statements such as <code>SELECT</code> and <code>EXPLAIN</code> that otherwise would use them.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/12159/optimizing-insertsupdates-on-mysql-tables/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WordPress to_ping Query Optimization</title>
		<link>http://maisonbisson.com/blog/post/12034/wordpress-to_ping-query-optimization/</link>
		<comments>http://maisonbisson.com/blog/post/12034/wordpress-to_ping-query-optimization/#comments</comments>
		<pubDate>Wed, 23 Jan 2008 17:34:26 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[fixed]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[query optimization]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/post/12034/wordpress-to_ping-query-optimization-2</guid>
		<description><![CDATA[
The WordPress team has taken up the issue of performance optimization pretty seriously, and I look forward to the fruits of their efforts, but I&#8217;m also casting a critical eye on my own code. Thanks to caching and a hugely optimized query architecture, Scriblio is now performing better than ever, and I&#8217;m now looking at [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-12034"><!-- &nbsp; --></abbr>
<p>The WordPress team has taken up the issue of <a href="http://boren.nu/archives/2007/11/13/wordpress-24-performance-profiling/">performance optimization</a> pretty seriously, and I look forward to the fruits of their efforts, but I&#8217;m also casting a critical eye on my own code. Thanks to caching and a hugely optimized query architecture, Scriblio is now performing better than ever, and I&#8217;m now looking at the next tier of problems.</p>
<p>First among them is a WordPress query that runs to find which posts have pingbacks or trackbacks waiting to be processed. As it was originally written, it looked like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$trackbacks</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get_results</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;
	 SELECT ID 
	 FROM $wpdb-&gt;posts 
	 WHERE CHAR_LENGTH(TRIM(to_ping)) &gt; 7 
	 AND post_status = 'publish'
	&quot;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>The problem is that the query requires a full table scan, and it can&#8217;t be optimized simply by creating an index on <code>to_ping</code> because <code>CHAR_LENGTH(TRIM(to_ping)) > 7</code> requires inspecting every row and applying the functions before the result can be tested. As written, the query could take as long as 15 minutes to execute on a busy table of 350,000 rows.</p>
<p>Once I read through the code and determined that it&#8217;s very unlikely that cruft would be left in <code>to_ping</code>, or that any that was there would get removed once processed through the ping functions, I decided to try the query below. (Hat tip also to <a href="http://andy.wordpress.com/" title="Andy Skelton">Andy Skelton</a> for sanity checking my reading of the code.)</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$trackbacks</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get_results</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;
	 SELECT ID 
	 FROM $wpdb-&gt;posts 
	 WHERE to_ping &lt;&gt; '' 
	 AND post_status = 'publish'
	&quot;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>A <a href="http://trac.wordpress.org/ticket/5649" title="#5649 (to_ping query optimization) - WordPress Trac - Trac">trac ticket</a> has been created and <a href="http://trac.wordpress.org/attachment/ticket/5649/comment_to_ping.diff" title="#5649: comment_to_ping.diff - WordPress Trac - Trac">patch added</a>, but despite the optimized query, a table as large as I&#8217;m working with probably needs an index to keep things running smoothly. So here&#8217;s what I&#8217;ve got:</p>
<p><code>KEY ping_status ( to_ping(1), post_status )</code></p>
<p>I&#8217;ve not yet confirmed that this is the most optimal index, but queries now take a fraction of a second to complete.</p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/12034/wordpress-to_ping-query-optimization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress + Invalid URLs = Extra Database Queries</title>
		<link>http://maisonbisson.com/blog/post/12035/wordpress-invalid-urls-extra-database-queries/</link>
		<comments>http://maisonbisson.com/blog/post/12035/wordpress-invalid-urls-extra-database-queries/#comments</comments>
		<pubDate>Fri, 18 Jan 2008 13:38:13 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[404]]></category>
		<category><![CDATA[behavior]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[permalinks]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/post/12035/wordpress-invalid-urls-extra-database-queries</guid>
		<description><![CDATA[
After reporting weirdness last week I finally sat down with a completely clean and virgin install of WordPress 2.3.2 and traced what happens when you make a permalink request for a non-existent URL.
Here are two sets of URLs to use as examples and context:

These are valid URLs:

http://site.org/archives/101
http://site.org/page-name


These are _not_ valid URLs:

http://site.org/archivezorz/101
http://site.org/favicon.ico



Valid URLs get parsed, the [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-12035"><!-- &nbsp; --></abbr>
<p>After <a href="http://comox.textdrive.com/pipermail/wp-hackers/2008-January/017144.html">reporting weirdness last week</a> I finally sat down with a completely clean and virgin install of WordPress 2.3.2 and traced what happens when you make a permalink request for a non-existent URL.</p>
<p>Here are two sets of URLs to use as examples and context:</p>
<ul>
<li>These are valid URLs:
<ul>
<li>http://site.org/archives/101</li>
<li>http://site.org/page-name</li>
</ul>
</li>
<li>These are _not_ valid URLs:
<ul>
<li>http://site.org/archivezorz/101</li>
<li>http://site.org/favicon.ico</li>
</ul>
</li>
</ul>
<p>Valid URLs get parsed, the expected MySQL queries get executed, and the results are processed and returned to the browser. Normal. The problem is that invalid URLs that get sent through WordPress still result in a query like the following being executed on the database. What?</p>

<div class="wp_syntax"><div class="code"><pre class="mysql mysql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">SQL_CALC_FOUND_ROWS</span>  test_posts.<span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> test_posts  <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span>  <span style="color: #993333; font-weight: bold;">AND</span> post_type <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'post'</span> <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span>post_status <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'pub
lish'</span> <span style="color: #993333; font-weight: bold;">OR</span> post_status <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'private'</span><span style="color: #66cc66;">&#41;</span>  <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> post_date DESC <span style="color: #993333; font-weight: bold;">LIMIT</span> 0, <span style="color: #cc66cc;">10</span></pre></div></div>

<p>That is, even after a URL is sent through <code>WP->parse_request()</code> and found to be invalid/404, WordPress marches on to <code>WP->query_posts()</code> and hits the database with a generic request for the X most recent posts. And because this is executed for every 404, it actually results in a lot of database activity.</p>
<p>In most cases MySQL has cached the result, and so it poses a minimal load on the server. And even if the cache is stale, for most sites it&#8217;s not a particularly resource intensive query.</p>
<p>But, if you&#8217;ve got <a href="http://library.plymouth.edu/browse/?subj=20th+century">350,000 rows in the posts table</a>, it&#8217;s incredibly resource intensive to order all those posts on the <code>post_date</code> (<code>datetime</code>) column. I&#8217;ve seen hundreds of them pile up and take <em>forever</em> to complete after writes to the table. It&#8217;s sufferable if write activity on the posts table is very low, but that&#8217;s not something I want to hope for.</p>
<p>So <a href="http://comox.textdrive.com/pipermail/wp-hackers/2008-January/017264.html">my question to the wp-hackers community</a> is: Do we actually want to execute that query for every 404 under normal circumstances? If not, is the following (or something like it) the stupidest solution?</p>
<p>In <a href="http://svn.automattic.com/wordpress/tags/2.3.2/wp-includes/classes.php">wp-includes/classes.php</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;">	<span style="color: #000000; font-weight: bold;">function</span> query_posts<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #990000;">global</span> <span style="color: #000088;">$wp_the_query</span>;
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">build_query_string</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
		<span style="color: #666666; font-style: italic;">// return if the request URI is a 404</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">did_permalink</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query_vars</span><span style="color: #009900;">&#91;</span><span style="">'error'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="">'404'</span> <span style="color: #009900;">&#41;</span>
			<span style="color: #b1b100;">return</span>;
&nbsp;
		<span style="color: #000088;">$wp_the_query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query_vars</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The above works, but there&#8217;s probably a better way to write it.</p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/12035/wordpress-invalid-urls-extra-database-queries/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Easy MySQL Performance Tips</title>
		<link>http://maisonbisson.com/blog/post/11796/easy-mysql-performance-tips/</link>
		<comments>http://maisonbisson.com/blog/post/11796/easy-mysql-performance-tips/#comments</comments>
		<pubDate>Tue, 05 Jun 2007 15:19:14 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[query optimization]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/post/11796/#easy-mysql-performance-tips</guid>
		<description><![CDATA[
Yes, I&#8217;m still trying to squeeze more performance out of MySQL. And since small changes to a query can make a big difference in performance&#8230;
Here are two really easy things to be aware of:

Never do a COUNT(*) (or anything *, says Zach). Instead, replace the * with the name of the column you&#8217;re searching against [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-11796"><!-- &nbsp; --></abbr>
<p>Yes, I&#8217;m <a href="http://maisonbisson.com/blog/post/10970/">still trying</a> to squeeze more performance out of MySQL. And since small changes to a query can make a big difference in performance&#8230;</p>
<p>Here are two really easy things to be aware of:</p>
<ul>
<li><a href="http://www.mysqlperformanceblog.com/2007/04/10/count-vs-countcol/" title="MySQL Performance Blog » COUNT(*) vs COUNT(col)">Never do a <code>COUNT(*)</code></a> (or anything <code>*</code>, says <a href="http://nosheep.net/">Zach</a>). Instead, replace the <code>*</code> with the name of the column you&#8217;re searching against (and is hopefully indexed). That way some queries can execute entirely in the keycache (while * forces MySQL to read every matching row from the table).</li>
<li>When joining two large tables, but only searching against one, <a href="http://www.mysqlperformanceblog.com/2007/04/06/using-delayed-join-to-optimize-count-and-limit-queries/" title="MySQL Performance Blog » Using delayed JOIN to optimize count(*) and LIMIT queries">put the join statement at the end</a>. Why join the two entire tables when you only have to join the matching rows?</li>
</ul>
<p>I mention these because, well, I&#8217;ve known them forever, but upon seeing them again I realized I hadn&#8217;t really obeyed those simple rules in some of my queries.</p>
<p>Separately, there&#8217;s some pretty good info on <a href="http://www.mysqlperformanceblog.com/2006/06/08/mysql-server-variables-sql-layer-or-storage-engine-specific/" title="MySQL Performance Blog » MySQL Server Variables - SQL layer or Storage Engine specific.">what server variables affect what</a> at mysqlperformanceblog too.</p>
<p><tags>mysql, optimization, query optimization, performance, tips</tags></p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/11796/easy-mysql-performance-tips/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Speedy PHP: Intermediate Code Caching</title>
		<link>http://maisonbisson.com/blog/post/10970/speedy-php-intermediate-code-caching/</link>
		<comments>http://maisonbisson.com/blog/post/10970/speedy-php-intermediate-code-caching/#comments</comments>
		<pubDate>Thu, 31 May 2007 15:10:08 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[acceleration]]></category>
		<category><![CDATA[apc]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[intermediate code cache]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[web applications]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/post/10970/#speedy-php-intermediate-code-caching</guid>
		<description><![CDATA[
I&#8217;ve been working on MySQL optimization for a while, and though there&#8217;s still more to done on that front, I&#8217;ve gotten to the point where the the cumulative query times make up less than half of the page generation time.
So I&#8217;m optimizing code when the solution is obvious (and I hope to rope Zach into [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-10970"><!-- &nbsp; --></abbr>
<p>I&#8217;ve been working on MySQL optimization for a while, and though there&#8217;s still more to done on that front, I&#8217;ve gotten to the point where the the cumulative query times make up less than half of the page generation time.</p>
<p>So I&#8217;m optimizing code when the solution is obvious (and I hope to rope <a href="http://nosheep.net/">Zach</a> into giving the code a performance audit soon), but I&#8217;m also looking at optimizing how PHP works.</p>
<p>Once upon a time, most of us ran PHP as a CGI, and every time a request came in, the PHP interpreter would have to launch, read/compile/execute the script, then spit out the result and shutdown. Now (hopefully) everybody&#8217;s running PHP as an Apache module, so all the time spent launching the interpreter, allocating memory and other resources for it, and then shutting it down and cleaning up after it, is done just once for each thread of Apache.</p>
<p>It might not sound like much, but I had a chance to compare CGI vs. module performance recently and found that a fairly simple, but frequently accessed script running as a CGI completely swamped a server as a CGI (creating a load average over 20), but was hardly noticed when running as a module. </p>
<p>But even as a module, the PHP scripts still need to be interpreted and compiled before they can be executed. And because of the way PHP works, this is done every time the page/script is requested.</p>
<p>Java programmers, among others, criticize PHP for this, but that <a href="http://www.37signals.com/svn/archives2/fear_shark_attacks_and_will_it_scale.php">small inefficiency</a> is part of what makes PHP so easy to use (and popular). And that ease of use means people are building some really interesting <a href="http://gettingreal.37signals.com/ch04_Scale_Later.php">apps worth scaling</a>.</p>
<p>Anyway, there&#8217;s a solution to eliminate that inefficiency in PHP: intermediate code caching.</p>
<p>By caching the executable code generated by the interpreter, then the using the cached copy instead of the source script for the next request, you can enjoy the benefits of PHP&#8217;s easy development and compiled code&#8217;s fast execution time. A number of projects all promise anywhere from double to 10X jump in performance.</p>
<ul>
<li><a href="http://www.php-accelerator.co.uk/" title="The ionCube PHP Accelerator: Home">ionCube PHP Accelerator</a><br />This has the most recognizable “brand,” and some hosting providers even offer it, but it&#8217;s offered <a href="http://phprpms.sourceforge.net/phpa">only in binary form</a> and <a href="http://www.php-accelerator.co.uk/faq.php#license">the license</a> seems intentionally ambiguous (um, <a href="http://www.fsf.org/licensing/essays/free-sw.html">not free</a>?).</li>
<li><a href="http://sourceforge.net/projects/turck-mmcache/" title="SourceForge.net: Turck MMCache for PHP">Turck MMCache for PHP</a><br />Has a good <a href="http://turck-mmcache.sourceforge.net/index_old.html">performance chart</a>, and is GPL&#8217;d, but development appears to have ended in 2003.</li>
<li><a href="http://web.archive.org/web/20040401135239/bwcache.bware.it/cache.htm">afterBURNERr*Cache</a><br />Yeah, I had to point to a page in the Wayback Machine, this project is dead.</li>
<li><a href="http://www.zend.com/products/zend_platform/">Zend Platform Performance Suite</a><br />A commercial suite that includes <a href="http://www.zend.com/products/zend_platform/features_comparison">piles of goodies</a>, if you pay.</li>
<li><a href="http://pecl.php.net/package/apc" title="PECL :: Package :: APC">APC: Alternative PHP Cache</a><br />It&#8217;s under active development and includes Rasmus Lerdorf, the guy who created PHP, among the project leads. License: <a href="http://www.php.net/license/2_02.txt">BSD-style</a> (<a href="http://www.gnu.org/philosophy/license-list.html">non-copyleft</a>)</li>
</ul>
<p>I haven&#8217;t actually tried any of these yet, but I&#8217;m looking for information and suggestions, and I&#8217;m likely to try APC, maybe even Zend soon. Just as soon as I make an app compelling enough (and large enough) to need it.</p>
<p><tags>php, caching, acceleration, zend, apc, intermediate code cache, optimization, scaling, web applications</tags></p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/10970/speedy-php-intermediate-code-caching/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Memcached and Wordpress</title>
		<link>http://maisonbisson.com/blog/post/11489/memcached-and-wordpress/</link>
		<comments>http://maisonbisson.com/blog/post/11489/memcached-and-wordpress/#comments</comments>
		<pubDate>Wed, 13 Dec 2006 17:17:04 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/post/11489/</guid>
		<description><![CDATA[
Ryan Boren wrote about using memcached with WordPress almost a year ago:
Memcached is a distributed memory object caching system. WordPress 2.0 can make use of memcached by dropping in a special backend for the WP object cache. The memcached backend replaces the default backend and directs all cache requests to one or more memcached daemons. [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-11489"><!-- &nbsp; --></abbr>
<p><a href="http://boren.nu//">Ryan Boren</a> <a href="http://ryan.wordpress.com/2005/12/23/memcached-backend/" title="Memcached Backend « Ryan on WordPress">wrote about using</a> <a href="http://www.danga.com/memcached/" title="memcached: a distributed memory object caching system">memcached</a> with WordPress almost a year ago:</p>
<blockquote><p>Memcached is a distributed memory object caching system. WordPress 2.0 can make use of memcached by dropping in a special backend for the WP object cache. The memcached backend replaces the default backend and directs all cache requests to one or more memcached daemons. You must have a memcached daemon running somewhere for this to work. Unless you’re managing the server on which your blog is running, you probably can’t run a memcached daemon, making this backend useless to you. The memcached backend is targeted at ISPs and those running WPMU. If you are using WPMU and distributing DB requests across multiple servers, memcached will come in very handy. Using memcached for a single blog isn’t really worth it. In my tests, it was sometimes slower than using the default object cache backend.</p></blockquote>
<p>The <a href="http://dev.wp-plugins.org/browser/memcached/" title="/memcached/ - WordPress Plugin Repository - Trac">plugin is here</a>, a <a href="http://mu.wordpress.org/forums/topic.php?id=1424" title="WordPress MU › memcached mod « WordPress MU Forums">bug-fix note is here</a>.</p>
<p><tags>WordPress, memcached, optimization, caching</tags></p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/11489/memcached-and-wordpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WordPress 2.1 + WPopac</title>
		<link>http://maisonbisson.com/blog/post/11522/wordpress-21-wpopac/</link>
		<comments>http://maisonbisson.com/blog/post/11522/wordpress-21-wpopac/#comments</comments>
		<pubDate>Tue, 12 Dec 2006 14:58:24 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Libraries & Networked Information]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[WordPress 2.1]]></category>
		<category><![CDATA[wpopac]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/post/11522/</guid>
		<description><![CDATA[
I&#8217;ve been following WP2.1 development, but Aaron Brazell&#8217;s post in the development blog wrapped up a lot of questions all at once.
The short story is that 2.1 is going to bring some really good changes that will allow more flexibility and better optimization of WPopac. Of the four changes Brazell names, the last two, the [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-11522"><!-- &nbsp; --></abbr>
<p>I&#8217;ve been following WP2.1 development, but <a href="http://wordpress.org/development/2006/12/naughty-or-nice/">Aaron Brazell&#8217;s post in the development blog</a> wrapped up a lot of questions all at once.</p>
<p>The short story is that 2.1 is going to bring some really good changes that will allow more flexibility and better optimization of WPopac. Of the four changes Brazell names, the last two, the addition of the <code>post_type</code> column and a change in usage of the <code>post_status</code> column, are where the money is.</p>
<p>I&#8217;m awaiting the final release of 2.1 before building the necessary changes into WPopac, but the benefits will be worth it.</p>
<p><tags>WordPress 2.1, WPopac, optimization, development</tags></p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/11522/wordpress-21-wpopac/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>More bsuite Hacking</title>
		<link>http://maisonbisson.com/blog/post/11248/more-bsuite-hacking/</link>
		<comments>http://maisonbisson.com/blog/post/11248/more-bsuite-hacking/#comments</comments>
		<pubDate>Wed, 05 Apr 2006 16:41:13 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[bstat]]></category>
		<category><![CDATA[bsuite]]></category>
		<category><![CDATA[Chow Kah Soon]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[KahSoon.com]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[update]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/post/11248/</guid>
		<description><![CDATA[
Update: bugfix release b2v6 available.
Some conversations with Chow Kah Soon, who&#8217;s site is  full of diversions from work , finally convinced encouraged me to solve some small problems that were giving him big trouble. Chow Kah Soon is in the lucky, but rare, position of having over 20,000 unique daily visitors to his site, [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-11248"><!-- &nbsp; --></abbr>
<p><strong>Update:</strong> <a href="http://maisonbisson.com/blog/post/11390/">bugfix release b2v6 available</a>.</p>
<p>Some conversations with Chow Kah Soon, who&#8217;s site is <a href="http://www.kahsoon.com/" title="Addicting Games Funny Junk Video Clips - Kahsoon.com"> full of diversions from work </a>, finally <strike>convinced</strike> encouraged me to solve some small problems that were giving him big trouble. Chow Kah Soon is in the lucky, but rare, position of having over 20,000 unique daily visitors to his site, so he&#8217;s sort of my designated stress-tester.</p>
<p>After looking at the logs he shared with me, the table structure, and the queries in bsuite, it was pretty clear that I needed to make some changes to the indexes.</p>
<p>Optimizing the indexes was easy, but how can I make bsuite update those indexes on existing installs? That&#8217;s where <a href="http://codex.wordpress.org/Creating_Tables_with_Plugins">these docs</a> explaining WordPress&#8217; rather unique <a href="http://codex.wordpress.org/Creating_Tables_with_Plugins#Creating_and_Updating_the_Table">dbDelta</a> function come in:</p>
<blockquote><p>Instead of using a normal $wpdb query to make our table, there is a special function in WordPress that we&#8217;ll use that can create a table if it isn&#8217;t there, or change the structure if it doesn&#8217;t match the current table. This will come in very handy if we ever need to make changes to the MySQL structure in the future.</p></blockquote>
<p>The function&#8217;s a little finicky, and it took me a couple minutes to realize that it was tripping up on the backtick quotes (`) I had wrapped around my table and field names. But with that out of the way, it solves the big problem of how to easily add indexes to existing tables. What it doesn&#8217;t solve, sadly, is how to delete existing indexes that aren&#8217;t in the new table definition.</p>
<p>With the dbDelta function implemented, I also finally got around to implementing an auto-install hook that creates or re-configs the tables upon plugin activation. Here&#8217;s the <a href="http://codex.wordpress.org/Creating_Tables_with_Plugins#Calling_the_function">example from the docs</a>:</p>
<blockquote><p><code>add_action('activate_pluginurl','jal_install');</code></p></blockquote>
<p>But I had to Google for <a href="http://wordpress.org/support/topic/65500">this support forum post</a> to <a href="http://timvw.madoka.be/?p=535">understand</a> what the “pluginurl” should be.</p>
<blockquote><p>&#8230;you simply have to use the path of your plugin relative to /wp-content/plugins. Eg: you have a plugin in /wp-content/plugins/wp-spamfilter/wp-spamfilter.php then you have to call add_action as following:</p>
<p><code>add_action(‘activate_wp-spamfilter/wp-spamfilter.php’, ’somefunction’);</code></p></blockquote>
<p>Yes, all of these updates will be released soon. I promise.</p>
<p><tags>bstat, bsuite, Chow Kah Soon, documentation, KahSoon.com, mysql, optimization, update, wordpress</tags></p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/11248/more-bsuite-hacking/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Learning: MySQL Optimization</title>
		<link>http://maisonbisson.com/blog/post/11090/learning-mysql-optimization/</link>
		<comments>http://maisonbisson.com/blog/post/11090/learning-mysql-optimization/#comments</comments>
		<pubDate>Tue, 17 Jan 2006 15:31:56 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[big databases]]></category>
		<category><![CDATA[database optimization]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[mysql optimization]]></category>
		<category><![CDATA[mytop]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[server overload]]></category>
		<category><![CDATA[server sizing]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/?p=11090</guid>
		<description><![CDATA[
I have over 1000 posts here at MaisonBisson, but even so, the table with all those posts is under 3MB. Now I&#8217;ve got a project with 150,000 posts &#8212; yes, 150,000 posts! &#8212; and the table is about 500MB. An associated table, structured sort of like WP&#8217;s postsmeta, has over 1.5 million records and weighs [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-11090"><!-- &nbsp; --></abbr>
<p>I have over 1000 posts here at MaisonBisson, but even so, the table with all those posts is under 3MB. Now I&#8217;ve got a project with 150,000 posts &#8212; yes, 150,000 posts! &#8212; and the table is about 500MB. An associated table, structured sort of like WP&#8217;s postsmeta, has over 1.5 million records and weighs in at over 100MB (not including the 150MB of indexes).</p>
<p>Up to now I&#8217;ve been a “throw more hardware at it” sort of guy &#8212; and in a server with only 1GB of RAM, that&#8217;s probably the best solution &#8212; but I also think it&#8217;s time I learned some MySQL optimization tricks. <a href="http://nosheep.net/">Zach</a>&#8217;s been pushing me to get <a href="http://jeremy.zawodny.com/mysql/mytop/">mytop</a> installed for quite a while, and I finally got around to it.</p>
<blockquote><p>mytop is a console-based (non-gui) tool for monitoring the threads and overall performance of a MySQL 3.22.x, 3.23.x, and 4.x server. It runs on most Unix systems (including Mac OS X) which have Perl, <a href="http://search.cpan.org/search?dist=DBI">DBI</a>, and <a href="http://search.cpan.org/search?dist=TermReadKey">Term::ReadKey</a> installed. And with <a href="http://search.cpan.org/search?dist=ANSIColor">Term::ANSIColor</a> installed you even get color. If you install <a href="http://search.cpan.org/search?mode=module&#038;query=Time%3A%3AHiRes">Time::HiRes</a>, you&#8217;ll get good real-time queries/second stats.</p></blockquote>
<p><tags>mysql, mysql optimization, optimization, server overload, big databases, mytop, server sizing, database optimization, db</tags></p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/11090/learning-mysql-optimization/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>