<?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>code.openark.org &#187; InnoDB</title>
	<atom:link href="http://code.openark.org/blog/tag/innodb/feed" rel="self" type="application/rss+xml" />
	<link>http://code.openark.org/blog</link>
	<description>Blog by Shlomi Noach</description>
	<lastBuildDate>Tue, 07 Sep 2010 05:53:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Personal observation: more migrations from MyISAM to InnoDB</title>
		<link>http://code.openark.org/blog/mysql/personal-observation-more-migrations-from-myisam-to-innodb</link>
		<comments>http://code.openark.org/blog/mysql/personal-observation-more-migrations-from-myisam-to-innodb#comments</comments>
		<pubDate>Wed, 16 Jun 2010 16:43:42 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[MyISAM]]></category>
		<category><![CDATA[Opinions]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2517</guid>
		<description><![CDATA[I&#8217;m evidencing an increase in the planning, confidence &#38; execution for MyISAM to InnoDB migration. How much can a single consultant observe? I agree Oracle should not go to PR based on my experience. But I find that: More companies are now familiar with InnoDB than there used to. More companies are interested in migration [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m evidencing an increase in the planning, confidence &amp; execution for MyISAM to InnoDB migration.</p>
<p>How much can a single consultant observe? I agree Oracle should not go to PR based on my experience. But I find that:</p>
<ul>
<li>More companies are now familiar with InnoDB than there used to.</li>
<li>More companies are interested in migration to InnoDB than there used to.</li>
<li>More companies feel such migration to be safe.</li>
<li>More companies start up with an InnoDB based solution than with a MyISAM based solution.</li>
</ul>
<p>This is the way I see it. No doubt, the Oracle/Sun deal made its impact. The fact that InnoDB is no longer a 3rd party; the fact Oracle invests in InnoDB and no other engine (Falcon is down, no real development on MyISAM); the fact InnoDB is to be the default engine: all these put companies at ease with migration.</p>
<p><span id="more-2517"></span>I am happy with this change. I believe for most installations InnoDB provides with a clear advantage over MyISAM (though MyISAM has its uses), and this makes for more robust, correct and manageable MySQL instances; the kind that make a DBA&#8217;s life easier and quieter. And it is easier to make customers see the advantages.</p>
<p>I am not inclined to say <em>&#8220;You should migrate your entire database to InnoDB&#8221;</em>. I don&#8217;t do that a lot. But recently, more customers approach and say <em>&#8220;We were thinking about migrating our entire database to InnoDB, what do you think?&#8221;</em>. What a change of approach.</p>
<p>And, yes: there are still <em>a lot</em> of companies using MyISAM based databases, who still live happily.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/personal-observation-more-migrations-from-myisam-to-innodb/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A MyISAM backup is blocking as read-only, including mysqldump backup</title>
		<link>http://code.openark.org/blog/mysql/a-myisam-backup-is-blocking-as-read-only-including-mysqldump-backup</link>
		<comments>http://code.openark.org/blog/mysql/a-myisam-backup-is-blocking-as-read-only-including-mysqldump-backup#comments</comments>
		<pubDate>Tue, 18 May 2010 17:29:05 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[MyISAM]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=2441</guid>
		<description><![CDATA[Actually this is (almost) all I wanted to say. This is intentionally posted with all related keywords in title, in the hope that a related search on Google will result with this post on first page. I&#8217;m just still encountering companies who use MyISAM as their storage engine and are unaware that their nightly backup [...]]]></description>
			<content:encoded><![CDATA[<p>Actually this is (almost) all I wanted to say. This is intentionally posted with all related keywords in title, in the hope that a related search on Google will result with this post on first page.</p>
<p>I&#8217;m just still encountering companies who use MyISAM as their storage engine and are <em>unaware</em> that their nightly backup actually blocks their application, basically rendering their product unavailable for long minutes to hours on a nightly basis.</p>
<p>So this is posted as a warning for those who were not aware of this fact.</p>
<p>There is no hot (non blocking) backup for MyISAM. Closest would be file system snapshot, but even this requires flushing of tables, which may take a while to complete. If you must have a hot backup, then either use replication &#8211; and take the risk of the slave not being in complete sync with the master &#8211; or use another storage engine, i.e. InnoDB.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/a-myisam-backup-is-blocking-as-read-only-including-mysqldump-backup/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Reducing locks by narrowing primary key</title>
		<link>http://code.openark.org/blog/mysql/reducing-locks-by-narrowing-primary-key</link>
		<comments>http://code.openark.org/blog/mysql/reducing-locks-by-narrowing-primary-key#comments</comments>
		<pubDate>Tue, 04 May 2010 06:46:01 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Indexing]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=1269</guid>
		<description><![CDATA[In a period of two weeks, I had two cases with the exact same symptoms. Database users were experiencing low responsiveness. DBAs were seeing locks occurring on seemingly normal tables. In particular, looking at Innotop, it seemed that INSERTs were causing the locks. In both cases, tables were InnoDB. In both cases, there was a [...]]]></description>
			<content:encoded><![CDATA[<p>In a period of two weeks, I had two cases with the exact same symptoms.</p>
<p>Database users were experiencing low responsiveness. DBAs were seeing locks occurring on seemingly normal tables. In particular, looking at Innotop, it seemed that <strong>INSERT</strong>s were causing the locks.</p>
<p>In both cases, tables were InnoDB. In both cases, there was a <strong>PRIMARY KEY</strong> on the combination of all <strong>5</strong> columns. And in both cases, there was no clear explanation as for why the <strong>PRIMARY KEY</strong> was chosen as such.</p>
<h4>Choosing a proper PRIMARY KEY</h4>
<p>Especially with InnoDB, which uses clustered index structure, the <strong>PRIMARY KEY</strong> is of particular importance. Besides the fact that a bloated <strong>PRIMARY KEY</strong> bloats the entire clustered index and secondary keys (see: <a href="http://code.openark.org/blog/mysql/the-depth-of-an-index-primer">The depth of an index: primer</a>), it is also a source for locks. It&#8217;s true that any <strong>UNIQUE KEY</strong> can serve as a <strong>PRIMARY KEY</strong>. But not all such keys are good candidates.<span id="more-1269"></span></p>
<h4>Reducing the locks</h4>
<p>In both described cases, the solution was to add an <strong>AUTO_INCREMENT</strong> column to serve as the <strong>PRIMARY KEY</strong>, and have that <strong>5</strong> column combination under a secondary <strong>UNIQUE KEY</strong>. The impact was immediate: no further locks on that table were detected, and query responsiveness turned very high.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/reducing-locks-by-narrowing-primary-key/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Tip: faster than TRUNCATE</title>
		<link>http://code.openark.org/blog/mysql/tip-faster-than-truncate</link>
		<comments>http://code.openark.org/blog/mysql/tip-faster-than-truncate#comments</comments>
		<pubDate>Tue, 09 Mar 2010 11:37:01 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=1896</guid>
		<description><![CDATA[TRUNCATE is usually a fast operation (much faster than DELETE FROM). But sometimes it just hangs; I&#8217;ve has several such uncheerful events with InnoDB (Plugin) tables which were extensively written to. The TRUNCATE hanged; nothing else would work; minutes pass. TRUNCATE on tables with no FOREIGN KEYs should act fast: it translate to dropping the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://dev.mysql.com/doc/refman/5.0/en/truncate-table.html"><strong>TRUNCATE</strong></a> is usually a fast operation (much faster than <strong>DELETE FROM</strong>). But sometimes it just hangs; I&#8217;ve has several such uncheerful events with InnoDB (Plugin) tables which were extensively written to. The <strong>TRUNCATE</strong> hanged; nothing else would work; minutes pass.</p>
<p><strong>TRUNCATE</strong> on tables with no <strong>FOREIGN KEY</strong>s <em>should</em> act fast: it translate to dropping the table and creating a new one (and it all depends on the MySQL version, see the manual).</p>
<p>What&#8217;s faster than <strong>TRUNCATE</strong>, then? If you don&#8217;t have triggers nor <strong>FOREIGN KEY</strong>s, a <a href="http://dev.mysql.com/doc/refman/5.0/en/rename-table.html"><strong>RENAME TABLE</strong></a> can come to the rescue. Instead of:</p>
<blockquote>
<pre>TRUNCATE log_table</pre>
</blockquote>
<p>Do:</p>
<blockquote>
<pre>CREATE TABLE log_table_new LIKE log_table;
<strong>RENAME TABLE</strong> log_table TO log_table_old, log_table_new TO log_table;
DROP TABLE log_table_old;</pre>
</blockquote>
<p>I found this to work well for me. Do note that <strong>AUTO_INCREMENT</strong> values can be tricky here: the &#8220;new&#8221; table is created with an <strong>AUTO_INCREMENT</strong> value which is immediately taken in the &#8220;working&#8221; table. If you care about not using same <strong>AUTO_INCREMENT</strong> values, you can:<span id="more-1896"></span></p>
<blockquote>
<pre>ALTER TABLE log_table_new AUTO_INCREMENT=<em>some high enough value;</em></pre>
</blockquote>
<p>Just before renaming.</p>
<p>I do not have a good explanation as for why the <strong>RENAME TABLE</strong> succeeds to respond faster than <strong>TRUNCATE</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/tip-faster-than-truncate/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Performance analysis with mycheckpoint</title>
		<link>http://code.openark.org/blog/mysql/performance-analysis-with-mycheckpoint</link>
		<comments>http://code.openark.org/blog/mysql/performance-analysis-with-mycheckpoint#comments</comments>
		<pubDate>Thu, 12 Nov 2009 10:47:00 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Analysis]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[mycheckpoint]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=1568</guid>
		<description><![CDATA[mycheckpoint (see announcement) allows for both graph presentation and quick SQL access to monitored &#38; analyzed data. I&#8217;d like to show the power of combining them both. InnoDB performance Taking a look at one of the most important InnoDB metrics: the read hit ratio (we could get the same graph by looking at the HTML [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.openark.org/forge/mycheckpoint">mycheckpoint</a> (see <a href="http://code.openark.org/blog/mysql/announcing-mycheckpoint-lightweight-sql-oriented-monitoring-for-mysql">announcement</a>) allows for both graph presentation and quick SQL access to monitored &amp; analyzed data. I&#8217;d like to show the power of combining them both.</p>
<h4>InnoDB performance</h4>
<p>Taking a look at one of the most important InnoDB metrics: the read hit ratio (we could get the same graph by looking at the <a href="http://code.openark.org/forge/mycheckpoint/documentation/generating-html-reports">HTML report</a>):</p>
<blockquote>
<pre>SELECT innodb_read_hit_percent FROM sv_report_chart_sample \G
*************************** 1. row ***************************
innodb_read_hit_percent: http://chart.apis.google.com/chart?cht=lc&amp;chs=400x200&amp;chts=303030,12&amp;chtt=Nov+10,+11:40++-++Nov+11,+08:55+(0+days,+21+hours)&amp;chdl=innodb_read_hit_percent&amp;chdlp=b&amp;chco=ff8c00&amp;chd=s:400664366P6674y7176677677u467773y64ux166666764366646y616666666666644444434444s6u4S331444404433341334433646777666666074736777r1777767764776666F667777617777777777777777yaRi776776mlf667676xgx776766rou67767777u37797777x76676776u6A737464y67467761777666643u66446&amp;chxt=x,y&amp;chxr=1,99.60,100.00&amp;chxl=0:||Nov+10,+15:55|Nov+10,+20:10|Nov+11,+00:25|Nov+11,+04:40|&amp;chxs=0,505050,10</pre>
</blockquote>
<blockquote>
<pre><img class="alignnone" title="innodb_read_hit_percent" src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x200&amp;chts=303030,12&amp;chtt=Nov+10,+11:40++-++Nov+11,+08:55+(0+days,+21+hours)&amp;chdl=innodb_read_hit_percent&amp;chdlp=b&amp;chco=ff8c00&amp;chd=s:400664366P6674y7176677677u467773y64ux166666764366646y616666666666644444434444s6u4S331444404433341334433646777666666074736777r1777767764776666F667777617777777777777777yaRi776776mlf667676xgx776766rou67767777u37797777x76676776u6A737464y67467761777666643u66446&amp;chxt=x,y&amp;chxr=1,99.60,100.00&amp;chxl=0:||Nov+10,+15:55|Nov+10,+20:10|Nov+11,+00:25|Nov+11,+04:40|&amp;chxs=0,505050,10" alt="" width="400" height="200" /></pre>
</blockquote>
<p>We see that read hit is usually high, but occasionally drops low, down to 99.7, or even 99.6. But it seems like most of the time we are above 99.95% read hit ratio. It&#8217;s hard to tell about 99.98%.</p>
<h4>Can we know for sure?</h4>
<p>We can stress our eyes, yet be certain of little. It&#8217;s best if we just query for the metrics! <em>mycheckpoint</em> provides with all data, accessible by simple SQL queries:<span id="more-1568"></span></p>
<blockquote>
<pre>SELECT SUM(innodb_read_hit_percent &gt; 99.95)/count(*)
  FROM sv_report_sample;
+-----------------------------------------------+
| SUM(innodb_read_hit_percent &gt; 99.95)/count(*) |
+-----------------------------------------------+
|                                        0.7844 |
+-----------------------------------------------+</pre>
</blockquote>
<p>Yes, most of the time we&#8217;re above 99.95% read hit ratio: but not too often!</p>
<p>I&#8217;m more interested in seeing how much time my server&#8217;s above 99.98% read hit:</p>
<blockquote>
<pre>SELECT SUM(innodb_read_hit_percent &gt; 99.98)/count(*)
  FROM sv_report_sample;
+-----------------------------------------------+
| SUM(innodb_read_hit_percent &gt; 99.98)/count(*) |
+-----------------------------------------------+
|                                        0.3554 |
+-----------------------------------------------+</pre>
</blockquote>
<p>We can see the server only has 99.98% read hit percent 35% of the time. Need to work on that!</p>
<h4>Disk activity</h4>
<p>Lower read hit percent means higher number of disk reads; that much is obvious. The first two following graphs present this obvious connection. But the third graph tells us another fact: with increased disk I/O, we can expect more (and longer) locks.</p>
<p>Again, this should be very intuitive, when thinking about it this way. The problem sometimes arises when we try to analyze it the other way round: &#8220;Hey! InnoDB has a lot of locks! What are we going to do about it?&#8221;. Many times, people will look for answers in their <em>transactions</em>, their <em>Isolation Level</em>, their <em>LOCK IN SHARE MODE</em> clauses. But the simple answer can be: &#8220;There&#8217;s a lot of I/O, so everything has to wait; therefore we increase the probability for locks; therefore there&#8217;s more locks&#8221;.</p>
<p>The answer, then, is to reduce I/O. The usual stuff: slow queries; indexing; &#8230; and, yes, perhaps transactions or tuning.</p>
<p>The charts below make it quite clear that we have an issue of excessive reads -&gt; less read hit -&gt; increased I/O -&gt; more locks.</p>
<blockquote>
<pre><img class="alignnone" title="DML" src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x200&amp;chts=303030,12&amp;chtt=Oct+31,+17:00++-++Nov+11,+08:00+(10+days,+15+hours)&amp;chdl=com_select_psec|com_insert_psec|com_delete_psec|com_update_psec|com_replace_psec&amp;chdlp=b&amp;chco=ff8c00,4682b4,9acd32,dc143c,9932cc&amp;chd=s:IJJJJJKHGHGHGHHHHHIIIJJJKKKLKLLIHHHIHIHIIIJJJJJKKKLLLLMIHHHHHHHIIIIIJJKKKLLLLMMIHIIIIIIIIIIJJJJKKLLLLMMIHHHIHIHIIIJJJJJKKLKLLLLIHHHIHIHIIIIJIJJJJKKKKKKHHHHHHHHHHHHIIIIJIJJJJJKHHHHHHHHHHIIJJNKLLKKLLLMSMHHIHHHIOSae9RNPJIIJJJKHGGGHGGHHHHHJJKJLKLLLMKMJHIIIIIII,EEEEEEEFEEEEEEEFEFFFFFFFFFFFFFFEEFFEEEEEFFFFFFFFFFFGFFFGFFFFEEEEFFFFFFGGFGFFFFFGEFFFEEFFFFFFFFFFFFFFFFFGEEEEEEEEFFFGGFFFFGFFFFFGEEEFFEEFFEFFEEFFFFFFFEEFEEEEEEEEEEEEEEFFEEEEFEEGEEEEEEEEEFFFFFFFFFEFFFFHEEEEEEEFFFFFFFFFFEEEEFEHEFEEEEEEEEFFFGFGGFFFFFFIEEEEEEEF,CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCCCCDDCCCCCCCCCCCCCCCDCCCCCCCCCCCCCCCCCCDCCCCECCBCBCCCCCCCCCCDCCCCCDCECCCCCCCCCCCCCCCCCCCDCCCDCCCCBBCCCCDCCDCCCCCCCCCECCCBBCCCCCCCCCCCCCCCCCCFCCBCCCCCCCCCCCCCCCCCCCCFCCCCBCCCCCCCDCCCCDCCDCCGCCCCCCCD,CBCCCBBCBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCBBBCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBCBBBBBBBBCBBCCCCCCCCCCCCCCCCCCCCC,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;chxt=x,y&amp;chxr=1,0,680.42&amp;chxl=0:||Nov+2,+20:00|Nov+4,+23:00|Nov+7,+02:00|Nov+9,+05:00|&amp;chxs=0,505050,10" alt="" width="400" height="200" />

<img class="alignnone" title="innodb_read_hit_percent" src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x200&amp;chts=303030,12&amp;chtt=Oct+31,+17:00++-++Nov+11,+08:00+(10+days,+15+hours)&amp;chdl=innodb_read_hit_percent&amp;chdlp=b&amp;chco=ff8c00&amp;chd=s:8p879mq7z1377377777z788863778839z13773877633697786888969z1379377667275377376672813167266771288716689y759121685885785236675889869232685789w63y69997989999252696878y8698878588886933368587ffpibibaTYRfVAdXjqfdmbYneRhciXYcifb6995802z56377666576877268875913278387&amp;chxt=x,y&amp;chxr=1,99.44,99.99&amp;chxl=0:||Nov+2,+20:00|Nov+4,+23:00|Nov+7,+02:00|Nov+9,+05:00|&amp;chxs=0,505050,10" alt="" width="400" height="200" />

<img class="alignnone" title="innodb_io" src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x200&amp;chts=303030,12&amp;chtt=Oct+31,+17:00++-++Nov+11,+08:00+(10+days,+15+hours)&amp;chdl=innodb_buffer_pool_reads_psec|innodb_buffer_pool_pages_flushed_psec&amp;chdlp=b&amp;chco=ff8c00,4682b4&amp;chd=s:DYDDBZVEPMJEFKFGGGEOEDDDEJDECBGBONKEFJEFFFIHFCDDCECCCBECSPLECJEFGHFLDGHEDHEEEDHCMJMGFLGHFELMDCDLEFDBRDFBKIKECIDEHEDHJHFEDGCDCDFCKJKFEJFECRGHNFCCBFBECBCCLHKFBGDEDUEGBCCEEHDCDDFBJJJFEIDFwrfpthozmqqcn3g9hYjkbpqdsvhxormohorGCBHDOLNGEHEDFFGIEFDEDKFDDDGCLIJECIDE,EEEEEGEFSWUFFEGHKIHHHGGHJIHHHHGGQbTFFEFFHGGGGFFHHHGHGFFGUdYGDEGFJKIHHHLKJJJIHHHGHZQRGFGHIHIGGGHIIIGHFFFEHYPNCEFEHHIIIKKJIJHHGIFFGbSPFGJIGFGGGEFFEFEFFEEGSIUODCDFHGGFEEGGGGGGGHFFGYPNDFFGJHIJJIJIHHGFFFEHHVSLCDGIHIHGIHGGFGFFFGIJTRSMEEFFGHHIIIHJKLKHIHGHPNNMCFGE&amp;chxt=x,y&amp;chxr=1,0,151.44&amp;chxl=0:||Nov+2,+20:00|Nov+4,+23:00|Nov+7,+02:00|Nov+9,+05:00|&amp;chxs=0,505050,10" alt="" width="400" height="200" />

<img class="alignnone" title="innodb_row_lock_waits_psec" src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x200&amp;chts=303030,12&amp;chtt=Oct+31,+17:00++-++Nov+11,+08:00+(10+days,+15+hours)&amp;chdl=innodb_row_lock_waits_psec&amp;chdlp=b&amp;chco=ff8c00&amp;chd=s:GWFGGYSHQJKFGJHIHIHNGHGGGKHHFFGGMMJFFKHHHKMIHGIIJGGFGFHGTNOGFJIHGJGKGJHGGGGFHFJFPIKFFJHJIFLKGGFIFGGEVEJGPILGFIGHJJHIJKGGFJGLIGKGJMSGGIGIGVGGQJGHHKHIGHFGLHMHFIFIGQGGIFGJHIEEHFHGKLJHGGGIYgTVXOaXabSUadW9gVfRSeaQbfalXeYcXTiGHIKHKEJEFFFGGGIGGGGHGKGGHGLGPJHGFJEG&amp;chxt=x,y&amp;chxr=1,0,1.42&amp;chxl=0:||Nov+2,+20:00|Nov+4,+23:00|Nov+7,+02:00|Nov+9,+05:00|&amp;chxs=0,505050,10" alt="" width="400" height="200" /></pre>
</blockquote>
<p>By the way, the above resulted from the fact that, due to a problematic query, all slave stopped replicating. Slaves participated in read-balancing, so when they went stale, all reads were directed at the master (the monitored node).</p>
<h4>You have the metrics at your disposal</h4>
<p>Looking at the following chart:</p>
<blockquote>
<pre><img class="alignnone" title="questions" src="http://chart.apis.google.com/chart?cht=lc&amp;chs=400x200&amp;chts=303030,12&amp;chtt=Nov+11,+15:15++-++Nov+12,+12:30+(0+days,+21+hours)&amp;chdl=queries_psec|questions_psec|slow_queries_psec|com_commit_psec|com_set_option_psec&amp;chdlp=b&amp;chco=ff8c00,4682b4,9acd32,dc143c,9932cc&amp;chd=s:pqpviksvvz0vuxxxjpw0mwpkkso1vhuvn0nnrtx2uisrnvoknmusomqvlyymsvpuweqslwumkomutcromzrinukvwcuzotujjto1shrtszqlu849mXenejkaZlZhcYbgciaZZegecUWhZkaYWebfaXVaecdZUZgdbSbccbcTXYeaaTYZfZeVjbnZhRdegcfYorkdmVadqenfcknkoadeuhrjcbptpkhkqkrqfjprrtmllmnqdwsusojoo0qtpwp4,abfjVQebgjaWeedkWRgcelWUcdclYUhddnaVidendUieflaUhcfkdRfefmgSjianfPkcdmfUegamfRmcfmgTgegmhQghgmgWeiepfShfhqjcqzwzfVYdbfbUXbXcYSYaYdVWUZabWTTbXeYUVZYdVTUYabYWUYbbXSWaYaYSSXZZVTVZaXZURZaWbQWZaaYWUWbaZSUadadVUcbbbTWYeabXUUcebUYbabdVUYbbdTWaaccWTddaeTWbdbgXXdci,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,MLOPJHNMNPLKNNNQJHOMNQJJMMMQLIPMNSLJPNNRNJPNNRKJPMNQNHONNRNIPPLROHQNMRNJOOMRNHRMNRNJONOROHOPOROKNPNTOIPOOTOMQUSUNJKNLOLJKMKMKIKLKMJJILLMKIIMKNJJJLKNIJJKKMKJIKLMKHJLKLKIIKKLJIJLKKKJHLLKLHJLKLKJIKLLKIJLMLMKJMMMMIJKMLLKIJMNLJKMLMMJJKLMNIKLLMMKIMMLNIKMMMOKKNMP&amp;chxt=x,y&amp;chxr=1,0,916.47&amp;chxl=0:||Nov+11,+19:30|Nov+11,+23:45|Nov+12,+04:00|Nov+12,+08:15|&amp;chxs=0,505050,10" alt="" width="400" height="200" /></pre>
</blockquote>
<p>It appears that there&#8217;s no slow queries. But this may be misleading: perhaps there&#8217;s just a little, that don&#8217;t show due to the chart&#8217;s large scale?</p>
<p>One could argue that this is the chart&#8217;s fault. Perhaps there should be a distinct chart for &#8220;slow queries percent&#8221;. Perhaps I&#8217;ll add one. But we can&#8217;t have special charts for everything. It&#8217;s would be too tiresome to look at hundreds of charts.</p>
<p>Anyway, my point is: let&#8217;s verify just how many slow queries we have:</p>
<blockquote>
<pre>SELECT slow_queries_psec FROM sv_hour ORDER BY id DESC;
+-------------------+
| slow_queries_psec |
+-------------------+
|              3.05 |
|              3.83 |
|              4.39 |
|              4.03 |
|              3.86 |
|              3.56 |
|              3.73 |
|              3.79 |
|              3.58 |
|              3.55 |
...
+-------------------+</pre>
</blockquote>
<p>So, between 3 and 4 slow queries per second. It doesn&#8217;t look too good in this light. Checking on the percentage of slow queries (of total questions):</p>
<blockquote>
<pre>SELECT ROUND(100*slow_queries_diff/questions_diff, 1) AS slow_queries_percent
  FROM sv_hour ORDER BY id DESC LIMIT 10;</pre>
</blockquote>
<p>Or, since the above calculation is pre-defined in the reports tables:</p>
<blockquote>
<pre>SELECT slow_queries_percent FROM sv_report_hour_recent;
+----------------------+
| slow_queries_percent |
+----------------------+
|                  0.8 |
|                  1.0 |
|                  1.2 |
|                  1.2 |
|                  1.1 |
|                  1.0 |
|                  1.1 |
|                  1.1 |
|                  1.0 |
...
+----------------------+</pre>
</blockquote>
<h4>Accessible data</h4>
<p>This is what I&#8217;ve been trying to achieve with <em>mycheckpoint</em>. As a DBA, consultant and SQL geek I find that direct SQL access works best for me. It&#8217;s like loving command line interface over GUI tools. Direct SQL gives you so much more control and information.</p>
<p>Charting is important, since it&#8217;s easy to watch and get first impressions, or find extreme changes. But beware of relying on charts all the time. Scale issues, misleading human interpretation, technology limitations &#8211; all these make charts inaccurate.</p>
<p><a href="http://code.openark.org/forge/mycheckpoint">mycheckpoint</a> allows for both methods, and, I believe, intuitively so.</p>
<p>&lt;/propaganda&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/performance-analysis-with-mycheckpoint/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to calculate a good InnoDB log file size &#8211; recap</title>
		<link>http://code.openark.org/blog/mysql/how-to-calculate-a-good-innodb-log-file-size-recap</link>
		<comments>http://code.openark.org/blog/mysql/how-to-calculate-a-good-innodb-log-file-size-recap#comments</comments>
		<pubDate>Tue, 20 Oct 2009 19:04:40 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[INFORMATION_SCHEMA]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=895</guid>
		<description><![CDATA[Following Baron Schwartz&#8217; post: How to calculate a good InnoDB log file size, which shows how to make an estimate for the InnoDB log file size, and based on SQL: querying for status difference over time, I&#8217;ve written a query to run on MySQL 5.1, which, upon sampling 60 seconds of status, estimates the InnoDB [...]]]></description>
			<content:encoded><![CDATA[<p>Following Baron Schwartz&#8217; post: <a href="http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/">How to calculate a good InnoDB log file size</a>, which shows how to make an estimate for the InnoDB log file size, and based on <a href="http://code.openark.org/blog/mysql/sql-querying-for-status-difference-over-time">SQL: querying for status difference over time</a>, I&#8217;ve written a query to run on MySQL 5.1, which, upon sampling 60 seconds of status, estimates the InnoDB transaction log bytes that are expected to be written in the period of 1 hour.</p>
<p><em>Recap</em>: this information can be useful if you&#8217;re looking for a good <strong>innodb_log_file_size</strong> value, such that will not pose too much I/O (smaller values will make for more frequent flushes), not will make for a too long recovery time (larger values mean more transactions to recover upon crash).</p>
<p>It is assumed that the 60 seconds period represents an average system load, not some activity spike period. Edit the sleep time and factors as you will to sample longer or shorter periods.<span id="more-895"></span></p>
<blockquote>
<pre><strong>SELECT</strong>
  innodb_os_log_written_per_minute*60
    <strong>AS</strong> estimated_innodb_os_log_written_per_hour,
  CONCAT(ROUND(innodb_os_log_written_per_minute*60/1024/1024, 1), 'MB')
    <strong>AS</strong> estimated_innodb_os_log_written_per_hour_mb
<strong>FROM</strong>
  (<strong>SELECT</strong> <strong>SUM</strong>(value) <strong>AS</strong> innodb_os_log_written_per_minute <strong>FROM</strong> (
    <strong>SELECT</strong> -VARIABLE_VALUE <strong>AS</strong> value
      <strong>FROM</strong> INFORMATION_SCHEMA.GLOBAL_STATUS
      <strong>WHERE</strong> VARIABLE_NAME = 'innodb_os_log_written'
    <strong>UNION ALL</strong>
    <strong>SELECT</strong> SLEEP(60)
      <strong>FROM</strong> DUAL
    <strong>UNION ALL</strong>
    <strong>SELECT</strong> VARIABLE_VALUE
      <strong>FROM</strong> INFORMATION_SCHEMA.GLOBAL_STATUS
      <strong>WHERE</strong> VARIABLE_NAME = 'innodb_os_log_written'
  ) s1
) s2
;</pre>
</blockquote>
<p>Sample output:</p>
<blockquote>
<pre>+------------------------------------------+---------------------------------------------+
| estimated_innodb_os_log_written_per_hour | estimated_innodb_os_log_written_per_hour_mb |
+------------------------------------------+---------------------------------------------+
|                                584171520 | 557.1MB                                     |
+------------------------------------------+---------------------------------------------+</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/how-to-calculate-a-good-innodb-log-file-size-recap/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>InnoDB is dead. Long live InnoDB!</title>
		<link>http://code.openark.org/blog/mysql/innodb-is-dead-long-live-innodb</link>
		<comments>http://code.openark.org/blog/mysql/innodb-is-dead-long-live-innodb#comments</comments>
		<pubDate>Thu, 10 Sep 2009 05:04:38 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=1271</guid>
		<description><![CDATA[I find myself converting more and more customers&#8217; databases to InnoDB plugin. In one case, it was a last resort: disk space was running out, and plugin&#8217;s compression released 75% space; in another, a slow disk made for IO bottlenecks, and plugin&#8217;s improvements &#38; compression alleviated the problem; in yet another, I used the above [...]]]></description>
			<content:encoded><![CDATA[<p>I find myself converting more and more customers&#8217; databases to InnoDB plugin. In one case, it was a last resort: disk space was running out, and plugin&#8217;s compression released 75% space; in another, a slow disk made for IO bottlenecks, and plugin&#8217;s improvements &amp; compression alleviated the problem; in yet another, I used the above to fight replication lag on a stubborn slave.</p>
<p>In all those case, I needed to justify the move to &#8220;new technology&#8221;. The questions &#8220;Is it GA? Is it stable?&#8221; are being asked a lot. Well, just a few days ago the MySQL 5.1 distribution started shipping with InnoDB plugin 1.0.4. That gives some weight to the stability question when facing a doubtful customer.</p>
<p>But I realized <em>that wasn&#8217;t the point</em>.</p>
<p><span id="more-1271"></span>Before InnoDB plugin was first announced, little was going on with InnoDB. There were concerns about the slow/nonexistent progress on this important storage engine, essentially the heart of MySQL. Then the plugin was announced, and everyone went happy.</p>
<p>The point being, since then I only saw (or was exposed to, at least) progress on the plugin. The way I understand it, the plugin is the main (and only?) focus of development. And this is the significant thing to consider: if you&#8217;re keeping to &#8220;old InnoDB&#8221;, fine &#8211; but it won&#8217;t get you much farther; you&#8217;re unlikely to see great performance improvements (will 5.4 make a change? An ongoing improvement to InnoDB?). It may eventually become stale.</p>
<p>Converting to InnoDB plugin means you&#8217;re working with the technology at focus. It&#8217;s being tested, benchmarked, forked, improved, talked about, explained. I find this to be a major motive.</p>
<p>So, long live InnoDB Plugin! (At least till next year, that is, when we may all find ourselves migrating to PBXT)</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/innodb-is-dead-long-live-innodb/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Reasons to use InnoDB Plugin</title>
		<link>http://code.openark.org/blog/mysql/reasons-to-use-innodb-plugin</link>
		<comments>http://code.openark.org/blog/mysql/reasons-to-use-innodb-plugin#comments</comments>
		<pubDate>Mon, 03 Aug 2009 08:32:35 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[InnoDB]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=951</guid>
		<description><![CDATA[I wish to present some compelling reasons to use the InnoDB plugin. The plugin is a drop-in replacement for &#8220;normal&#8221; InnoDB tables; enabling many new features. It is the outcome of a long termed silence from InnoBase (Oracle), which were thought to be neglecting the InnoDB engine. I&#8217;m going to leave out &#8220;performance&#8221; for the [...]]]></description>
			<content:encoded><![CDATA[<p>I wish to present some compelling reasons to use the InnoDB plugin. The plugin is a drop-in replacement for &#8220;normal&#8221; InnoDB tables; enabling many new features. It is the outcome of a long termed silence from InnoBase (Oracle), which were thought to be neglecting the InnoDB engine.</p>
<p>I&#8217;m going to leave out &#8220;performance&#8221; for the reason that grander forces <a href="http://www.mysqlperformanceblog.com/2008/12/03/mysql-50-51-and-innodb-plugin-cpu-efficiency/">have benchmarked and written</a> about it.</p>
<h4>Compression</h4>
<p>Using the new <strong>Barracuda</strong> table format, table data can be compressed. Compression depends on the type of data you have in your table, and in <strong>KEY_BLOCK_SIZE</strong>. I have found tables with lots of textual data to compress well, to about 25% volume (that is, reduction of 75%), and strictly integer-typed tables (like an a-2-b connecting table) to compress poorly.</p>
<p>I have seen an InnoDB 50GB database shrink into some 12GB only. Wow! That meant a server which only had RAID 1 two 72GB disks, and which was dangerously filled up with disk space, could now accommodate the database, a backup, and then some!</p>
<p><span id="more-951"></span>Compression does not only occur on disk: when pages are loaded to memory, they are loaded compressed. This means the same <strong>innodb_buffer_pool_size</strong> you had, now holds a lot more data.</p>
<p>There is no compression for the undo buffer.</p>
<h4>INFORMATION_SCHEMA</h4>
<p>There&#8217;s lot&#8217;s of useful data in the new <strong>INFORMATION_SCHEMA</strong> tables. Very interesting questions can be answered:</p>
<ul>
<li>How many transactions are open right now?</li>
<li>What&#8217;s the state of each transaction?</li>
<li>What queries are being run right now?</li>
<li>Are any transaction waiting on locks? Which locks? Held by which transactions?</li>
<li>What kind of locks are currently held? On which tables?</li>
<li>How much time has been spent on compression/uncompress?</li>
<li>How many compression operations have occurred?</li>
<li>How many pages are allocated? How many are free?</li>
</ul>
<h4>Fast index creation</h4>
<p>Just to be clear, this is <em>not</em> non-blocking index creation. It&#8217;s just <em>fast</em>. What&#8217;s <em>fast</em>? Well, <em>slow</em> index creation is what we&#8217;re used to: to add an index we <strong>ALTER TABLE</strong>, thereby creating a new, temporary tablespace, into which the entire table&#8217;s data is copied. With fast index creation, table data is left untouched. The new index is created by scanning the primary key and to-be indexed values. Thus, it requires less I/O operations.</p>
<p>Dropping an index is an instantaneous operation.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/reasons-to-use-innodb-plugin/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Reasons to use innodb_file_per_table</title>
		<link>http://code.openark.org/blog/mysql/reasons-to-use-innodb_file_per_table</link>
		<comments>http://code.openark.org/blog/mysql/reasons-to-use-innodb_file_per_table#comments</comments>
		<pubDate>Thu, 21 May 2009 03:40:42 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[mysqldump]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=614</guid>
		<description><![CDATA[When working with InnoDB, you have two ways for managing the tablespace storage: Throw everything in one big file (optionally split). Have one file per table. I will discuss the advantages and disadvantages of the two options, and will strive to convince that innodb_file_per_table is preferable. A single tablespace Having everything in one big file [...]]]></description>
			<content:encoded><![CDATA[<p>When working with InnoDB, you have two ways for managing the tablespace storage:</p>
<ol>
<li>Throw everything in one big file (optionally split).</li>
<li>Have one file per table.</li>
</ol>
<p>I will discuss the advantages and disadvantages of the two options, and will strive to convince that <strong>innodb_file_per_table</strong> is preferable.</p>
<h4>A single tablespace</h4>
<p>Having everything in one big file means all tables and indexes, from <em>all schemes</em>, are &#8216;mixed&#8217; together in that file.</p>
<p>This allows for the following nice property: free space can be shared between different tables and different schemes. Thus, if I purge many rows from my <strong>log</strong> table, the now unused space can be occupied by new rows of any other table.</p>
<p>This same nice property also translates to a not so nice one: data can be greatly fragmented across the tablespace.</p>
<p>An annoying property of InnoDB&#8217;s tablespaces is that they never shrink. So after purging those rows from the <strong>log</strong> table, the tablespace file (usually <strong>ibdata1</strong>) still keeps the same storage. It does not release storage to the file system.</p>
<p>I&#8217;ve seen more than once how certain tables are left unwatched, growing until disk space reaches 90% and SMS notifications start beeping all around.<span id="more-614"></span></p>
<p>There&#8217;s little to do in this case. Well, one can always purge the rows. Sure, the space would be reused by InnoDB. But having a file which consumes some 80-90% of disk space is a performance catastrophe. It means the disk needle needs to move large distances. Overall disk performance runs very low.</p>
<p>The best way to solve this is to setup a new slave (after purging of the rows), and dump the data into that slave.</p>
<h4>InnoDB Hot Backup</h4>
<p>The funny thing is, the <strong>ibbackup</strong> utility will copy the tablespace file as it is. If it was 120GB, of which only 30GB are used, you still get a 120GB backed up and restored.</p>
<h4>mysqldump, mk-parallel-dump</h4>
<p>mysqldump would be your best choice if you only had the original machine to work with. Assuming you&#8217;re only using InnoDB, a dump with <strong>&#8211;single-transaction</strong> will do the job. Or you can utilize <a title="Maatkit: mk-parallel-dump" href="http://www.maatkit.org/">mk-parallel-dump</a> to speed things up (depending on your dump method and accessibility needs, mind the locking).</p>
<h4>innodb_file_per_table</h4>
<p>With this parameter set, a <strong>.ibd</strong> file is created per table. What we get is this:</p>
<ul>
<li>Tablespace is not shared among different tables, and certainly not among different schemes.</li>
<li>Each file is considered a tablespace of its own.</li>
<li>Again, tablespace never reduces in size.</li>
<li>It is possible to regain space per tablespace.</li>
</ul>
<p>Wait. The last two seem conflicting, don&#8217;t they? Let&#8217;s explain.</p>
<p>In our <strong>log</strong> table example, we purge many rows (up to 90GB of data is removed). The <strong>.ibd</strong> file does not shrink. But we <em>can</em> do:</p>
<blockquote><p>ALTER TABLE log ENGINE=InnoDB</p></blockquote>
<p>What will happen is that a new, temporary file is created, into which the table is rebuilt. Only existing data is added to the new table. Once comlete, the original table is removed, and the new table renamed as the original table.</p>
<p>Sure, this takes a long time, during which the table is completely locked: no writes and no reads allowed. But still &#8211; it allows us to regain disk space.</p>
<p>With the new InnoDB plugin, disk space is also regained when execuing a <strong>TRUNCATE TABLE log</strong> statement.</p>
<p>Fragmentation is not as bad as in a single tablespace: the data is limited within the boundaries of a smaller file.</p>
<h4>Monitoring</h4>
<p>One other nice thing about <strong>innodb_file_per_table</strong> is that it is possible to monitor table size on the file system level. You don&#8217;t need access to MySQL, to use SHOW TABLE STATUS or to query the INFORMATION_SCHEMA. You can just look up the top 10 largest files under your MySQL data directory (and subdirectories), and monitor their size. You can see which table grows fastest.</p>
<h4>Backup</h4>
<p>Last, it is not yet possible to backup single InnoDB tables by copying the <strong>.ibd</strong> files. But hopefully work will be done in this direction.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/reasons-to-use-innodb_file_per_table/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>The depth of an index: primer</title>
		<link>http://code.openark.org/blog/mysql/the-depth-of-an-index-primer</link>
		<comments>http://code.openark.org/blog/mysql/the-depth-of-an-index-primer#comments</comments>
		<pubDate>Thu, 09 Apr 2009 03:55:08 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Data Types]]></category>
		<category><![CDATA[Indexing]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[MyISAM]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=545</guid>
		<description><![CDATA[InnoDB and MyISAM use B+ and B trees for indexes (InnoDB also has internal hash index). In both these structures, the depth of the index is an important factor. When looking for an indexed row, a search is made on the index, from root to leaves. Assuming the index is not in memory, the depth [...]]]></description>
			<content:encoded><![CDATA[<p>InnoDB and MyISAM use B+ and B trees for indexes (InnoDB also has internal hash index).</p>
<p>In both these structures, the depth of the index is an important factor. When looking for an indexed row, a search is made on the index, from root to leaves.</p>
<p>Assuming the index is not in memory, the depth of the index represents the minimal cost (in I/O operation) for an index based lookup. Of course, most of the time we expect large portions of the indexes to be cached in memory. Even so, the depth of the index is an important factor. The deeper the index is, the worse it performs: there are simply more lookups on index nodes.</p>
<p>What affects the depth of an index?</p>
<p>There are quite a few structural issues, but it boils down to two important factors:</p>
<ol>
<li>The number of rows in the table: obviously, more rows leads to larger index, larger indexes grow in depth.</li>
<li>The size of the indexed column(s). An index on an INT column can be expected to be shallower than an index on a CHAR(32) column (on a very small number of rows they may have the same depth, so we&#8217;ll assume a large number of rows).</li>
</ol>
<p><span id="more-545"></span>Of course, these two factors also affect the total size of the index, hence its disk usage, but I wish to concentrate on the index depth.</p>
<p>Let&#8217;s emphasize the second factor. It is best to index shorter columns, if that is possible. It is the reason behind using an index on a VARCHAR&#8217;s prefix (e.g. KEY(email_address(16)). It is also a reason to use INT, instead of BIGINT columns for your primary key, when BIGINT is not required.</p>
<p>The larger the indexed data type is (or the total size of data types for all columns in a combined index), the less values that can fit in an index node. The less values in a node, the more node splits occur; the more nodes are required to build the index. The less values in the node, the less <em>wide</em> the index tree is. The less wide an index tree is, and the more nodes it has &#8211; the deeper it gets.</p>
<p>So bigger data types lead to deeper trees. Deeper trees lead to more IO operations on lookup.</p>
<h4>InnoDB</h4>
<p>On InnoDB there&#8217;s another issue: all tables are clustered by primary key. Any access to table data requires diving into, or traversing the primary key tree.</p>
<p>On InnoDB, a secondary index (any index which is not the primary key) does not lead to table data. Instead, the &#8220;data&#8221; in the leaf nodes of a secondary index &#8211; are the primary key values.</p>
<p>And so, when looking up a value on an InnoDB table using a secondary key, we first search the secondary key to retrieve the primary key value, then go to the primary key tree to retrieve the data.</p>
<p>This means two index lookups, one of which is always the primary key.</p>
<p>On InnoDB, it is therefore in particular important to keep the primary key small. Have small data types. Prefer an SMALLINT to INT, if possible. Prefer an INT to BIGINT, if possible. Prefer an integer value over some VARCHAR text.</p>
<p>With long data types used in an InnoDB primary key, not only is the primary key index bloated (deep), but also every other index gets to be bloated, as the leaf values in all other indexes are those same long data types.</p>
<h4>MyISAM</h4>
<p>MyISAM does not use clustered trees, hence the primary key is just a regular unique key. All indexes are created equal and an index lookup only consists of a single index search. Therefore, two indexes do no affect one another, with the exception that they are competing on the same key cache.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/the-depth-of-an-index-primer/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
