<?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>MySQL Performance Blog &#187; tuning</title>
	<atom:link href="http://www.mysqlperformanceblog.com/category/tuning/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mysqlperformanceblog.com</link>
	<description>Everything about MySQL Performance</description>
	<lastBuildDate>Sat, 21 Nov 2009 03:11:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MySQL-Memcached or NOSQL Tokyo Tyrant &#8211; part 3</title>
		<link>http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/</link>
		<comments>http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 16:00:43 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[NOSQL]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=1435</guid>
		<description><![CDATA[This is part 3 of our series.  In part 1 we talked about boosting performance with memcached on top of MySQL, in Part 2 we talked about running 100% outside the data with memcached, and now in Part 3 we are going to look at a possible solution to free you from the database.  The [...]]]></description>
			<content:encoded><![CDATA[<p>This is part 3 of our series.  In <a href="http://www.mysqlperformanceblog.com/2009/10/15/mysql-memcached-or-nosql-tokyo-tyrant-part-1/">part 1</a> we talked about boosting performance with memcached on top of MySQL, in<a href="http://www.mysqlperformanceblog.com/2009/10/16/mysql_memcached_tyrant_part2/"> Part 2</a> we talked about running 100% outside the data with memcached, and now in Part 3 we are going to look at a possible solution to free you from the database.  The solution I am going to discuss here is Tokyo Cabinet and Tyrant.</p>
<p>I am not going to give you a primer  or Tutorial on Tyrant and Cabinet, there are plenty of these out there already.  Instead I want to see what sort of performance we can see compared to MySQL and Memcached, and later on other NoSQL solutions.  Tokyo actually allows you to use several types of databases that are supported, there are hash databases which are very similar to memcached, a table database which is similar to your classic database tables where you can add a where clause and search individual columns, and a ton more &#8220;database options&#8221;  beyond just those two.  Again my goal is to not make this a Tokyo Tyrant tutorial but rather show one potential role it can play.</p>
<p>More details can be read about here:<br />
<a href="http://1978th.net/tokyotyrant/"> http://1978th.net/tokyotyrant/</a><br />
<a href="http://1978th.net/tokyocabinet/"> http://1978th.net/tokyocabinet/</a></p>
<p>So if we can get performance similar to memcached with Tokoyo Tyrant when using disk based hash tables it would be a compelling replacement for our application here.  It should provide the interface and the same access we saw in memcached but with disk persistence. So let&#8217;s look at the numbers:</p>
<p><img class="aligncenter size-full wp-image-1519" title="Tyrant -vs- memcached" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/10/more_tc_numbers_html_m31feebd3.jpg" alt="Tyrant -vs- memcached" width="662" height="354" /></p>
<p>Tyrant&#8217;s disk based hash was almost 2x faster then combining memcached and MySQL, and about 20% slower then the all memory memcached approach.  So for this particular application I would have been much better off not storing my data in MySQL and instead looking outside the database for an answer.  Now sure there are other reasons you may want to keep data in the database&#8230; but I am trying to get you to think about your application and if those reasons are really valid.  Helping clients pick the right solution is one of the things we do here at Percona.  If an application requires a database great, but if there is a better solution we want to suggest it.  It&#8217;s our goal to make your application perform optimally.</p>
<p>Finally, one concern you have to have is the scalability of your storage solution.  As load, number of threads, and data size increases how does performance differ or change?  One knock on Tokyo -vs- Memcached is Tokyo is not distributed by default.  Now that&#8217;s not to say we could not shard it based on a hash, or even build an api with the capability built in ( or use the memcached clients which works! )&#8230;  but native support is lacking.  It does support replication which could make some rather interesting architectures in the future.</p>
<p>So lets look at some scalability benchmarks, my server resources are rather limited but I thought I should try throwing more threads and work at the server until it hit its limit and fell over dead.  It&#8217;s interesting to see the number of transactions that occur with a given number of threads.  let&#8217;s look at some of these:</p>
<p><img class="size-full wp-image-1426" title="Threads &amp; Application performance" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/10/db_right_option_html_m52d249fc.gif" alt="Tyrant/MySQL/Memcached Thread Benchmark performance" width="663" height="291" /></p>
<p>As expected the smaller buffer pool struggled ( why a smaller buffer pool?  This simulates a much larger data set.  A BP of 256M with 1GB of data, can give similar performance to 20GB of data and a 5GB BP ).  So with 256M BP and 4GB of memcached we were well off the numbers we hit with a 4GB BP+4Gb of memcached ( which is expected ).   Adding more threads even up to 128 threads increased overall throughput but my load average on the server hit 40 and my CPU was pegged.  At 128 threads I was pegging out my CPU across the board.  Also interesting is I started to hit bottlenecks in MySQL/Innodb when I had enough memory but I increased the threads from 64 to 128.  As time permits I should revisit this and look at increased datasets, and look for area&#8217;s where Tyrant may stumble a bit.</p>
<p>Bottom line given a specific application and data pattern sometimes a relational database is not the appropriate place for storing data.  A tool like Tokyo Tyrant may not be for everyone or every application, but neither is a relational database.  Before building your next application try and understand whether an RDBMS is really needed or not.</p>
<p>How did I do these tests:</p>
<p>The above number were run with 32 Threads, Tyrant was started with 8 threads and 128M of memory,  memached was started with 16 threads ( 1.4 memcached ), mysql was 5.1 XtraDB.  Each environment had 2 tables each with 2 million rows.  The data was identical. memcached and Tyrant stored a comma delimited string to represent the row.   Mysql was running with 256M allocated to the innodb buffer unless otherwise noted.</p>
<p>What&#8217;s next?  Well next I am going to try and continue this series by exploring and benchmarking other NOSQL options and comparing them to database based solutions.  I think showing the performance of a couple of different Tokyo database formats would also be interesting.  What other solutions are people interested in?  I know I have gotten a lot of requests for cassandra #&#8217;s, but what else?  Drop a comment and let me know!</p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by matt |
      <a href="http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/#comments">24 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/&amp;title=MySQL-Memcached or NOSQL Tokyo Tyrant &#8211; part 3" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/&amp;title=MySQL-Memcached or NOSQL Tokyo Tyrant &#8211; part 3" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/&amp;title=MySQL-Memcached or NOSQL Tokyo Tyrant &#8211; part 3" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/&amp;T=MySQL-Memcached or NOSQL Tokyo Tyrant &#8211; part 3" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/&amp;title=MySQL-Memcached or NOSQL Tokyo Tyrant &#8211; part 3" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2009/10/19/mysql_memcached_tyrant_part3/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Tuning for heavy writing workloads</title>
		<link>http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/</link>
		<comments>http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 00:06:55 +0000</pubDate>
		<dc:creator>Yasufumi</dc:creator>
				<category><![CDATA[Innodb]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[patch]]></category>
		<category><![CDATA[tuning]]></category>
		<category><![CDATA[xtradb]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=1376</guid>
		<description><![CDATA[For the my previous post, there was comment to suggest to test db_STRESS benchmark on XtraDB by Dimitri. And I tested and tuned for the benchmark. I will show you the tunings. It should be also tuning procedure for general heavy writing workloads.
At first, &#60;tuning peak performance&#62;. The next, &#60;tuning purge operation&#62; to stabilize performance  [...]]]></description>
			<content:encoded><![CDATA[<p>For the <a href="http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/">my previous post</a>, there was comment to suggest to test <a href="http://dimitrik.free.fr/">db_STRESS benchmark</a> on XtraDB by Dimitri. And I tested and tuned for the benchmark. I will show you the tunings. It should be also tuning procedure for general heavy writing workloads.</p>
<p>At first, &lt;tuning peak performance&gt;. The next, &lt;tuning purge operation&gt; to stabilize performance  and to avoid decreasing performance.</p>
<p><strong>&lt;test condition&gt;</strong></p>
<p>Server:<br />
PowerEdge R900, Four Quad Core E7320 Xeon, 2.13GHz, 32GB Memory, 16X2GB, 667MHz</p>
<p>db_STRESS:<br />
32 sessions, RW=1, dbsize = 1000000, no thinktime</p>
<p>XtraDB: (mysql-5.1.39 + XtraDB-1.0.4-current)<br />
innodb_io_capacity = 4000<br />
innodb_support_xa = false<br />
innodb_file_per_table = true<br />
innodb_buffer_pool_size = 16G<br />
innodb_read_io_threads = 8<br />
innodb_write_io_threads = 8<br />
innodb_flush_log_at_trx_commit = 2<br />
innodb_log_buffer_size = 128M<br />
innodb_log_file_size = 512M<br />
innodb_log_files_in_group = 2<br />
innodb_max_dirty_pages_pct = 90<br />
innodb_flush_method = O_DIRECT<br />
(the followings are XtraDB specific general settings)<br />
innodb_ibuf_active_contract = 1<br />
innodb_adaptive_flushing = false<br />
innodb_adaptive_checkpoint = estimate</p>
<p><strong>&lt;tuning peak performance&gt;</strong></p>
<p>At first, tuning the peak performance to use CPU and IO resource more effectively. To avoid mutex/lock contentions are good to use more CPU resource of many CPUs.</p>
<p><img class="alignnone size-full wp-image-1381" title="purge_thread_test_1ST_TUNE" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/10/purge_thread_test_1ST_TUNE.png" alt="purge_thread_test_1ST_TUNE" width="299" height="238" /></p>
<p>This graph shows the peak performance in tps of db_STRESS.</p>
<p>At current settings, <strong>&#8220;base&#8221;</strong> in the graph is the perfomance. We can confirm the mutex/lock contention roughly by the SEMAPHORES sction of SHOW INNODB STATUS output.</p>
<p><em>&#8220;xx-lock on RW-latch at 0&#215;7f2ff40a3dc0 created in file dict/dict0dict.c line 1627&#8243;</em></p>
<p>It is index-&gt;lock, viewing the source file (and it may be HISTORY table). This is the lock for each index tree. We may be able to disperse the lock using by the partitioning of MySQL. Added the following clause to the HISTORY table definition.</p>
<p style="text-align: center;"><strong>&#8220;PARTITION BY HASH(REF_OBJECT) PARTITIONS 16&#8243;</strong></p>
<p>Now the performance became to <strong>&#8220;+partitioned&#8221;</strong> in the graph. Looking the SEMAPHORES section again,</p>
<p><em>&#8220;has waited at handler/ha_innodb.cc line 7275 for 0.0000 seconds the semaphore:<br />
X-lock on RW-latch at 0xd30320 created in file dict/dict0dict.c line 623&#8243;</em></p>
<p>may be the line which appears for the most times (it is dict_operation_lock). It may be partition specific lock contention. The current XtraDB has the variable to tune the contention.</p>
<p style="text-align: center;"><strong>innodb_stats_update_need_lock = 0</strong> (default 1)</p>
<p>It skip the updating statistics which needs the lock. (it only affects for &#8220;Data_free:&#8221; value of TABLE STATS). And the performance became <strong>&#8220;+skip_stats&#8221;</strong> in the graph.  Then, the next contention at SEMAPHORES section is&#8230;</p>
<p><em>&#8220;Mutex at 0&#215;1b3e3e78 created file trx/trx0rseg.c line 167&#8243;</em></p>
<p>may be remarkable (it is rseg-&gt;mutex). The mutex is for each rollback segments, so we can increase the rsegs to solve the contention problem. XtraDB can increase the rseg.</p>
<p style="text-align: center;"><strong>innodb_extra_rsegments = 64</strong> (affects to initialization of InnoDB)</p>
<p>Recreated database files with the parameter. Then the performance became <strong>&#8220;+rsegs64&#8243;</strong>. At last, the next contention may be <em>&#8220;Mutex at 0&#215;28ce8e0 created file srv/srv0srv.c line 982&#8243;. </em>It is kernel_mutex, currently we don&#8217;t have proper solution for that. The setting seems to be enough for now.</p>
<p><strong>&lt;tuning purge operation&gt;</strong></p>
<p>Next, looking the sequential result in more long term.</p>
<p>The next problem is &#8220;History list length&#8221; growing to huge size. The value is the number of entries in rollback segment. The entries are used for consistent reading of the older transactions. They can be removed when any transactions doesn&#8217;t refer the entry. This removing operation for the entries is called &#8220;purge&#8221; in InnoDB. The purge operation should be done enough on time, because the huge history list affects to performance.</p>
<p>Basically, the purging is done by master_thread (general background thread of InnoDB). The huge history list makes the purge operation slow, and it interferes  with the other tasks of the master_thread (e.g. flushing dirty blocks, treating insert buffer, etc&#8230;). <a href="http://dimitrik.free.fr/blog/index.html">Dimitri</a> implemented a purge_thread to devote to the purging, and also XtraDB has similar purge_thread. Though it seems to make the throughput stabilize, it is not enough still for heavy update workloads. A single purge_thread on one CPU is not enough for updates from user threads on the all of other CPUs.</p>
<p>XtraDB can increase the purge_threads from the next release.</p>
<p style="text-align: center;"><strong>innodb_use_purge_thread = 4</strong></p>
<p style="text-align: left;">seems to be enough for this workload on the server.</p>
<p style="text-align: left;">The first graph of followings is sequential throughput [tps] up to 3500 sec.</p>
<p><img class="alignnone size-full wp-image-1388" title="purge_thread_test_TPS" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/10/purge_thread_test_TPS.png" alt="purge_thread_test_TPS" width="675" height="377" /></p>
<p>The next is tracking the &#8220;History list length&#8221; at the same time.</p>
<p><img class="alignnone size-full wp-image-1389" title="purge_thread_test_HIST_LENGTH" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/10/purge_thread_test_HIST_LENGTH.png" alt="purge_thread_test_HIST_LENGTH" width="675" height="377" /></p>
<pre>"Norm 1.0.4": Normal InnoDB Plugin 1.0.4 without XtraDB specific options
"xtra p_t 0": XtraDB 1.0.4-new (no purge_thread)
"xtra p_t 1": XtraDB 1.0.4-new (single purge_thread similar to Dimitri's)
"xtra p_t 4": XtraDB 1.0.4-new (4 purge threads)</pre>
<p>The graphs show&#8230;</p>
<ul>
<li>The purge thread (&gt; 0) helps to stabilize the throughput greatly.</li>
<li>Increasing the purge threads can suppress the strong growing of the hitory list</li>
<li>The adaptive checkpoint &#8220;estimate&#8221; needs the purge_thread&#8230; (than the adaptive_flushing does)</li>
</ul>
<p>And the last 300secs&#8217; average tps are&#8230;</p>
<pre>"Norm 1.0.4": 5725.47
"xtra p_t 0": 4699.33
"xtra p_t 1": 7130.3
"xtra p_t 4": 9118    (about 60%up from Normal Plugin 1.0.4)</pre>
<p>In the end, the faster and more stable performance of db_STRESS benchmark is obtained by these tunings of XtraDB.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>(Added 2009.10.29)</p>
<p>&lt;<strong>FAQ: Is XtraDB slower than Plugin?</strong>&gt;</p>
<p>I&#8217;d like to say <strong>&#8220;no&#8221;</strong> to this question. We have been adding many tuning options to XtraDB. But they are effective not for all cases, sometimes the performance may get worse because of &#8220;not proper&#8221; or &#8220;too much value&#8221;. We should choose the options correctly. XtraDB is based on InnoDB Plugin and we can set XtraDB same to InnoDB Plugin at least. The following graphs are results of XtraDB and Plugin with same options and same database.</p>
<p>top-left (same condition to above graphs):<br />
innodb_flush_log_at_trx_commit = 2<br />
innodb_doublewrite = true</p>
<p>top-right:<br />
innodb_flush_log_at_trx_commit = 1<br />
innodb_doublewrite = true</p>
<p>bottom-left:<br />
innodb_flush_log_at_trx_commit = 2<br />
innodb_doublewrite = false</p>
<p>bottom-right:<br />
innodb_flush_log_at_trx_commit = 1<br />
innodb_doublewrite = false</p>
<p><img class="alignnone size-full wp-image-1570" title="purge_thread_test_2_TPS" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/10/purge_thread_test_2_TPS.png" alt="purge_thread_test_2_TPS" width="952" height="566" /></p>
<p>It seems that XtraDB is not slower than Plugin here at least.</p>
<p><strong><em>We can start tuning based on these performances using XtraDB specific options!</em></strong></p>
<p>Why do you make XtraDB slower than Plugin? <img src='http://www.mysqlperformanceblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by Yasufumi |
      <a href="http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/#comments">9 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/&amp;title=Tuning for heavy writing workloads" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/&amp;title=Tuning for heavy writing workloads" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/&amp;title=Tuning for heavy writing workloads" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/&amp;T=Tuning for heavy writing workloads" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/&amp;title=Tuning for heavy writing workloads" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2009/10/14/tuning-for-heavy-writing-workloads/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Which adaptive should we use?</title>
		<link>http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/</link>
		<comments>http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 00:12:44 +0000</pubDate>
		<dc:creator>Yasufumi</dc:creator>
				<category><![CDATA[Innodb]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[tuning]]></category>
		<category><![CDATA[xtradb]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=1125</guid>
		<description><![CDATA[As you may know, InnoDB has 2 limits for unflushed modified blocks in the buffer pool. The one is from physical size of the buffer pool. And the another one is oldness of the block which is from the capacity of transaction log files.
In the case of heavy updating workload, the modified ages of the [...]]]></description>
			<content:encoded><![CDATA[<p>As you may know, InnoDB has 2 limits for unflushed modified blocks in the buffer pool. The one is from physical size of the buffer pool. And the another one is oldness of the block which is from the capacity of transaction log files.</p>
<p>In the case of heavy updating workload, the modified ages of the many blocks are clustered. And to reduce the maximum of the modified ages InnoDB needs to flush many of the blocks in a short time, if these are not flushed at all. Then the flushing storm affect the performance seriously.</p>
<p>We suggested the &#8220;adaptive_checkpoint&#8221; option of constant flushing to avoid such a flushing storm. And finally, the newest InnoDB Plugin 1.0.4 has the new similar option &#8220;adaptive_flushing&#8221; as native.</p>
<p>Let&#8217;s check the adaptive flushing options at this post.</p>
<p><em><strong>HOW THEY WORK</strong></em></p>
<p><strong>&lt; adaptive_checkpoint=reflex (older method)&gt;</strong></p>
<table border="1" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td>oldest modified age %/max</td>
<td>behavior</td>
</tr>
<tr>
<td>0 ~ 50%</td>
<td>nothing</td>
</tr>
<tr>
<td>50% ~ 75%</td>
<td>constant flushing (weak)</td>
</tr>
<tr>
<td>75% ~ 87.5%</td>
<td>constant flushing (strong)</td>
</tr>
<tr>
<td>87.5% ~</td>
<td>(flushing storm)</td>
</tr>
</tbody>
</table>
<p><strong>&lt; adaptive_checkpoint=estimate (newer method)&gt;</strong></p>
<table border="1" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td>oldest modified age %/max</td>
<td>behavior</td>
</tr>
<tr>
<td>0 ~ 50%</td>
<td>nothing</td>
</tr>
<tr>
<td>50% ~ 87.5%</td>
<td>estimate flushing as bellow *</td>
</tr>
<tr>
<td>87.5% ~</td>
<td>(flushing storm)</td>
</tr>
</tbody>
</table>
<p>* estimate blocks to flush based on&#8230;</p>
<ul>
<li> how many modified and unflushed blocks</li>
<li> progress speed of the transaction log</li>
<li> the modified age average of all blocks to flush</li>
</ul>
<p><strong>&lt; adaptive_flushing (default &#8220;true&#8221; at 1.0.4)&gt;</strong><br />
Its behavior is not based on the oldest modified age %.</p>
<p>* the how many blocks to flush based on&#8230;</p>
<ul>
<li> how many modified and unflushed blocks</li>
<li> progress speed of the transaction log</li>
<li> transaction log capacity</li>
</ul>
<p>(and adjust along with another flushing)</p>
<p>And it doesn&#8217;t exceed the equivalent to &#8220;constant flushing (strong)&#8221;<br />
of the &#8220;adaptive_checkpoint=reflex&#8221;</p>
<p><em><strong>RESULTS</strong></em></p>
<p>TPC-C like workload (100WH: 16 session full)</p>
<p>innodb_buffer_pool_size = 16G<br />
innodb_max_dirty_pages_pct = 90</p>
<p>innodb_log_file_size = 512M<br />
innodb_log_files_in_group = 2</p>
<p>innodb_io_capacity = 4000<br />
innodb_read_io_threads = 8<br />
innodb_write_io_threads = 8<br />
innodb_flush_method = O_DIRECT</p>
<p>innodb_thread_concurrency = 0<br />
innodb_ibuf_active_contract = 1</p>
<p><strong>&lt;none&gt;</strong><br />
innodb_adaptive_flushing = false<br />
innodb_adaptive_checkpoint = none</p>
<p><strong>&lt;flushing&gt;</strong><br />
innodb_adaptive_flushing = true</p>
<p><strong>&lt;reflex&gt;</strong><br />
innodb_adaptive_flushing = false<br />
innodb_adaptive_checkpoint = reflex</p>
<p><strong>&lt;estimate&gt;</strong><br />
innodb_adaptive_flushing = false<br />
innodb_adaptive_checkpoint = estimate</p>
<p><strong><em>case1: &#8220;innodb_doublewrite = false&#8221;</em></strong></p>
<p>[0~1800 sec.]</p>
<p><img class="alignnone size-full wp-image-1132" title="no_doublewrite-0-1800" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/09/no_doublewrite-0-18001.png" alt="no_doublewrite-0-1800" width="705" height="388" /></p>
<p>[1200~1800 sec.]</p>
<p><img class="alignnone size-full wp-image-1134" title="no_doublewrite-1200-1800" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/09/no_doublewrite-1200-1800.png" alt="no_doublewrite-1200-1800" width="705" height="388" /></p>
<p>averages (1200~1800 sec.)<br />
none:     6868.92<br />
flushing: 6655.92<br />
reflex:     6481<br />
estimate: 6575.88</p>
<p><strong><em>case2: &#8220;innodb_doublewrite = true&#8221;</em></strong></p>
<p>[0~1800 sec.]</p>
<p><img class="alignnone size-full wp-image-1137" title="doublewrite-0-1800" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/09/doublewrite-0-1800.png" alt="doublewrite-0-1800" width="705" height="388" /></p>
<p>[1200~1800 sec.]</p>
<p><img class="alignnone size-full wp-image-1138" title="doublewrite-1200-1800" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/09/doublewrite-1200-1800.png" alt="doublewrite-1200-1800" width="705" height="388" /></p>
<p>averages (1200~1800 sec.)<br />
none:     6569.48<br />
flushing: 5090.12<br />
reflex:     6871.9<br />
estimate: 6609.9</p>
<p><strong><em>CONSIDERINGS</em></strong></p>
<p>The new &#8220;adaptive_flushing&#8221; seems to be tuned for &#8220;innodb_doublewrite = false&#8221; only.<br />
(cause too much flushing for &#8220;innodb_doublewrite = true&#8221;)</p>
<p>&#8220;innodb_adaptive_checkpoint = reflex&#8221; and &#8220;adaptive_flushing&#8221; need tuning innodb_io_capacity properly.<br />
(The result is based on proper value &#8220;innodb_io_capacity = 4000&#8243;)</p>
<p>&#8220;innodb_adaptive_checkpoint = estimate&#8221; is not depend on innodb_io_capacity, and it seems more &#8220;soft&#8221; result than the other methods.</p>
<p>So,</p>
<p>The &#8220;adaptive_flushing&#8221; seems good when we use &#8220;innodb_doublewrite = false&#8221;.</p>
<p>&#8220;innodb_adaptive_checkpoint = estimate&#8221; may be safe for &#8220;innodb_doublewrite = true&#8221; for now.</p>
<p>I should adjust &#8220;adaptive_flushing&#8221; for &#8220;innodb_doublewrite = true&#8221;. <img src='http://www.mysqlperformanceblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<hr /><em><strong>IMPROVEMENTS</strong></em> (16 Sep.)</p>
<p>I have tried to improve the performance. But I couldn&#8217;t adjust performance of adaptive_flushing with doublewrite&#8230; So, instead of that, estimate is adjusted more.</p>
<p><strong><em>case1: &#8220;innodb_doublewrite = false&#8221;</em></strong></p>
<p>[0~1800 sec.]</p>
<p><img class="alignnone size-full wp-image-1159" title="no_doublewrite-0-1800_2" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/09/no_doublewrite-0-1800_21.png" alt="no_doublewrite-0-1800_2" width="705" height="388" /></p>
<p><strong><em>case2: &#8220;innodb_doublewrite = true&#8221;</em></strong></p>
<p>[0~1800 sec.]</p>
<p><img class="alignnone size-full wp-image-1160" title="doublewrite-0-1800_2" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/09/doublewrite-0-1800_2.png" alt="doublewrite-0-1800_2" width="705" height="388" /></p>
<p>The new &#8220;innodb_adaptive_checkpoint = estimate&#8221; seems to be more stable than before. The next question is, <strong>&#8220;Why is estimate + doublewrite better than the other no doublewrite settings?&#8221;</strong>&#8230; <img src='http://www.mysqlperformanceblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<hr /><strong>ADDITIONAL TEST IN ANOTHER BALANCE</strong></p>
<p>Also tested in another configuration to check the behaviors in another balance of IO bound.</p>
<p>&lt;changes&gt;<br />
innodb_buffer_pool_size = 2G   (1/8)<br />
innodb_log_file_size = 128M    (1/4)</p>
<p><strong><em>case1: &#8220;innodb_doublewrite = false&#8221;</em></strong></p>
<p>[0~1200 sec.]</p>
<p><img class="alignnone size-full wp-image-1202" title="no_doublewrite_2-0-1200" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/09/no_doublewrite_2-0-1200.png" alt="no_doublewrite_2-0-1200" width="705" height="387" /></p>
<p><strong><em>case2: &#8220;innodb_doublewrite = true&#8221;</em></strong></p>
<p>[0~1200 sec.]</p>
<p><img class="alignnone size-full wp-image-1203" title="doublewrite_2-0-1200" src="http://www.mysqlperformanceblog.com/wp-content/uploads/2009/09/doublewrite_2-0-1200.png" alt="doublewrite_2-0-1200" width="705" height="387" /></p>
<p>&#8220;innodb_adaptive_checkpoint = estimate&#8221; seems stable but seems to flush much in its initial phase. The adaptive_flushing seems to be more soft in this cases.</p>
<p>Hmmm&#8230;.</p>
<p><strong>We should choose suitable adaptive_xxx for each workload for now</strong>&#8230; <img src='http://www.mysqlperformanceblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by Yasufumi |
      <a href="http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/#comments">12 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/&amp;title=Which adaptive should we use?" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/&amp;title=Which adaptive should we use?" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/&amp;title=Which adaptive should we use?" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/&amp;T=Which adaptive should we use?" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/&amp;title=Which adaptive should we use?" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2009/09/15/which-adaptive-should-we-use/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Scaling IO Bound Workloads Webinar</title>
		<link>http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/</link>
		<comments>http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/#comments</comments>
		<pubDate>Sat, 20 Jun 2009 03:18:32 +0000</pubDate>
		<dc:creator>peter</dc:creator>
				<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=704</guid>
		<description><![CDATA[I will co-present in webinar  on Performance Challenges and Solutions for IO Bound Workloads in MySQL.    My part of the presentation will be speaking about why switching from CPU bound workload to IO bound is such an important event, how to prepare to it as well as how to keep your [...]]]></description>
			<content:encoded><![CDATA[<p>I will co-present in <a href="http://www1.schoonerinfotech.com/news-and-events/press-releases/schooner-webinar.html">webinar</a>  on Performance Challenges and Solutions for IO Bound Workloads in MySQL.    My part of the presentation will be speaking about why switching from CPU bound workload to IO bound is such an important event, how to prepare to it as well as how to keep your application performance good as the data growths.</p>
<p>The Brian&#8217;s portion of webinar will focus on the Schooner offering as  example of flash based appliance &#8211; one of solutions I mention in my presentation. </p>
<p>It should be interesting whenever you&#8217;re interested in Schooner appliance offerings, flash or scaling MySQL in General.</p>
<p>You can follow this <a href="http://www1.schoonerinfotech.com/x169.xml">url</a> to register. </p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by peter |
      <a href="http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/#comments">2 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/&amp;title=Scaling IO Bound Workloads Webinar" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/&amp;title=Scaling IO Bound Workloads Webinar" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/&amp;title=Scaling IO Bound Workloads Webinar" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/&amp;T=Scaling IO Bound Workloads Webinar" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/&amp;title=Scaling IO Bound Workloads Webinar" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2009/06/19/scaling-io-bound-workloads-webinar/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A rule of thumb for choosing column order in indexes</title>
		<link>http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/</link>
		<comments>http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 12:30:39 +0000</pubDate>
		<dc:creator>Baron Schwartz</dc:creator>
				<category><![CDATA[tips]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=663</guid>
		<description><![CDATA[I wanted to share a little rule of thumb I sometimes use to decide which columns should come first in an index.  This is not specific to MySQL, it's generally applicable to any database server with b-tree indexes.  And there are a bunch of subtleties, but I will also ignore those for the [...]]]></description>
			<content:encoded><![CDATA[<p>I wanted to share a little rule of thumb I sometimes use to decide which columns should come first in an index.  This is not specific to MySQL, it's generally applicable to any database server with b-tree indexes.  And there are a bunch of subtleties, but I will also ignore those for the sake of simplicity.</p>
<p>Let's start with this query, which returns zero rows but does a full table scan.  EXPLAIN says there are no possible_keys.</p>
<div class="igBar"><span id="lsql-5"><a href="#" onclick="javascript:showPlainTxt('sql-5'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-5">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> * <span style="color: #993333; font-weight: bold;">FROM</span> tbl <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">STATUS</span>=<span style="color: #ff0000;">'waiting'</span> <span style="color: #993333; font-weight: bold;">AND</span> source=<span style="color: #ff0000;">'twitter'</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;<span style="color: #993333; font-weight: bold;">AND</span> no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span> <span style="color: #993333; font-weight: bold;">AND</span> tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> date <span style="color: #993333; font-weight: bold;">ASC</span> <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;color:#800000;">1</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Don't try to figure out the meaning of the query, because that'll add complexity to the example <img src='http://www.mysqlperformanceblog.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />   In the simplest case, we want to put the most selective column first in the index, so that the number of possible matching rows is the smallest, i.e. we find the rows as quickly as possible.  Assuming that all the columns have an even distribution of values, we can just count the number of matching rows for each criterion.</p>
<div class="igBar"><span id="lsql-6"><a href="#" onclick="javascript:showPlainTxt('sql-6'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-6">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> sum<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #993333; font-weight: bold;">STATUS</span>=<span style="color: #ff0000;">'waiting'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, sum<span style="color:#006600; font-weight:bold;">&#40;</span>source=<span style="color: #ff0000;">'twitter'</span><span style="color:#006600; font-weight:bold;">&#41;</span>,</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, sum<span style="color:#006600; font-weight:bold;">&#40;</span>tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span><span style="color:#006600; font-weight:bold;">&#41;</span>, count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;<span style="color: #993333; font-weight: bold;">FROM</span> tbl\G</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;*************************** <span style="color: #cc66cc;color:#800000;">1</span>. row ***************************</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #993333; font-weight: bold;">STATUS</span> =<span style="color: #ff0000;">'waiting'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">550</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sum<span style="color:#006600; font-weight:bold;">&#40;</span>source=<span style="color: #ff0000;">'twitter'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">37271</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">36975</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">36569</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">37271</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>This is pretty simple -- all I did was wrap each clause in a SUM() function, which in MySQL is equivalent to COUNT(number_of_times_this_is_true).  It looks like the most selective criterion is "status=waiting".  Let's put that column first in the index.  Now, pull it out of the SELECT list and put it into the WHERE clause, and run the query again to get numbers within the subset of rows that match:</p>
<div class="igBar"><span id="lsql-7"><a href="#" onclick="javascript:showPlainTxt('sql-7'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-7">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> sum<span style="color:#006600; font-weight:bold;">&#40;</span>source=<span style="color: #ff0000;">'twitter'</span><span style="color:#006600; font-weight:bold;">&#41;</span>,</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, sum<span style="color:#006600; font-weight:bold;">&#40;</span>tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span><span style="color:#006600; font-weight:bold;">&#41;</span>, count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;<span style="color: #993333; font-weight: bold;">FROM</span> tbl <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">STATUS</span>=<span style="color: #ff0000;">'waiting'</span>\G</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;*************************** <span style="color: #cc66cc;color:#800000;">1</span>. row ***************************</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sum<span style="color:#006600; font-weight:bold;">&#40;</span>source=<span style="color: #ff0000;">'twitter'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">549</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">255</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">294</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">549</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>So we're down to a reasonable number of rows (the count() is changing because I'm running this on live data, by the way).  It looks like the 'source' is no more selective, that is, it won't filter out any more rows within this set.  So adding it to the index would not be useful.  We can filter this set further by either the 'no_send_before' or the 'tries' column.  Doing so on either will reduce the count of matches for the other to zero:</p>
<div class="igBar"><span id="lsql-8"><a href="#" onclick="javascript:showPlainTxt('sql-8'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-8">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> sum<span style="color:#006600; font-weight:bold;">&#40;</span>source=<span style="color: #ff0000;">'twitter'</span><span style="color:#006600; font-weight:bold;">&#41;</span>,</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, sum<span style="color:#006600; font-weight:bold;">&#40;</span>tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span><span style="color:#006600; font-weight:bold;">&#41;</span>, count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;<span style="color: #993333; font-weight: bold;">FROM</span> tbl <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">STATUS</span>=<span style="color: #ff0000;">'waiting'</span> <span style="color: #993333; font-weight: bold;">AND</span> no_send_before</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;&lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span>\G</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;*************************** <span style="color: #cc66cc;color:#800000;">1</span>. row ***************************</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sum<span style="color:#006600; font-weight:bold;">&#40;</span>source=<span style="color: #ff0000;">'twitter'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">255</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">255</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">0</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">255</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> sum<span style="color:#006600; font-weight:bold;">&#40;</span>source=<span style="color: #ff0000;">'twitter'</span><span style="color:#006600; font-weight:bold;">&#41;</span>,</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, sum<span style="color:#006600; font-weight:bold;">&#40;</span>tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span><span style="color:#006600; font-weight:bold;">&#41;</span>, count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;<span style="color: #993333; font-weight: bold;">FROM</span> tbl <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">STATUS</span>=<span style="color: #ff0000;">'waiting'</span> <span style="color: #993333; font-weight: bold;">AND</span> tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span>\G</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;*************************** <span style="color: #cc66cc;color:#800000;">1</span>. row ***************************</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sum<span style="color:#006600; font-weight:bold;">&#40;</span>source=<span style="color: #ff0000;">'twitter'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">294</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>no_send_before &lt;= <span style="color: #ff0000;">'2009-05-28 03:17:50'</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">0</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sum<span style="color:#006600; font-weight:bold;">&#40;</span>tries &lt;= <span style="color: #cc66cc;color:#800000;">20</span><span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">294</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span>: <span style="color: #cc66cc;color:#800000;">294</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>That means we can add an index on either of (status,tries) or (status,no_send_before) and we will find the zero rows pretty efficiently.  Which is better depends on what this table is really used for, which is a question I'm avoiding.</p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by Baron Schwartz |
      <a href="http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/#comments">13 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/&amp;title=A rule of thumb for choosing column order in indexes" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/&amp;title=A rule of thumb for choosing column order in indexes" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/&amp;title=A rule of thumb for choosing column order in indexes" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/&amp;T=A rule of thumb for choosing column order in indexes" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/&amp;title=A rule of thumb for choosing column order in indexes" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2009/06/05/a-rule-of-thumb-for-choosing-column-order-in-indexes/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>How much memory can MySQL use in the worst case?</title>
		<link>http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/</link>
		<comments>http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 00:07:31 +0000</pubDate>
		<dc:creator>Baron Schwartz</dc:creator>
				<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=625</guid>
		<description><![CDATA[I vaguely recall a couple of blog posts recently asking something like "what's the formula to compute mysqld's worst-case maximum memory usage?"  Various formulas are in wide use, but none of them is fully correct.  Here's why: you can't write an equation for it.
The most popular equation, of course, is the one in [...]]]></description>
			<content:encoded><![CDATA[<p>I vaguely recall a couple of blog posts recently asking something like "what's the formula to compute mysqld's worst-case maximum memory usage?"  Various formulas are in wide use, but none of them is fully correct.  Here's why: you can't write an equation for it.</p>
<p>The most popular equation, of course, is the one in the error log after a crash: "It is possible that mysqld could use up to key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections".  This was never true -- not even when ISAM and friends were the only storage engines, which was before most of us remember.  And at a minimum, most servers these days need to consider the added memory for InnoDB: specifically, the buffer pool.  (There's also an innodb_additional_mem_pool_size but it's typically set pretty small, like 20M).</p>
<p>But even that's not enough.  Staying with InnoDB, we also need to count the data dictionary.  This can take many gigabytes on servers with a lot of tables.  <a href="http://www.mysqlperformanceblog.com/2009/02/11/limiting-innodb-data-dictionary/">We're trying to fix that</a>, but it's unbounded in a non-Percona server.  And InnoDB has other needs that it doesn't actually promise to fit within  innodb_additional_mem_pool_size, by the way.  If it needs more it will allocate it.   innodb_additional_mem_pool_size is just a handy way to avoid repeated malloc() calls by doing it all up front in one call.</p>
<p>And what about the query cache and the table cache and the size needed for each thread (thread stack, etc)?  Those take memory too.  The query cache can use quite a bit if it's configured to.  There are a bunch more global buffers to think about; that's just a partial list.  And there are some "global buffers" that aren't really global.  Suppose you set sort_buffer_size to 128K -- I can quite well connect and say "set @@sort_buffer_size := 1 * 1024 * 1024 * 1024;" and my sort_buffer_size is now 1GB.  And a single query may cause multiple sort buffers to be allocated.  You can't control that or calculate it at a global level.</p>
<p>But let's keep going! Any stored code (triggers, stored routines, etc) uses memory to execute; so do temporary tables.  The following query creates at least 2 temporary tables:</p>
<div class="igBar"><span id="lsql-11"><a href="#" onclick="javascript:showPlainTxt('sql-11'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-11">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> * <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color: #993333; font-weight: bold;">SELECT</span> * <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #cc66cc;color:#800000;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> a <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> b <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> c; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>You can have many of those <em>per query</em>.  Sorting and grouping and DISTINCT and UNION may/will also create temp tables; the same applies to views and probably some other things I'm forgetting.</p>
<p>Let's not forget about the memory needed to parse and optimize and execute queries; mysqld creates internal structures for the query plan, for example, and keeps it around until the query is done.  And there are prepared statements, which you can create and never deallocate.</p>
<p>Any more?  Of course...  I can also set a bunch of user variables -- they use memory too.  And they can be really big (but no bigger than max_allowed_packet).  And keys for user locks!  I set my max_allowed_packet bigger and ran the following on my laptop:</p>
<div class="igBar"><span id="lsql-12"><a href="#" onclick="javascript:showPlainTxt('sql-12'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-12">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SET</span> @a := repeat<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #ff0000;">'a'</span>, <span style="color: #cc66cc;color:#800000;">1024</span> * <span style="color: #cc66cc;color:#800000;">1024</span> * <span style="color: #cc66cc;color:#800000;">100</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Query OK, <span style="color: #cc66cc;color:#800000;">0</span> rows affected <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">34</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SELECT</span> get_lock<span style="color:#006600; font-weight:bold;">&#40;</span>@a, <span style="color: #cc66cc;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">-----------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| get_lock<span style="color:#006600; font-weight:bold;">&#40;</span>@a, <span style="color: #cc66cc;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">-----------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">|&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">1</span> | </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">-----------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">3</span>.<span style="color: #cc66cc;color:#800000;">63</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Now I've got a 100M user variable and a 100M lock key.  Note how long it took to run these statements!  And now mysqld is suddenly using 324M of memory, up from 124M.</p>
<p>I'm sure you can think of other things I've forgotten here (the <a href="http://dev.mysql.com/doc/en/memory-use.html">manual page</a> has a bunch).  My point is there simply is no formula to compute the maximum possible memory usage, <em>and there cannot be</em> because there are some things that have no defined limits.</p>
<p>It's not something that's worth worrying about much, in my opinion.  I think it's far better to use a monitoring tool to watch the actual memory usage over time and see how it varies.  When I'm initially setting up a my.cnf for a server, I usually calculate the Big Ones like the buffer pool, query cache etc; leave some memory for other needs; and see what happens.  The results are workload-specific.</p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by Baron Schwartz |
      <a href="http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/#comments">16 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/&amp;title=How much memory can MySQL use in the worst case?" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/&amp;title=How much memory can MySQL use in the worst case?" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/&amp;title=How much memory can MySQL use in the worst case?" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/&amp;T=How much memory can MySQL use in the worst case?" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/&amp;title=How much memory can MySQL use in the worst case?" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2009/02/12/how-much-memory-can-mysql-use-in-the-worst-case/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Profiling MySQL stored routines</title>
		<link>http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/</link>
		<comments>http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 09:33:39 +0000</pubDate>
		<dc:creator>Aurimas Mikalauskas</dc:creator>
				<category><![CDATA[community]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=589</guid>
		<description><![CDATA[These days I'm working with a customer who has an application based entirely on stored routines on MySQL side. Even though I haven't worked much with stored procedures, I though it's going to be a piece of cake. In the end - it was, but there's a catch.
My initial idea was - I'll just analyze [...]]]></description>
			<content:encoded><![CDATA[<p>These days I'm working with a customer who has an application based entirely on stored routines on MySQL side. Even though I haven't worked much with stored procedures, I though it's going to be a piece of cake. In the end - it was, but there's a catch.</p>
<p>My initial idea was - I'll just analyze queries in the slow query log generated by <a title="MySQL releases with Percona patchset" href="http://www.percona.com/percona-lab.html" target="_blank">our mysql build</a> running with long_query_time=0, get the slowest ones and work on them. It wasn't really all the way I expected..</p>
<p>For a showcase I have created a function "whatstheweatherlike". Let's call it and see what shows up in the slow query log:</p>
<div class="igBar"><span id="lsql-15"><a href="#" onclick="javascript:showPlainTxt('sql-15'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-15">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SELECT</span> whatstheweatherlike<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------------------------------------------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| whatstheweatherlike<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------------------------------------------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Its <span style="color: #cc66cc;color:#800000;">5</span>°C, time <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #cc66cc;color:#800000;">02</span>:<span style="color: #cc66cc;color:#800000;">28</span>:<span style="color: #cc66cc;color:#800000;">05</span>, feels <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color: #993333; font-weight: bold;">LIKE</span><span style="color:#006600; font-weight:bold;">&#93;</span> almost summer!&nbsp; &nbsp;|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------------------------------------------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">00</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">host <span style="color: #808080; font-style: italic;"># tail /var/log/mysql/mysql-slow.log</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># Time: 090115&nbsp; 2:25:28</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># User@Host: me[me] @ localhost []</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># Thread_id: 3432&nbsp; Schema: test</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># Query_time: 0.000695&nbsp; Lock_time: 0.000284&nbsp; Rows_sent: 1&nbsp; Rows_examined: 0&nbsp; Rows_affected: 0&nbsp; Rows_read: 1</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># QC_Hit: No&nbsp; Full_scan: No&nbsp; Full_join: No&nbsp; Tmp_table: No&nbsp; Tmp_table_on_disk: No</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># Filesort: No&nbsp; Filesort_on_disk: No&nbsp; Merge_passes: 0</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #808080; font-style: italic;"># No InnoDB statistics available for this query</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #993333; font-weight: bold;">SELECT</span> whatstheweatherlike<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Not overly useful for query optimization, is it? Well, I can still aggregate the slow query log with <a title="Maatkit log parser" href="http://www.maatkit.org/doc/mk-log-parser.html" target="_blank">mk-log-parser</a> and find routines that MySQL spends most of the time on, but I don't want to go over the complicated logic of stored procedure just to figure out what queries are being executed. This is where <a title="MySQL SHOW PROFILE patch" href="http://lists.mysql.com/internals/33768" target="_blank">Jeremy's SHOW PROFILE patch</a> - which is included in all Community tree based Percona MySQL builds since it is part of MySQL community version ever since 5.0.37 (note - not all Percona builds are done on Community tree) - comes into play. Let me show you how this works:</p>
<div class="igBar"><span id="lsql-16"><a href="#" onclick="javascript:showPlainTxt('sql-16'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-16">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SET</span> profiling=<span style="color: #cc66cc;color:#800000;">1</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Query OK, <span style="color: #cc66cc;color:#800000;">0</span> rows affected <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">00</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SELECT</span> whatstheweatherlike<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">3</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">-----------------------------------------------------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| whatstheweatherlike<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">3</span><span style="color:#006600; font-weight:bold;">&#41;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">-----------------------------------------------------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Its <span style="color: #cc66cc;color:#800000;">3</span>°C, time <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #cc66cc;color:#800000;">02</span>:<span style="color: #cc66cc;color:#800000;">43</span>:<span style="color: #cc66cc;color:#800000;">25</span>, feels <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color: #993333; font-weight: bold;">LIKE</span><span style="color:#006600; font-weight:bold;">&#93;</span> snow <span style="color: #993333; font-weight: bold;">IS</span> melting&nbsp; &nbsp;| </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">-----------------------------------------------------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">00</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SHOW</span> profiles;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------+------------+-------------------------------------------------------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Query_ID | Duration&nbsp; &nbsp;| Query&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------+------------+-------------------------------------------------------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">|&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;color:#800000;">1</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">00005100</span> | <span style="color: #993333; font-weight: bold;">SELECT</span> CURTIME<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> time&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">|&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;color:#800000;">2</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">00014100</span> | <span style="color: #993333; font-weight: bold;">SELECT</span> feeling <span style="color: #993333; font-weight: bold;">INTO</span> feels <span style="color: #993333; font-weight: bold;">FROM</span> weather <span style="color: #993333; font-weight: bold;">WHERE</span> temp = in_temp |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------+------------+-------------------------------------------------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">2</span> rows <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">00</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>So now not only do we get to see what queres were executed, how much time they spent executing but we can also get a profile for each of the queries individually. I think this is pretty cool and it helped me a lot. Sure, you may still need to check routine and track the logic so having constants that were used rather than variables would be even more useful. Nevertheless I think this is a great way to find what's happening under the scenes so you could start digging deeper.</p>
<p>On the other hand, this way of manual profiling you can't really see real time stats, for example if it was slow because of locks, in the logs you may not see it. I will ask my colleagues to check if it would be hard to implement configurable variable for switching between routine and query logging, so maybe one day we'll be able to have both ways of looking at it.</p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by Aurimas Mikalauskas |
      <a href="http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/#comments">3 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/&amp;title=Profiling MySQL stored routines" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/&amp;title=Profiling MySQL stored routines" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/&amp;title=Profiling MySQL stored routines" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/&amp;T=Profiling MySQL stored routines" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/&amp;title=Profiling MySQL stored routines" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2009/01/19/profiling-mysql-stored-routines/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Goal driven performance optimization</title>
		<link>http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/</link>
		<comments>http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 02:23:55 +0000</pubDate>
		<dc:creator>peter</dc:creator>
				<category><![CDATA[production]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=575</guid>
		<description><![CDATA[When your goal is to optimize application performance it is very important to understand what goal do you really have.  If you do not have a good understanding of the goal your performance optimization effort may well still bring its results but you may waste a lot of time before you reach same results [...]]]></description>
			<content:encoded><![CDATA[<p>When your goal is to optimize application performance it is very important to understand what goal do you really have.  If you do not have a good understanding of the goal your performance optimization effort may well still bring its results but you may waste a lot of time before you reach same results as you would reach much sooner with focused approach.   </p>
<p>The time is critical for many performance optimization tasks not only because of labor associated expenses but also because of the suffering - slow web site means your marketing budget is wasted, customer not completing purchases, users are leaving to competitors, all of this making the time truly critical matter.</p>
<p>So what can be the goal ?   Generally I see there are 2 types of goals seen in practice.  One is <strong>capacity goal</strong>  this is when the system is generally overloaded so everything is slow, when you're just looking to see how you can get most out of your existing system,  looking for consolidation or saving on infrastructure cost.      If this is the goal you can perform general system performance evaluation and just fix the stuff which causes the most load on the system.   MySQL Log analyzes with <a href="http://www.maatkit.org/doc/mk-log-parser.html">Mk-Log-Parser</a> is a very good start for a ways to generally optimize MySQL load on the system.</p>
<p><strong>Latency Goal</strong> is another breed.  The system may not look loaded but some pages still may want to be loading much slower than you like.  These goals are not system wise but they are much more specific to the different user interactions or even types of users.  For example you may define goal also "Search pages have to have response time below 1 second in 95% cases and below 3 seconds in 99% cases".   Note We're specific to the user interaction - people are used to Search taking longer time than other interactions for many applications, and also we speak about percentile response time rather than "all queries".  It is surely good all search queries complete in one seconds but it is too not practical.    The goal description may be more specific too - for example you may have different response time guidelines for pages which are requested for real humans vs search engine bots (which are often quite different in their access pattern) or you may define "large users" as users having more than 100.000 images uploaded and measure the response time for them specifically because this group has its own performance challenges.</p>
<p>Looking at Latency it is also much more practical to look from the top of the stack.  If you look at MySQL log you may find some queries which are slow but it is hard to go back from them to what is really important for the user and so the business - the page response times.  Furthermore. It is not enough in many cases to focus only on Server Side optimization -  the <a href="http://www.percona.com/services/front-end-performance-optimization.html">Client Side Optimization</a> is also quite important in particular for aggressive performance goals and fast back-end. This is why we added this service to Percona offerings. </p>
<p>If Server side or Client Side performance optimization is going to be more important for your application depends on the application performance a lot. The better your application is the more Client Side optimization you will need.   For example if it takes you 30 seconds to generate the search results and 3 more seconds to load all style sheets images and render the page  server side optimization is more important.  If  you have optimized things and now HTML takes 0.5 seconds to generates  an extra 3 seconds become the main response time contributer which has the highest performance optimization potential.  </p>
<p>But let us get back to the Server Side Optimization.  Lets assume our performance goal applies to the HTML generation rather than full page load on the client.   So meet our goal we should look at the pages which do not meet our goal, which is pages which take more than 1 second to generate in given example. </p>
<p>For goal driven performance optimization it is important there is enough instrumentation and production performance logging in place so you really can focus on hard data in your work.  For small and medium size applications you can log all requests to MySQL table for larger ones you can log only small portion of them.   I usually keep one table per day so it is easy to copy the data to a different box for data crunching and remove the old ones. </p>
<p>The log table should contain URL, IP and all the data you need to be able to repeat request if you need to. It may include cookie data, post data, logged in user information etc.  But the real thing is number of times which are stored for request.    <strong>wall clock time</strong> - is the real time it took to generate the page by server backend.     <strong>CPU Time</strong>  This is the CPU time needed to generate request (you can split it to user and system if you want) and when there come various wait times -  mysql, memcache, sphinx, web services etc.</p>
<p>For web applications doing processing in a single thread the following simple formula applies  <em>wall_time=cpu_time+sum(wait_time)+lost_time</em>   The lost time is the time which was lost for some reason - some waits we did not profile or waits we do not have control of, for example when processing had to wait for CPU available to do processing.    For multi-thread application it is a bit more complicated but you still can analyze critical path. </p>
<p>If you have such profiling in place all you have to do is to run the query to see what are contributing factors to the response time of the problematic pages:</p>
<div class="igBar"><span id="lsql-19"><a href="#" onclick="javascript:showPlainTxt('sql-19'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-19">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SELECT</span> count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span>,avg<span style="color:#006600; font-weight:bold;">&#40;</span>wtime<span style="color:#006600; font-weight:bold;">&#41;</span>,avg<span style="color:#006600; font-weight:bold;">&#40;</span>utime/wtime<span style="color:#006600; font-weight:bold;">&#41;</span> cpu_ratio, avg<span style="color:#006600; font-weight:bold;">&#40;</span>mysql_time/wtime<span style="color:#006600; font-weight:bold;">&#41;</span> mysql_ratio ,avg<span style="color:#006600; font-weight:bold;">&#40;</span>sphinx_time/wtime<span style="color:#006600; font-weight:bold;">&#41;</span> sphinx_ratio, avg<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#40;</span>wtime-mysql_time-sphinx_time-utime<span style="color:#006600; font-weight:bold;">&#41;</span>/wtime<span style="color:#006600; font-weight:bold;">&#41;</span> lost_ratio <span style="color: #993333; font-weight: bold;">FROM</span> performance_log_081221 <span style="color: #993333; font-weight: bold;">WHERE</span> page_type=<span style="color: #ff0000;">'search'</span> <span style="color: #993333; font-weight: bold;">AND</span> wtime&gt;<span style="color: #cc66cc;color:#800000;">1</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------+-----------------+------------------+------------------+------------------+------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span> | avg<span style="color:#006600; font-weight:bold;">&#40;</span>wtime<span style="color:#006600; font-weight:bold;">&#41;</span> | cpu_ratio | mysql_ratio | sphinx_ratio | lost_ratio |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------+-----------------+------------------+------------------+------------------+------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">112376</span> | <span style="color: #cc66cc;color:#800000;">6</span>.<span style="color: #cc66cc;color:#800000;">0645327150223</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">11126040714778</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">17609498370795</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">54612972549309</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">16651488365119</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">----------+-----------------+------------------+------------------+------------------+------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">29</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Why looking only at such pages is important ?  This is because if you look at all pages rather than problematic subset it may lead you away from your goal. For example it is very possible among all pages  we would see CPU usage as the main factor because sphinx and MySQL respond from cache. </p>
<p>We however see for pages which have the problem it is Sphinx which accounts for most of the time. </p>
<p>Looking at the data such way we have two great benefits.  First we really understand what is the bottleneck. Second we know what performance gain potential is. For example in this case we could spend a lot of time optimizing PHP code but because it takes only 10% of response time in average even  speeding it up 10 times we would not get more than 10% response time reduction.    At the same time if we find a way to speed up Sphinx we can reduce response time to its half.  </p>
<p>Note in this case there is some 16% of response time which is not accounted for.  Large portion probably comes from memcache accesses which are not instrumented for this application.   In this case this portion is not the biggest part yet but if we'd speed up Sphinx and MySQL dramatically we would have to go and look into better instrumentation so we can look inside this black box.</p>
<p>Once we know it is Sphinx which causes the problem we have to go and find what queries exactly are causing it - this can be done by adding request ID as comment to Sphinx log so you can profile it carefully or you can add tracing functionality to the application.  All the same.  Once you found the queries causing the problem you see the ones which cause the most impact and focus on optimizing them. </p>
<p>There are multiple ways to optimize something, my checklist is usually  <strong>get rid of it</strong>, <strong>cache it</strong>, <strong>tune it</strong>, <strong>get more hardware</strong> in this order.  It is often it is possible to get rid of some queries, cache them, tune them so they are faster (often at the same time changing semantics a bit)  and if nothing helps or can be done quickly we can buy more hardware, assuming application can use it. </p>
<p>Once you've performed optimizations you can repeat analyzes again to see if performance goals are met and where is the bottleneck this time. </p>
<p>As a side note I should mention looking at performance statistics for the day overall is often not enough. Application performs as good as it performs during its worst times so it is very good to plot some graph over time.  Sometimes an hour base may be enough but for large scale application I'd recommend to looking down to 5 minutes or even 1 minute intervals and making sure there are no hiccups.</p>
<p>Check the stats from the application above for example:</p>
<div class="igBar"><span id="lsql-20"><a href="#" onclick="javascript:showPlainTxt('sql-20'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-20">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SELECT</span> date_format<span style="color:#006600; font-weight:bold;">&#40;</span>logged,<span style="color: #ff0000;">'%H'</span><span style="color:#006600; font-weight:bold;">&#41;</span> h,count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span>,avg<span style="color:#006600; font-weight:bold;">&#40;</span>wtime<span style="color:#006600; font-weight:bold;">&#41;</span>,avg<span style="color:#006600; font-weight:bold;">&#40;</span>sphinx_time/wtime<span style="color:#006600; font-weight:bold;">&#41;</span> sphinx_ratio&nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> performance_log_081221 <span style="color: #993333; font-weight: bold;">WHERE</span> page_type=<span style="color: #ff0000;">'search'</span> <span style="color: #993333; font-weight: bold;">AND</span> wtime&gt;<span style="color: #cc66cc;color:#800000;">1</span> <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> h;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">------+----------+-----------------+------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| h&nbsp; &nbsp; | count<span style="color:#006600; font-weight:bold;">&#40;</span>*<span style="color:#006600; font-weight:bold;">&#41;</span> | avg<span style="color:#006600; font-weight:bold;">&#40;</span>wtime<span style="color:#006600; font-weight:bold;">&#41;</span>&nbsp; &nbsp; &nbsp; | sphinx_ratio&nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">------+----------+-----------------+------------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">00</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">5851</span> | <span style="color: #cc66cc;color:#800000;">3</span>.<span style="color: #cc66cc;color:#800000;">0608555987602</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">49142908242509</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">01</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">6639</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">9099249532198</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">48133478800683</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">02</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">5406</span> | <span style="color: #cc66cc;color:#800000;">3</span>.<span style="color: #cc66cc;color:#800000;">3770073273647</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">49140835595675</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">03</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">5397</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">9834221059666</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">53178056214228</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">04</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">4820</span> | <span style="color: #cc66cc;color:#800000;">3</span>.<span style="color: #cc66cc;color:#800000;">8182240369409</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">53530183347988</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">05</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">3720</span> | <span style="color: #cc66cc;color:#800000;">13</span>.<span style="color: #cc66cc;color:#800000;">025273085185</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">61126549080115</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">06</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">1606</span> | <span style="color: #cc66cc;color:#800000;">60</span>.<span style="color: #cc66cc;color:#800000;">624889697559</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">89123114911947</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">07</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">2699</span> | <span style="color: #cc66cc;color:#800000;">38</span>.<span style="color: #cc66cc;color:#800000;">821067012253</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">90885394709571</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">08</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">2419</span> | <span style="color: #cc66cc;color:#800000;">45</span>.<span style="color: #cc66cc;color:#800000;">388828675971</span> |&nbsp; <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">9226436892381</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">09</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">4810</span> |&nbsp; <span style="color: #cc66cc;color:#800000;">6</span>.<span style="color: #cc66cc;color:#800000;">330725168364</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">60329631087965</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">10</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">5445</span> | <span style="color: #cc66cc;color:#800000;">3</span>.<span style="color: #cc66cc;color:#800000;">8355732669953</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">53918653169648</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">11</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">5283</span> | <span style="color: #cc66cc;color:#800000;">3</span>.<span style="color: #cc66cc;color:#800000;">0498331333457</span> |&nbsp; <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">5512679788082</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">12</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">4147</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">9050685487542</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">52802563348716</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">13</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">2313</span> | <span style="color: #cc66cc;color:#800000;">3</span>.<span style="color: #cc66cc;color:#800000;">1297905412629</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">47887915792732</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">14</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">4155</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">9788750504185</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">53700871350403</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">15</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">4081</span> | <span style="color: #cc66cc;color:#800000;">4</span>.<span style="color: #cc66cc;color:#800000;">4940078389087</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">67605124513469</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">16</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">3720</span> | <span style="color: #cc66cc;color:#800000;">3</span>.<span style="color: #cc66cc;color:#800000;">1698921914062</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">54566719123393</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">17</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">4210</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">7616731525034</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">47537024159769</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">18</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">6735</span> |&nbsp; <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">639767089152</span> |&nbsp; <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">5204920072653</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">19</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">5581</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">6058266677645</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">42959908812738</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">20</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">4990</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">4441354725308</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">44270882435635</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">21</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">6305</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">6316682707403</span> |&nbsp; <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">5236776389174</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">22</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">6774</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">4394227009732</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">53342757714496</span> |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">23</span>&nbsp; &nbsp;|&nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;color:#800000;">5270</span> | <span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">3949674527604</span> | <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">51381316608346</span> |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">------+----------+-----------------+------------------+</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">24</span> rows <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">2</span>.<span style="color: #cc66cc;color:#800000;">37</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>As you can see in this case during certain hours the average type of bad queries skyrockets and it becomes 90% or so driven by Sphinx.    This tells us there is some irregular activity (cron jobs?) is happening and it affects Sphinx layer significantly. </p>
<p>Such goal based  from top to bottom approach is especially helpful for complex applications using mutliple components (like sphinx and MySQL) or multiple MySQL Servers because in these cases you often can't easily guess the component which needs attention.  Though even for less complicated single MySQL server application there is often the question if it is MySQL server causing the problem or if application code needs to be optimized.</p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by peter |
      <a href="http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/#comments">No comment</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/&amp;title=Goal driven performance optimization" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/&amp;title=Goal driven performance optimization" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/&amp;title=Goal driven performance optimization" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/&amp;T=Goal driven performance optimization" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/&amp;title=Goal driven performance optimization" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2008/12/22/goal-driven-performance-optimization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How Percona does a MySQL Performance Audit</title>
		<link>http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/</link>
		<comments>http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/#comments</comments>
		<pubDate>Tue, 25 Nov 2008 04:42:01 +0000</pubDate>
		<dc:creator>Baron Schwartz</dc:creator>
				<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=542</guid>
		<description><![CDATA[Our customers or prospective customers often ask us how we do a performance audit (it's our most popular service).  I thought I should write a blog post that will both answer their question, so I can just reply "read all about it at this URL" and share our methodology with readers a little bit. [...]]]></description>
			<content:encoded><![CDATA[<p>Our customers or prospective customers often ask us how we do a <a href="http://www.percona.com/services/mysql-performance-audit.html">performance audit</a> (it's our most popular service).  I thought I should write a blog post that will both answer their question, so I can just reply "read all about it at this URL" and share our methodology with readers a little bit.  This fits well with our philosophy of openness.  It also shocks people sometimes -- "you're giving away the golden goose!"  Not really.  What you hire us for is our experience, not a recipe that anyone can follow.</p>
<p>A full performance audit is far more extensive than this article can cover, and might wander into Apache, networking config, caching layers, etc.  Wherever the problem is, we'll track it down.  I won't talk about that.  That's not because I want to keep secrets from you.  To the contrary, I'd love to share it all with you.  But that's a huge job; it will take many pages, and I'm not going to write that much.</p>
<p><strong>The kickoff call</strong></p>
<p>There's actually a step before the performance audit begins.  We call this a kickoff call.  We get on the phone with the key technical staff on the client's side and discuss the application in general.  If possible, we take a brief look at the server beforehand, so we can ask more intelligent questions and skip obvious things.  This call is sometimes up to an hour long, if we're discussing a lot of things like how to build for massive scalability, how to do read-write splitting without breaking the user experience, how to take online non-blocking backups, or things like that.</p>
<p>But in general it can be a lot shorter than clients expect, because</p>
<ul>
<li>time is money</li>
<li>your application is not as unique as you think, and we already know a lot about it by browsing your site or hearing you say "we are a SaaS hosted application for data mining stock market transactions," or whatever the case may be</li>
<li>we've generally seen just about everything people throw at databases</li>
</ul>
<p>Many people assume their application is difficult or somehow different, and that we need all kinds of schema diagrams and code listings, but the truth is people often have the same insights into particular problems, and therefore they try similar solutions.  And besides, most applications have a lot of the same components.  Tagging, friends, queues, click tracking, search, <a href="http://www.mysqlperformanceblog.com/2008/09/24/four-ways-to-optimize-paginated-displays/">paginated displays</a> -- we've seen these and dozens of other common patterns done a hundred different ways.</p>
<p>The kickoff call has some other important goals too.  We want to know what your concerns are at this stage.  Is it the current performance, future performance, scalability, ability to recover from disasters?  We also want to know what the operating parameters are.  Can we suggest upgrades, rewriting queries, or whatnot?  Sometimes there are rigid constraints on what types of solutions we can propose, and we need to know ahead of time so we don't spend time on things you have no way to change.  An example of this is a third-party product whose code you are unwilling or unable to change.</p>
<p>We also want to know the operating mode you expect us to work in.  Maybe you want us to analyze and present recommendations for your consideration, and take a look-don't-touch approach.  Or, maybe you just want us to fix things and tell you later what we did.  Either is a completely valid approach.  You tell us what you want, and that's what we'll do (of course, we will also tell you what we think is best for you, which is our job).</p>
<p>After the kickoff call, we write some notes, and then get down to the audit itself.  We usually have two people on the kickoff call so that we don't have a single person knowing everything about you (only one is billable, though).  The second person will be from the same team within Percona. However, the audit itself is generally a single person, with another person reading all the notes and generally keeping in touch with what the lead consultant does.  We want two sets of eyes on things whenever possible.  This also has value in case you decide to continue on to a longer relationship with Percona, which is reasonably common; in that case you will establish a solid relationship with the team, and group involvement early on is a good start to this.</p>
<p><strong>What to look for during the audit</strong></p>
<p>During the audit I look for outliers and anomalies in every aspect of the server's configuration and performance and contents.  I'm looking for characteristics that are much bigger or smaller than normal, or things I don't usually see.  Anything out of the ordinary or out of proportion.  These things are often relatively easy to catch if you have enough experience.  It's  a little hard to describe without making it sound like it's some secret handshake, but it's really not magical.  You're either familiar with what a server normally looks like, or you're not.  It's just like a mechanic who listens to the car and says "I hear the valves knocking."</p>
<p>In other cases there may be things that are NOT easy to catch, and may require a lot of experience and investigation.  The work we do is often not simple at all.  It's impossible to predict.  A customer may call and ask "how long to debug server lockups?"  It could be ten minutes, or it could be a really major effort chasing down something like a bug in a hardware component, and you never know ahead of time.</p>
<p>In either case, the point to know here is that we can work with systems that are at any level of tuning, from completely untuned to a system that's already had a lot of expert attention.  I use "tuning" in a generic way here -- we focus on far more than my.cnf files.  In fact my.cnf files are usually one of the smallest levers we can pull for server optimization.  Schema and query optimization can give much greater improvements, for example.</p>
<p>If you're familiar with <a href="http://www.amazon.com/Blink-Power-Thinking-Without/dp/0316172324?tag=perinc-20">Malcolm Gladwell's excellent book Blink</a>, you know the term "thin-slicing."  That describes an experienced consultant's approach to the problem very well.</p>
<p><strong>The audit itself</strong></p>
<p>OK, so here's a very basic audit, whose scope I'll keep within just a MySQL server.  The first step is to log into the machine via SSH and open up a text editor (gedit, notepad, what have you.)  I want to keep this open and paste everything I see into it.  If there's no record later that someone else can follow, I am not doing my job.</p>
<p>I would also note that the commands I'll show here are the lowest common denominator.  We often use tools to gather a lot of the data for us and speed the process, when possible, but the core commands I'll show are what we can always fall back to if that's not possible.</p>
<p><strong>Gathering information about the server</strong></p>
<p>I start off with these commands:</p>
<ul>
<li>date</li>
<li>uname -a</li>
<li>cat /etc/*release</li>
</ul>
<p>The first command is invaluable for later reference.  The others will show exactly what kind of server I'm looking at, assuming I'm on a GNU/Linux box (I have to adapt to whatever environment I'm in -- obviously a FreeBSD box is different).  For example,</p>
<div class="igBar"><span id="lcode-30"><a href="#" onclick="javascript:showPlainTxt('code-30'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-30">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#91;</span>percona@db1 ~<span style="color:#006600; font-weight:bold;">&#93;</span>$ uname -a</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Linux hostname.<span style="">domain</span> <span style="color:#800000;color:#800000;">2</span>.<span style="color:#800000;color:#800000;">6</span>.<span style="color:#800000;color:#800000;">18</span>-<span style="color:#800000;color:#800000;">92</span>.<span style="">el5</span> #1 SMP Tue Apr <span style="color:#800000;color:#800000;">29</span> <span style="color:#800000;color:#800000;">13</span>:<span style="color:#800000;color:#800000;">16</span>:<span style="color:#800000;color:#800000;">15</span> EDT <span style="color:#800000;color:#800000;">2008</span> x86_64 x86_64 x86_64 GNU/Linux</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#91;</span>percona@db1 ~<span style="color:#006600; font-weight:bold;">&#93;</span>$ cat /etc<span style="color:#008000;">/*release</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000;">Red Hat Enterprise Linux Server release 5.2 (Tikanga) </span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>From this, I can see a couple of important things.  One thing is that I'm looking at a 64-bit OS, which is important to know.  I also know I'm on RHEL and I know the kernel -- knowing this may tell us a lot of useful things about the system.</p>
<p>Next I continue looking around the server.  Holding with the assumption of GNU/Linux, I keep working to get a picture of the OS and hardware.</p>
<div class="igBar"><span id="lcode-31"><a href="#" onclick="javascript:showPlainTxt('code-31'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-31">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#91;</span>percona@db1 ~<span style="color:#006600; font-weight:bold;">&#93;</span>$ tail -n <span style="color:#800000;color:#800000;">25</span> /proc/cpuinfo</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">power management:</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">processor&nbsp; &nbsp; &nbsp; &nbsp;: <span style="color:#800000;color:#800000;">7</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">vendor_id&nbsp; &nbsp; &nbsp; &nbsp;: GenuineIntel</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">cpu family&nbsp; &nbsp; &nbsp; : <span style="color:#800000;color:#800000;">6</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">model&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: <span style="color:#800000;color:#800000;">15</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">model name&nbsp; &nbsp; &nbsp; : Intel<span style="color:#006600; font-weight:bold;">&#40;</span>R<span style="color:#006600; font-weight:bold;">&#41;</span> Xeon<span style="color:#006600; font-weight:bold;">&#40;</span>R<span style="color:#006600; font-weight:bold;">&#41;</span> CPU&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;L5335&nbsp; @ <span style="color:#800000;color:#800000;">2</span>.00GHz</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">stepping&nbsp; &nbsp; &nbsp; &nbsp; : <span style="color:#800000;color:#800000;">11</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">cpu MHz&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: <span style="color:#800000;color:#800000;">1995</span>.<span style="color:#800000;color:#800000;">022</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">cache size&nbsp; &nbsp; &nbsp; : <span style="color:#800000;color:#800000;">4096</span> KB</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">physical id&nbsp; &nbsp; &nbsp;: <span style="color:#800000;color:#800000;">1</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">siblings&nbsp; &nbsp; &nbsp; &nbsp; : <span style="color:#800000;color:#800000;">4</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">core id&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: <span style="color:#800000;color:#800000;">3</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">cpu cores&nbsp; &nbsp; &nbsp; &nbsp;: <span style="color:#800000;color:#800000;">4</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">fpu&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: yes</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">fpu_exception&nbsp; &nbsp;: yes</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">cpuid level&nbsp; &nbsp; &nbsp;: <span style="color:#800000;color:#800000;">10</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">wp&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : yes</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">flags&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx lm constant_tsc pni monitor ds_cpl vmx tm2 cx16 xtpr lahf_lm</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">bogomips&nbsp; &nbsp; &nbsp; &nbsp; : <span style="color:#800000;color:#800000;">3990</span>.<span style="color:#800000;color:#800000;">03</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">clflush size&nbsp; &nbsp; : <span style="color:#800000;color:#800000;">64</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">cache_alignment : <span style="color:#800000;color:#800000;">64</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">address sizes&nbsp; &nbsp;: <span style="color:#800000;color:#800000;">38</span> bits physical, <span style="color:#800000;color:#800000;">48</span> bits virtual</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">power management: </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>What I see here is that this is an 8-core machine, two quad-core processors at 2GHz.  I also know some things about the CPU, such as the model number and the cache size, etc.  What else is important is the 'lm' flag, which tells me this is a 64-bit CPU.  From this and what I saw earlier I can see whether someone <a href="http://www.mysqlperformanceblog.com/2008/07/25/the-1-mistake-hosting-providers-make-for-mysql-servers/">installed a 32-bit OS on 64-bit hardware</a>, which is important if you want to allocate a lot of memory to mysqld.</p>
<p>Next I look at a couple of all-in-one commands.  For example, 'top -n 1' and 'uptime'.  That shows me what processes are running, but it also shows me load average, memory sizes, and a bunch of other stuff.  In this case I'm on a machine with 32GB of memory and there is very little load.  I see that mysqld is using 10g of memory with 17g virtual size, and there's practically nothing else running (this is a dedicated master server).  The machine has a lot of swap, but basically none is used.  This isn't all that relevant, as you'll see later, but in some cases it might be.</p>
<p>I continue my investigation into the machine itself with these commands:</p>
<ul>
<li>mount</li>
<li>df -h</li>
<li>dmesg</li>
<li>pvs; vgs; lvs</li>
</ul>
<p>These commands show me what filesystems are mounted, how much space they have on them, and what kind of I/O system is under the box in general.  dmesg is useful for several reasons.  For one thing, it has a lot of information on the box's hardware, including RAID controllers, installed memory, and so on in the boot output. In addition, at the tail it has information on core dumps and so on.  It's possible that it has filled up with stuff and the boot output has been lost, but in many cases there is a lot of information here that's hard to get elsewhere.</p>
<p>If I see an LSI MegaRAID card, which is pretty common, I can check whether MegaCli is installed, and use it to get information about the physical drives installed; then I can find out exactly what they are, both in terms of size and spindle speed.  I need to know how many physical spindles are under the box, and how fast they are.  I can also get information about the all-important battery-backed write cache, how it's configured and what its status is.  I can see the drive status, too.  Sometimes a failed drive is present but no one has noticed it yet!  (By the way, we can also help you install and configure monitoring and graphing systems, if you don't have any.  These will help catch such problems.)  If MegaCLI isn't installed there may be other ways to get this information, too.</p>
<p>The last three commands are for giving me information about LVM devices, volume groups, and logical volumes.  At this point, unless I've seen something that I want to investigate further, I have a pretty good idea what hardware and operating system I'm working with.</p>
<p><strong>System performance</strong></p>
<p>Next I investigate what the system is doing, in terms of performance.  There are two key commands for this on most operating systems (there are others, such as mpstat or dstat, that I may also elect to use in some cases):</p>
<ul>
<li>vmstat 5 5</li>
<li>iostat -dx 5 5</li>
</ul>
<p>If you don't know how to read these, there's a full explanation in <a href="http://www.amazon.com/gp/product/0596101716?tag=perinc-20">our book, High Performance MySQL 2nd Edition</a> (it's not in the first edition).  From this I get an idea where any possible problems might be: is the disk saturated?  Is the machine swapping actively?  (This is more important than whether it's using swap.)  There are a lot of combinations of possible things you can see here, so I will not try to explain it all.  Basically you need to know everything there is to know about these two commands and their output.</p>
<p>Based on what I've seen so far, I may look at other things, such as ifconfig (which shows good stuff like dropped packets).</p>
<p><strong>Starting to look at MySQL</strong></p>
<p>Assuming I don't see anything noteworthy here, I'll move on to the MySQL server.  I mean, let's just assume the physical hardware and the machine setup is fine, and the client has asked me to figure out why the website is slow; assume also I've checked out Apache and network config, etc, and I don't see anything wrong there.  So at this point, it looks like MySQL is probably a good place to look for performance problems.  Everything I've done up till now is just due diligence; I've gotten my bearings on the server as a whole, and now I'm ready to see what's up with the database.</p>
<p>The first step is to find out what MySQL instances are on the machine.  It doesn't do to just assume there's a single instance in /var/lib/mysql and it's reading from /etc/my.cnf.  I've seen a lot of cases where there's a /var/lib/mysql and an /etc/my.cnf, and the server is installed in /customsoftware/mysql with a different my.cnf file.  The way to find this out is to look at ps:</p>
<div class="igBar"><span id="lcode-32"><a href="#" onclick="javascript:showPlainTxt('code-32'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-32">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#91;</span>percona@db1 ~<span style="color:#006600; font-weight:bold;">&#93;</span>$ ps -eaf | grep mysqld</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">root&nbsp; &nbsp; &nbsp; <span style="color:#800000;color:#800000;">3137</span>&nbsp; &nbsp; &nbsp;<span style="color:#800000;color:#800000;">1</span>&nbsp; <span style="color:#800000;color:#800000;">0</span> Nov19 ?&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#800000;color:#800000;">00</span>:<span style="color:#800000;color:#800000;">00</span>:<span style="color:#800000;color:#800000;">00</span> /bin/sh /usr/bin/mysqld_safe --defaults-file=/etc/my.<span style="">cnf</span> --pid-file=/var/run/mysqld/mysqld.<span style="">pid</span> --log-error=/var/log/mysqld.<span style="">log</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&nbsp; &nbsp; &nbsp;<span style="color:#800000;color:#800000;">3172</span>&nbsp; <span style="color:#800000;color:#800000;">3137</span> <span style="color:#800000;color:#800000;">78</span> Nov19 ?&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#800000;color:#800000;">1</span>-<span style="color:#800000;color:#800000;">11</span>:<span style="color:#800000;color:#800000;">17</span>:<span style="color:#800000;color:#800000;">30</span> /usr/libexec/mysqld --defaults-file=/etc/my.<span style="">cnf</span> --basedir=/usr --datadir=/var/db/mysql --user=mysql --pid-file=/var/run/mysqld/mysqld.<span style="">pid</span> --skip-external-locking --port=<span style="color:#800000;color:#800000;">3306</span> --socket=/var/db/mysql/mysql.<span style="">sock</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">consult&nbsp; <span style="color:#800000;color:#800000;">28852</span> <span style="color:#800000;color:#800000;">26909</span>&nbsp; <span style="color:#800000;color:#800000;">0</span> <span style="color:#800000;color:#800000;">19</span>:<span style="color:#800000;color:#800000;">08</span> pts/<span style="color:#800000;color:#800000;">2</span>&nbsp; &nbsp; <span style="color:#800000;color:#800000;">00</span>:<span style="color:#800000;color:#800000;">00</span>:<span style="color:#800000;color:#800000;">00</span> grep mysqld </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>In this case, yes it's all default.  It's listening on the usual port, etc etc.  Nothing unusual.  Next I check what the MySQL version is, and I check (with the 'file' command) whether /usr/libexec/mysqld is a 64-bit build, if I'm on a 64-bit OS.</p>
<p><strong>Examining MySQL configuration</strong></p>
<p>Then I'll look at my.cnf quickly for anything weird:</p>
<div class="igBar"><span id="lcode-33"><a href="#" onclick="javascript:showPlainTxt('code-33'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-33">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#91;</span>percona@db1 ~<span style="color:#006600; font-weight:bold;">&#93;</span>$ grep -v <span style="color:#CC0000;">'^#'</span> /etc/my.<span style="">cnf</span> | grep . </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>My goal here is to look at the my.cnf without seeing all the comments, which a) are often a small novel, b) often say what the sysadmin thinks s/he's doing, which might not be what is really being done.  I want to look at it without polluting my brain with that.  I'll just scan this for anything odd.  In contrast to what you might think, spending a lot of time here isn't usually a good idea, because what's left out is often more important than what's included.  For example, <a href="http://www.mysqlperformanceblog.com/2008/05/31/dns-achilles-heel-mysql-installation/">the absence of skip-name-resolve is easy to miss</a>, as is the absence of <a href="http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/">innodb_log_file_size</a>.</p>
<p>I won't give you a full rundown over every option in the file.  But again, you learn quickly if something strange is here.</p>
<p>This whole time I've been copying the output of the commands and saving them in a text file.  I'll attach this text file to the issue in our CRM system so I (or someone else) can look at it later, see what I saw, and follow my line of reasoning about any suggestions I make.</p>
<p>The next thing to do is grab 'mysqladmin variables' and put it in the text file.  I don't spend a lot of time looking at this.  For one thing, all the values are in big units, so it's hard to read.  If the InnoDB buffer pool is set to 22GB, it's much easier to see 22GB than 23622320128, especially since that number is buried next to a lot of other long numbers.  They make my eyes hurt, and there are better ways to do this (I will run <a href="http://hackmysql.com/scripts/mysqlreport">mysqlreport</a> to get friendly numbers I can read easily).  But what I will do is scan the output for something strange that might be caused by a syntax error in the my.cnf file.  For an example, <a href="http://bugs.mysql.com/bug.php?id=39868">take a look at this bug report</a> (not a bug).</p>
<p><strong>Looking at MySQL status</strong></p>
<p>Now we're starting to get into the really interesting bits.  Alas, these are the bits where there is the most variability, so I'll have to be even less detailed and a little vague.  The next command is this:</p>
<div class="igBar"><span id="lcode-34"><a href="#" onclick="javascript:showPlainTxt('code-34'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-34">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysqladmin ext -ri10 </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>I let that run for at least two iterations.  The first iteration is the current values since the server was booted; the second and subsequent are incremental differences.  I'll usually capture two of these.  It looks like this:</p>
<div class="igBar"><span id="lcode-35"><a href="#" onclick="javascript:showPlainTxt('code-35'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-35">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#91;</span>percona@db1 ~<span style="color:#006600; font-weight:bold;">&#93;</span>$ mysqladmin ext -ri10</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+-----------------------------------+----------------------+</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Variable_name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| Value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+-----------------------------------+----------------------+</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Aborted_clients&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">205174</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Aborted_connects&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">29</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Binlog_cache_disk_use&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">0</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Binlog_cache_use&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">9630066</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Bytes_received&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">38563413074</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Bytes_sent&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">216162991863</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Com_admin_commands&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">255868807</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">... <span style="">snip</span> ...</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Uptime&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">162626</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Uptime_since_flush_status&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">162626</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+-----------------------------------+----------------------+</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+-----------------------------------+----------------------+</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Variable_name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| Value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+-----------------------------------+----------------------+</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Aborted_clients&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">6</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Aborted_connects&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">0</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Binlog_cache_disk_use&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">0</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Binlog_cache_use&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">468</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Bytes_received&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">1708212</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Bytes_sent&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">7796961</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Com_admin_commands&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">11893</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">... <span style="">snip</span> ... </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Then I format the second set of values up beside the first set for ease of reference (an easy task with an automated too, or a quick Vim command if I'm doing this the manual way.)  The result looks like this:</p>
<div class="igBar"><span id="lcode-36"><a href="#" onclick="javascript:showPlainTxt('code-36'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-36">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+-----------------------------------+----------------------+----------------------+</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Variable_name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| Value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+-----------------------------------+----------------------+----------------------+</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Aborted_clients&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">205174</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">6</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Aborted_connects&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">29</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">0</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Binlog_cache_disk_use&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">0</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">0</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Binlog_cache_use&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">9630066</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">468</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Bytes_received&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">38563413074</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">1708212</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Bytes_sent&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">216162991863</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| <span style="color:#800000;color:#800000;">7796961</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Com_admin_commands&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">255868807</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">11893</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Com_alter_db&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">0</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">0</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">...<span style="">snip</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>This output is very useful when writing the report to the client.  Now I go through it line by line looking for things that look wrong.  When I find something, I compare it against the server's variables or whatever other data I need, and write something instructional to the client about it.</p>
<p><strong>Preparing to report findings</strong></p>
<p>I should mention here a bit about how I write the report to the client.  I copy and paste the interesting snippets from what I've been gathering, save it in a text file, and explain what I'm seeing to the client.  Anything I see that looks wrong should be explained in detail, because my goal is to teach the client, not just to awe them with my knowledge and get "I could never understand, O Almighty Percona, here's your money" in reply.  If the client doesn't understand what I'm doing, I've done something wrong.  Clients need to understand so that they know they're getting good service.  A Percona consultant never says "just trust me" unless the client really insists "I don't want to know."</p>
<p>That's also why I'll comment on <em>things that seem good</em>.  Clients need to know that I'm being thorough.  Once upon a time, a Percona consultant was called back in to do some further work about 6 months after Peter helped a client.  Now, if Peter worked with the client 6 months ago, you have big shoes to fill, and getting further gains will probably <em>not</em> be easy.  So this consultant looked through things, spent about 2 hours, and came back to the client with "there's not a lot of performance left to gain here.  You can do X, Y and Z, and that's about all I see.  Beyond that, we need to talk about making your overall architecture more scalable." And the client said "that's all?  Didn't you do any work?  Peter's report 6 months ago was a small encyclopedia!"  The mistake here was that the consultant didn't show all the things he'd checked, which was extensive indeed.  After a quick explanation the customer understood that the consultant had really done a lot of work, but it's better to show the client the full extent of the investigations in the first place, and not just show "here's the 3 bad things I found in 2 hours."  We also make sure that we refer back to the previous issue's findings, so that we don't duplicate efforts from the earlier optimization.</p>
<p>Back to the output of mysqladmin.  When I send the report to the client, it typically looks something like this.  First, I explain the meaning of the output, so it's clear what I'm showing them.  Then, I go through it line by line, like this:</p>
<blockquote><pre>
+-----------------------------------+----------------------+----------------------+
| Variable_name                     | Value                | Value                |
+-----------------------------------+----------------------+----------------------+
| Aborted_clients                   | 205174               | 6                    |

Here we can see that something is disconnecting ungracefully
(without closing the connection properly).  This is happening 6
times every ten seconds.  We need to figure out what is happening
because it can indicate something else is wrong.  This is not a
big deal for performance, it's just something to figure out.

... snip ...

| Com_admin_commands                | 255868807            | 11893                |

Why is something running an admin command constantly?  This
is generally a Ping command, which is useless.  Something is
pinging the server about 1200 times per second.  Often this is
from some ORM system, such as Class::DBI, which does $dbh->ping
before each and every query.

Why is Ping useless?  Well, it is intended to tell you whether the
server is alive.  The trouble is, if it succeeds, it tells you nothing.
An instant later, when the ORM system actually runs the query,
the server could have died.  The ORM should just be running the
query, and if the query fails, then you know from the error code
that the server is dead.  So a successful Ping is meaningless.

On the other hand, pinging can be a serious performance problem.
Not really for the server, since it's a cheap query.  It adds hardly
any load.  But for the application, it's another network round trip.
It is a "garbage" query that just adds latency and makes the overall
time to complete an action longer.  If your application runs very short
queries, this can be a non-trivial part of the app's response time.
</pre>
</blockquote>
<p>And so on, and so on.  I'll often refer to other things; for example, when I'm examining the status values for Created_tmp_tables and Created_disk_tmp_tables, I'll paste in</p>
<div class="igBar"><span id="lcode-37"><a href="#" onclick="javascript:showPlainTxt('code-37'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-37">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; show global variables like <span style="color:#CC0000;">'%table_size%'</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+---------------------+-----------+</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| Variable_name&nbsp; &nbsp; &nbsp; &nbsp;| Value&nbsp; &nbsp; &nbsp;|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+---------------------+-----------+</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| max_heap_table_size | <span style="color:#800000;color:#800000;">268435456</span> | </div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| tmp_table_size&nbsp; &nbsp; &nbsp; | <span style="color:#800000;color:#800000;">268435456</span> | </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+---------------------+-----------+ </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>If these are not the same size, as often happens, I'll explain that the minimum of the two is used to determine when an in-memory temporary table will be converted to an on-disk table, which is an expensive operation.</p>
<p>In this way, I work through the status and the variables, and explain to the client what I can deduce about the server from them.</p>
<p>I would point out that I don't spend a lot of time on settings and status.  It is not where the greatest gains are to be found.  The real gold mine is yet to come.  After you've done it a few times, you can go through the settings and status pretty quickly.</p>
<p><strong>Analyzing MySQL's workload and data</strong></p>
<p>After I'm done with that, I'll grab a few snapshots of SHOW FULL PROCESSLIST, and look for odd values in this.  For example, if I see a lot of queries in odd statuses, like "statistics", I know something weird is going on, and I look deeper.  I also look at the queries themselves.  If the client has long-running queries, it can be pretty easy to catch.  Maybe they're long-running because they're in Locked status, which might be an indication that it's time to convert MyISAM tables to InnoDB.  (But then again, it might not be.)  Or maybe the client is doing queries like "... WHERE client IN (SELECT id FROM clients)" which is a really bad query plan.</p>
<p>After this I'll look at SHOW INNODB STATUS\G and see if there's anything worth commenting on there.  Depending on the workload, there might be a lot of substance here.  There's also a very thorough section on this in our book.</p>
<p>Next I look at the data in the server and see what I think about it.  If the server is not heavily loaded, I may even do some <a href="http://www.mysqlperformanceblog.com/2008/03/17/researching-your-mysql-table-sizes/">INFORMATION_SCHEMA queries to help me find the biggest tables</a> and so forth.  If the server is heavily loaded or has a lot of data, touching the INFORMATION_SCHEMA can take a barely-running site and bring it down, so I do this with great care! If it's not appropriate I may run 'du' on the data files, or simply skip this step.  This information can help me determine what kinds of things I ought to look for later during query analysis, and also might show me things like huge tables that should be archived, tables that I should be aware of if I see them in queries, or what have you.</p>
<p>I will also look at the error log.  The error log shows all sorts of interesting things.  Basically, anything but silence in the error log is interesting and needs to be investigated.  You might find that there are InnoDB tables whose .frm files exist but have been dropped from InnoDB, for example.  (The INFORMATION_SCHEMA query will surely trigger errors about this.)</p>
<p>There are a bunch of other things I'll look at, including checking for default users in the mysql.* tables, running <a href="http://www.maatkit.org/doc/mk-duplicate-key-checker">mk-duplicate-key-checker</a> to find redundant indexes, and so on.  As with settings and status, these set the stage for bigger gains to come later, so I don't spend all that much time here, although there is occasionally something really bad that can be fixed and bring big gains.</p>
<p><strong>Schema, query, and index optimization</strong></p>
<p>Analyzing and optimizing a server's table and index structures, and the queries that run against them, is by far the most important thing to concentrate on.  All the other work is a prerequisite to understanding the context within which these things operate.  For example, if the workload is a star schema data warehouse, it is important to know a lot about the I/O subsystem.  And by now I know that I should concentrate in certain areas -- there may be hundreds of tables, but at this point I should have identified a handful of tables that really matter.  That's why I save this part of the analysis for last.</p>
<p>You cannot consider any one of these factors (schema, queries, indexing) in isolation, because they are tightly bound together, and tweaking one will often have effects on the others.  Each decision is a consideration of the costs and benefits on the system as a whole.</p>
<p>The queries the system runs, and hence the slow query log, is one of the more fruitful ways to analyze the system.  What I usually do is ask the client to enable it a day before the audit if possible, and set it to one second.  That way there's at least one "cycle" of queries in it.  Then I run the following:</p>
<div class="igBar"><span id="lcode-38"><a href="#" onclick="javascript:showPlainTxt('code-38'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-38">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">wget http:<span style="color:#FF9933; font-style:italic;">//hackmysql.com/scripts/mysqlsla</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">perl mysqlsla -lt slow /path/to/slow.<span style="">log</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>By default, this outputs the top 10 most expensive queries, in total execution time.  By the way, the slow query logs in the stock MySQL server are extremely limited, and for serious analysis it's basically mandatory to use a server that has the <a href="http://www.percona.com/percona-lab.html">Percona patches for microsecond logging and additional information in the slow query log output</a>.  The stock MySQL server's limitation of one-second granularity makes it hide problem queries that are faster than one second (which in a high-performance system is virtually every query.)  If it's not possible to use a patched binary, we can use MySQL Proxy, packet sniffing, or other techniques to get more information than the slow log gives us; but by far the richest and most efficient source of analysis information is our custom server, which we have designed exactly for the purpose of giving us as much insight as possible into the server's true workload.  At the moment there is no other technique that approaches the amount of information a Percona build can give you.</p>
<p>Having found the desired information about the queries by any means necessary, I find out which are the most likely to give the greatest gains.  I use a dual approach for this: I look for both the queries which cause the greatest load on the server (in aggregate) and which cause the greatest latency for the application.  Again, it's a process of finding outliers by some criteria.  Both types of queries matter.  Some may be extremely fast, but run very often; others may be run seldom but take a long time to finish.  And it's important to focus on ones that can give the greatest improvement for the customer.  I can often tell at a glance whether a query is going to be possible to improve a lot, and a simple mental calculation can then tell me how much total gain I can get from it.  Queries are not just "bad" or "good" -- it's a question of where they fall on the scale.</p>
<p>Now I analyze these one at a time.  For each query, I run EXPLAIN if possible (rewriting non-SELECT queries if needed, and using careful judgment for queries with subqueries in the FROM clause, which will actually execute the inner subquery!), and examine the query plan.  This is where you need to really know how to write queries and <a href="http://www.percona.com/files//presentations/EXPLAIN_demystified.pdf">how EXPLAIN works</a>.  At Percona, we have peer training constantly on our internal IRC channel and mailing list.  We share all sorts of dirty tricks and neat ideas with each other.  Nothing is off the table.  Queries can be rewritten.  Indexes and data types and table structures can be changed.  Queries can be broken into pieces, combined, or even eliminated entirely (we may suggest caching, or tell the customer to evaluate <a href="http://www.sphinxsearch.com/">Sphinx</a>, or something like that.)</p>
<p>In the common case, though, a query simply needs a rewrite or a new index or something.  In this case we show the query and the information mysqlsla outputs about it (execution times, etc), the EXPLAIN plan, and the desired modifications to the query or the table.  We explain how to interpret what we're showing, and why the proposed modifications are better.  If the client approves it, we may make a copy of the table, make the proposed modifications to it, and show the difference afterwards.  Or we might have a test server to run on.  It varies widely; some clients have a test server, some don't; some have a formal QA process; some don't.  It is very customer-specific, and we work with what we have.</p>
<p><strong>Sending the report to the client</strong></p>
<p>After the slow query log analysis is done, I format all my analysis for sending, add in things I may have noticed along the way (comments on backups, for example) read over it once again and make sure I didn't miss anything important or write something in a confusing way, and then send it to the client.  Then I usually call to discuss, or just confirm that it was received and wait for a reply.  In most cases the client has a lot of work to do -- sometimes weeks of application changes.  Afterwards there's usually more to be gained by doing another pass through.</p>
<p>We may also want to have another call with the customer and talk about changes that can or should be made at a much higher level.  If we see that the application's overall architecture needs to be changed, that's something to discuss.  Customers usually want us to validate their application's overall scalability and whether it'll grow to meet their demands for some period of time.  We also frequently bring the discussion to topics such as monitoring, alerting, backups, caching, reverse proxies, and high availability solutions, all of which we can frequently help customers set up much more efficiently and with better results, due to our knowledge of what works in the real world and where there's quicksand to be avoided.</p>
<p>The changes Percona's performance audits typically suggest can be really significant, and can completely change the performance profile and workload of a server, so it's often worth another iteration, and sometimes even more after that.  A really thorough audit can take up to ten hours!  The initial round usually takes less than two, however.  The ten-hour cases are usually for really complex applications, or apps that have a lot of stored procedures, which are more difficult to analyze because you have to pull out the statements and analyze them individually.  The goal is always to <a href="http://www.mysqlperformanceblog.com/2008/11/08/drilling-down-to-the-source-of-the-problem/">develop X-Ray Vision and see through the symptoms to the underlying causes</a> in every aspect of application performance.</p>
<p><strong>Customer interaction</strong></p>
<p>In all cases, the customer's guidance is our first rule.  The customer determines the depth and complexity of the analysis we do.  A lot of times, customers will tell us up front to limit the work to some number of hours, such as 3 hours.  Knowing this ahead of time gives us a framework within which we have to deliver the maximum value to the customer.  If we have less time, we fix the "sore thumbs" and make notes of places where more effort is likely to pay off, and mention those to the customer.  Or we economize by giving the customer easy choices so they can decide which things to have us fix, which to fix themselves, and which to just ignore.</p>
<p>The above process may look like a static recipe that you can just mechanically execute, and in some cases that's truly what we do.  However, we don't just go through the motions.  The "recipe" above is only a framework within which we work.  Knowing the rules of a performance audit, and why they are the way they are, means you can know when and how to break them for the client's benefit.  It's like knowing openings in chess -- the great chess players study openings exhaustively, but they don't robotically play them in tournaments.</p>
<p>For example, although it may sound as though I go work for a while and then emerge with a report, it's not that way a lot of times.  Flexibility and exercising judgment about when it's appropriate to interact with the customer are a hallmark of our approach.  If we need to be interactive and keep in touch with the client early and often, we do that.  A lot of times I'll start out with a quick look and have a second brief call with the customer, or send a quick email and ask for feedback on the direction I'm going; or just get on an instant messaging chat and tell the customer "here's the top thing you can start working on while I keep investigating."  We make our process as interactive and flexible as the situation calls for.  Early, frequent feedback lets us make small adjustments to the direction we're going, communicate to the client how much time we're spending, and shortcut effort if it's not useful, e.g. skipping analysis for a query the client's developers are in the process of removing from the application completely.</p>
<p>That's all!  I hope this has been an informative and fun trip through the world of a typical Percona performance audit, although as you've seen there really isn't any such thing.  Post your questions in the comments, and I'll try to answer them as time permits.</p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by Baron Schwartz |
      <a href="http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/#comments">14 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/&amp;title=How Percona does a MySQL Performance Audit" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/&amp;title=How Percona does a MySQL Performance Audit" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/&amp;title=How Percona does a MySQL Performance Audit" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/&amp;T=How Percona does a MySQL Performance Audit" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/&amp;title=How Percona does a MySQL Performance Audit" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2008/11/24/how-percona-does-a-mysql-performance-audit/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>How to calculate a good InnoDB log file size</title>
		<link>http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/</link>
		<comments>http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 14:52:41 +0000</pubDate>
		<dc:creator>Baron Schwartz</dc:creator>
				<category><![CDATA[Innodb]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/?p=541</guid>
		<description><![CDATA[Peter wrote a post a while ago about choosing a good InnoDB log file size.  Not to pick on Peter, but the post actually kind of talks about a lot of things and then doesn't tell you how to choose a good log file size!  So I thought I'd clarify it a little.
The basic point [...]]]></description>
			<content:encoded><![CDATA[<p>Peter wrote a post a while ago about <a href="http://www.mysqlperformanceblog.com/2006/07/03/choosing-proper-innodb_log_file_size/">choosing a good InnoDB log file size</a>.  Not to pick on Peter, but the post actually kind of talks about a lot of things and then doesn't tell you how to choose a good log file size!  So I thought I'd clarify it a little.</p>
<p>The basic point is that your log file needs to be big enough to let InnoDB optimize its I/O, but not so big that recovery takes a long time.  That much Peter covered really well.  But how do you choose that size?  I'll show you a rule of thumb that works pretty well.</p>
<p>In most cases, when people give you a formula for choosing a configuration setting, you should look at it with skepticism.  But in this case you can calculate a reasonable value, believe it or not.  Run these queries at your server's peak usage time:</p>
<div class="igBar"><span id="lsql-42"><a href="#" onclick="javascript:showPlainTxt('sql-42'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-42">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; pager grep sequence</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">PAGER <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #993333; font-weight: bold;">TO</span> <span style="color: #ff0000;">'grep sequence'</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SHOW</span> engine innodb <span style="color: #993333; font-weight: bold;">STATUS</span>\G <span style="color: #993333; font-weight: bold;">SELECT</span> sleep<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">60</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color: #993333; font-weight: bold;">SHOW</span> engine innodb <span style="color: #993333; font-weight: bold;">STATUS</span>\G</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Log sequence number <span style="color: #cc66cc;color:#800000;">84</span> <span style="color: #cc66cc;color:#800000;">3836410803</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">06</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">1</span> min <span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">00</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Log sequence number <span style="color: #cc66cc;color:#800000;">84</span> <span style="color: #cc66cc;color:#800000;">3838334638</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #cc66cc;color:#800000;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">0</span>.<span style="color: #cc66cc;color:#800000;">05</span> sec<span style="color:#006600; font-weight:bold;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Notice the log sequence number.  That's the total number of bytes written to the transaction log.  So, now you can see how many MB have been written to the log in one minute.  (The technique I showed here works on all versions of MySQL.  In 5.0 and newer, you can just watch Innodb_os_log_written from SHOW GLOBAL STATUS, too.)</p>
<div class="igBar"><span id="lsql-43"><a href="#" onclick="javascript:showPlainTxt('sql-43'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">SQL:</span>
<div id="sql-43">
<div class="sql">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">mysql&gt; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color: #cc66cc;color:#800000;">3838334638</span> - <span style="color: #cc66cc;color:#800000;">3836410803</span><span style="color:#006600; font-weight:bold;">&#41;</span> / <span style="color: #cc66cc;color:#800000;">1024</span> / <span style="color: #cc66cc;color:#800000;">1024</span> <span style="color: #993333; font-weight: bold;">AS</span> MB_per_min;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| MB_per_min |</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">------------+</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">| <span style="color: #cc66cc;color:#800000;">1</span>.<span style="color: #cc66cc;color:#800000;">83471203</span> | </div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">+<span style="color: #808080; font-style: italic;">------------+ </span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>As a rough rule of thumb, you can make the log big enough that it can hold <em>at most</em> an hour or so of logs.  That's generally plenty of data for InnoDB to work with; an hour's worth is more than enough so that it can reorder the writes to use sequential I/O during the flushing and checkpointing process.  At this rate, this server could use about 110 MB of logs, total.  Round it up to 128 for good measure.  Since there are two log files by default, divide that in half, and now you can set</p>
<div class="igBar"><span id="lcode-44"><a href="#" onclick="javascript:showPlainTxt('code-44'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">CODE:</span>
<div id="code-44">
<div class="code">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">innodb_log_file_size=64M </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Does that look surprisingly small?  It might.  I commonly see log file sizes in the gigabyte ranges.  But that's generally a mistake.  The server I used for the measurements above is a big one doing a lot of work, not a toy.  Log file sizes can't be left at the default 5MB for any real workload, but they often don't need to be as big as you might think, either.</p>
<p>If this rule-of-thumb calculation ends up showing you that your log file size ought to be many gigabytes, well, you have a more active write workload.  Perhaps you're inserting a lot of big rows or something.  In this case you might want to make the log smaller so you don't end up with GB of logs.  But also realize this: the recovery time depends not only on the total log file size, but the number of entries in it.  If you're writing huge entries to the log, fewer log entries will fit into a given log file size, which will generally make recovery faster than you might expect with a big log.</p>
<p>However, most of the time when I run this calculation, I end up finding that the log file size needs to be a lot <em>smaller</em> than it's configured to be.  In part that's because InnoDB's log entries are very compact.  The other reason is that the common advice to size the logs as a fraction of the buffer pool size is just wrong.</p>
<p>One final note: huge buffer pools or really unusual workloads may require bigger (or smaller!) log sizes.  This is where formulas break down and judgment and experience are needed.  But this "rule of thumb" is generally a good sane place to start.</p>
    <hr noshade style="margin:0;height:1px" />
    <p>Entry posted by Baron Schwartz |
      <a href="http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/#comments">25 comments</a></p>
    <p>Add to: <a href="http://del.icio.us/post?url=http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/&amp;title=How to calculate a good InnoDB log file size" title="Bookmark this post on del.icio.us"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/delicious.png" alt="delicious" /></a> | <a href="http://digg.com/submit?phase=2&amp;url=http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/&amp;title=How to calculate a good InnoDB log file size" title="Digg this post on Digg.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/digg.png" alt="digg" /></a> | <a href="http://reddit.com/submit?url=http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/&amp;title=How to calculate a good InnoDB log file size" title="Submit this post on reddit.com"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/reddit.png" alt="reddit" /></a> | <a href="http://www.netscape.com/submit/?U=http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/&amp;T=How to calculate a good InnoDB log file size" title="Vote for this article on Netscape"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/netscape.gif" alt="netscape" /></a> | <a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/&amp;title=How to calculate a good InnoDB log file size" title="Add to Google Bookmarks"><img src="http://www.mysqlperformanceblog.com/wp-content/themes/boxy-but-gold/images/google.png" alt="Google Bookmarks" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
	</channel>
</rss>
