<?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>Transactions on InnoDB</title>
	<atom:link href="http://blogs.innodb.com/wp/category/innodb-builtin/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.innodb.com/wp</link>
	<description>&#34;The word&#34; about InnoDB Products and Technology</description>
	<lastBuildDate>Fri, 23 Dec 2011 11:17:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Improving InnoDB memory usage continued</title>
		<link>http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage-continued/</link>
		<comments>http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage-continued/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 11:14:29 +0000</pubDate>
		<dc:creator>Vasil Dimov</dc:creator>
				<category><![CDATA[InnoDB Builtin]]></category>
		<category><![CDATA[InnoDB Plugin]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1591</guid>
		<description><![CDATA[Continues from Improving InnoDB memory usage. Here are some numbers from the fixups described in the above article: The workload consists of 10 partitioned tables, each one containing 1000 partitions. This means 10&#8217;000 InnoDB tables. We truncate the tables, then restart mysqld and run: 1. INSERT a single row into each of the 10 tables [...]]]></description>
			<content:encoded><![CDATA[<p>Continues from <a href="http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage/" title="Improving InnoDB memory usage">Improving InnoDB memory usage</a>.</p>
<p>Here are some numbers from the fixups described in the <a href="http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage/" title="Improving InnoDB memory usage">above article</a>:</p>
<p>The workload consists of 10 partitioned tables, each one containing 1000 partitions. This means 10&#8217;000 InnoDB tables. We truncate the tables, then restart mysqld and run:</p>
<p>1. INSERT a single row into each of the 10 tables<br />
2. SELECT * from each table<br />
3. FLUSH TABLES (this causes the tables to be closed and reopened on the next run)<br />
4. wait for 10 seconds</p>
<p>we repeat the above steps 10 times. Here is the total memory consumption by mysqld with 1GB InnoDB buffer pool during the workload:</p>
<p><span id="more-1591"></span></p>
<p><img src="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/memfix1.png" alt="" title="Memory " width="700" height="500" class="alignnone size-full wp-image-1601" /></p>
<p>In the fixed case (green line) you can clearly see the peaks when the commands 1. &#8211; 4. are run and the valley bottoms during the 10 seconds waits.</p>
<p>Notice that no memory leaks were fixed in these improvements. This is all about interaction between InnoDB and the system allocator. InnoDB always frees memory it has allocated, but the problem was that the system allocator could not reuse the freed memory optimally due to memory fragmentation. We mainly reduced the number of and the sizes of some of the hottest allocations, mitigating the malloc/free storm.</p>
<p>Notice also that this is somewhat unusual workload &#8211; 10&#8217;000 InnoDB tables, row size of about 64KB and frequent FLUSH TABLES.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage-continued/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Improving InnoDB memory usage</title>
		<link>http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage/</link>
		<comments>http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 18:08:42 +0000</pubDate>
		<dc:creator>Vasil Dimov</dc:creator>
				<category><![CDATA[Bug fix]]></category>
		<category><![CDATA[InnoDB Builtin]]></category>
		<category><![CDATA[InnoDB Plugin]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[fragmentation]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[leak]]></category>
		<category><![CDATA[Memory]]></category>
		<category><![CDATA[oom]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1510</guid>
		<description><![CDATA[Last month we did a few improvements in InnoDB memory usage. We solved a challenging issue about how InnoDB uses memory in certain places of the code. The symptom of the issue was that under a certain workloads the memory used by InnoDB kept growing infinitely, until OOM killer kicked in. It looked like a [...]]]></description>
			<content:encoded><![CDATA[<p>Last month we did a few improvements in InnoDB memory usage. We solved a challenging issue about how InnoDB uses memory in certain places of the code.</p>
<p>The symptom of the issue was that under a certain workloads the memory used by InnoDB kept growing infinitely, until <a href="http://en.wikipedia.org/wiki/Out_of_memory" title="OOM killer" target="_blank">OOM killer</a> kicked in. It looked like a memory leak, but <a href="http://valgrind.org/" title="Valgrind" target="_blank">Valgrind</a> wasn&#8217;t reporting any leaks and the issue was not reproducible on FreeBSD &#8211; it only happened on Linux (see <a href="http://bugs.mysql.com/57480" title="Bug#57480" target="_blank">Bug#57480</a>). Especially the latest fact lead us to think that there is something in the InnoDB memory usage pattern that reveals a nasty side of the otherwise good-natured Linux&#8217;s memory manager.</p>
<p>It turned out to be an interesting <a href="http://en.wikipedia.org/wiki/Fragmentation_(computing)" title="memory fragmentation" target="_blank">memory fragmentation</a> caused by a storm of malloc/free calls of various sizes. We had to track and analyze <strong>each</strong> call to malloc during the workload, including the code path that lead to it. We collected a huge set of analysis data &#8211; some code paths were executed many 10&#8217;000s of times! A hurricane of allocations and deallocations! We looked at the hottest ones hoping that some of them are not necessary, can be eliminated, avoided, minimized or stuck together. Luckily there were plenty of them!</p>
<p>After an extensive testing we did a numerous improvements, allocating the smallest chunks of the memory from the stack instead of from the heap, grouping allocations together where possible, removing unnecessary allocations altogether, estimating exactly how much memory will be consumed by a given operation and allocating it in advance and others and others and others.</p>
<p>This not only fixed <a href="http://bugs.mysql.com/57480" title="Bug#57480" target="_blank">Bug#57480</a> but improved InnoDB memory usage in general.</p>
<p><span id="more-1510"></span></p>
<p>Note: the fix is not in the 5.6.4 release.</p>
<p>Continues with some numbers <a href="http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage-continued/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Better scaling of read-only workloads</title>
		<link>http://blogs.innodb.com/wp/2011/12/better-scaling-of-read-only-workloads/</link>
		<comments>http://blogs.innodb.com/wp/2011/12/better-scaling-of-read-only-workloads/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 17:55:12 +0000</pubDate>
		<dc:creator>Sunny Bains</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[auto commit]]></category>
		<category><![CDATA[read only]]></category>
		<category><![CDATA[Transactions]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1500</guid>
		<description><![CDATA[The problem and its cause There have been several complaints over the years about InnoDB&#8217;s inability to scale beyond 256 connections. One of the main issues behind this scalability bottleneck was the read view creation that is required for MVCC (Multi Version Concurrency Control) to work. When the user starts a transaction this is what [...]]]></description>
			<content:encoded><![CDATA[<p><strong>The problem and its cause<br />
</strong></p>
<p>There have been several complaints over the years about InnoDB&#8217;s inability to scale beyond 256 connections. One of the main issues behind this scalability bottleneck was the read view creation that is required for MVCC (Multi Version Concurrency Control) to work. When the user starts a transaction this is what InnoDB does under the hood:</p>
<ul>
<li>Create or reuse a transaction instance &#8211; usually it is reused, the transactions are reused from a pool (trx_sys_t::mysql_trx_list).</li>
<li>Initialize the transaction start time and assign a rollback segment</li>
<li>Append the transaction to an active  transaction list ordered on trx_t::id in descending order</li>
</ul>
<p>The append to  the trx_sys_t::trx_list and corresponding remove during commit is covered by trx_sys_t::mutex. After the transaction is &#8220;started&#8221; and if the transaction has an isolation greater than or equal to <strong>REPEATABLE-READ</strong> then before the first record/row is accessed by the transaction, InnoDB creates a view (snapshot) of the running system state. It does this by examining the transactions that are active at the time of the MVCC snapshot, so that their changes can be excluded from the creating transaction&#8217;s read view. This read view creation is also covered by the trx_sys_t::mutex. As the number of active transactions in the system increases this read view creation takes longer and longer. This increases the wait times on the trx_sys_t::mutex (during transaction start and commit) and once threads are forced to wait on a condition variable (in contrast to simply spinning while waiting for the mutex) the system throughput drops dramatically.</p>
<p><strong>The solution</strong></p>
<p>While investigating this problem there were two observations that I made:<span id="more-1500"></span></p>
<ul>
<li>Read only transactions should not be considered in the MVCC snapshot</li>
<li>Auto commit non-locking read-only selects should not be in the trx_sys_t::trx_list at all</li>
</ul>
<p>For the first to work we need to tag the transactions as<strong> READ ONLY</strong> when the transaction is started e.g.,</p>
<ul>
<li><strong>      START TRANSACTION READ ONLY;</strong></li>
</ul>
<p><strong></strong>I will not be discussing this functionality in this blog because the syntax for this doesn&#8217;t exist in MySQL (yet). However, the functionality exists in InnoDB to handle this case and is  in the 5.6.4 release. Once the above syntax exists, InnoDB can take advantage of the new syntax trivially. What I want to talk about is the second case. This special case can be detected by InnoDB using existing state information and handled transparently without any syntax change in user applications and is fully functional in the 5.6.4 release.</p>
<p><strong>InnoDB transaction life cycle redesign</strong></p>
<p>Split the trx_sys_t::trx_list (the active transactions list) into two, trx_sys_t::ro_trx_list and trx_sys_t::rw_trx_list. Only transactions that are in the trx_sys_t::rw_trx_list are taken into consideration when creating the MVCC snapshot. For a read-only heavy work load the benefits are obvious,  the smaller size of the RW active transaction list makes the read view creation for MVCC (and purge) very fast. For auto-commit read-only non-locking selects the additional benefit is that we don&#8217;t need to acquire the trx_sys_t::mutex at all because we don&#8217;t put them on the active list. This removes the bottleneck around the trx_sys_t::mutex and improves concurrency and scalability.</p>
<p>Auto-commit read-only non-locking transactions go from state NOT STARTED -&gt; ACTIVE -&gt; NOT STARTED, in contrast to locking read-only (and read-write) transactions which go from state NOT STARTED -&gt; ACTIVE -&gt; COMMIT TO MEMORY -&gt; NOT STARTED. The additional advantage in skipping the COMMIT TO MEMORY state is that we know that they cannot acquire any locks and therefore it is pointless to acquire the lock_sys_t::mutex and attempt lock release. Also, during COMMIT because they are not on any active transaction list we don&#8217;t need to acquire the trx_sys_t::mutex to remove them from the list, improving concurrency and performance further.</p>
<p><strong>Changes to transaction state visibility</strong></p>
<p>Currently (5.6.4) doesn&#8217;t display the auto-commit read-only non-locking selects in &#8220;<strong>SHOW ENGINE INNODB STATUS</strong>&#8220;, however they are visible in the <strong>INFORMATION_SCHEMA.innodb_trx</strong> table. The innodb_trx table has two new fields that can be queried to determine whether  a transaction is tagged as a read-only transaction and additionally whether it qualifies for the special handling of auto-commit read-only non-locking select. The new fields are:</p>
<ul>
<li>trx_read_only &#8211; 0 or 1 (INT)</li>
<li>trx_autocommit_non_locking &#8211; 0 or 1 (INT)</li>
</ul>
<p>Some additional minor tweaks, read-only transactions aren&#8217;t assigned a rollback segment and if they are flagged as autocommit non-locking selects then we only set the start time once every 32 times, his reduces the overhead of a system call.</p>
<p><strong>Test results</strong></p>
<p>These tests were run by Alexey Stroganov (a.k.a Ranger) using Sysbench (with &#8211;oltp-skip-trx=on), wl6046 refers to the internal worklog number of this performance fix. Note how InnoDB scales easily up to 4K threads on the 24 host and 1.5K threads on the 8 core host, there is very little (negligible) drop in the TPS as the number of threads is cranked up. In particular note how the peak TPS on the 24 core host is nearly double <img src='http://blogs.innodb.com/wp/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h5>Test POINT_SELECT</h5>
<ul>
<li>QUERY <strong>- SELECT c FROM sbtest</strong><strong> WHERE id=N</strong></li>
</ul>
<p><a href="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/POINT_SELECT_5.6.4.pan01.wl6046-linux_x86_64-std-1m_InnoDB_v1.02.png"><img class="size-full wp-image-1543 alignnone" title="POINT_SELECT 8 core host" src="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/POINT_SELECT_5.6.4.pan01.wl6046-linux_x86_64-std-1m_InnoDB_v1.02.png" alt="" width="498" height="339" /></a></p>
<p><a href="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/POINT_SELECT_5.6.4.caneland.wl6046-linux_x86_64-std-1m_InnoDB_v1.021.png"><img class="alignnone size-full wp-image-1547" title="POINT_SELECT 24 core host" src="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/POINT_SELECT_5.6.4.caneland.wl6046-linux_x86_64-std-1m_InnoDB_v1.021.png" alt="" width="498" height="339" /></a><br />
<strong>Test SIMPLE_RANGES</strong></p>
<ul>
<li>QUERY<strong> &#8211; SELECT c FROM sbtest WHERE id BETWEEN N AND M</strong></li>
</ul>
<p><a href="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/SELECT_SIMPLE_RANGES_5.6.4.pan01.wl6046-linux_x86_64-std-1m_InnoDB_v1.02.png"><img class="alignnone size-full wp-image-1546" title="SELECT_SIMPLE_RANGES 8 core host" src="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/SELECT_SIMPLE_RANGES_5.6.4.pan01.wl6046-linux_x86_64-std-1m_InnoDB_v1.02.png" alt="" width="498" height="339" /></a></p>
<p><a href="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/SELECT_SIMPLE_RANGES_5.6.4.caneland.wl6046-linux_x86_64-std-1m_InnoDB_v1.02.png"><img class="alignnone size-full wp-image-1548" title="SELECT_SIMPLE_RANGES 24 core host" src="http://blogs.innodb.com/wp/wp-content/uploads/2011/12/SELECT_SIMPLE_RANGES_5.6.4.caneland.wl6046-linux_x86_64-std-1m_InnoDB_v1.02.png" alt="" width="498" height="339" /></a></p>
<p>The same result for SIMPLE RANGES, at lower thread levels 5.6 has less TPS than 5.5 on the 8 core host however that is due to another known and unrelated issue that is currently being worked on actively.</p>
<p><strong>Conclusion</strong></p>
<p>This is a significant step forward in InnoDB read-only performance and will allow InnoDB to scale up to a very high number of concurrent queries and take advantage of greater number of processors with the improved parallelism. Note: mixed workloads with a read-only heavy component will also benefit from this improvement. Currently, only if the read-only transactions are auto-commit non-locking selects. The better news is that with this split of the active transaction list into two, we can now optimize deadlock detection, lock release and transaction scheduling around lock grants and waits, stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/12/better-scaling-of-read-only-workloads/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>InnoDB Full-Text Search is in MySQL 5.6.4</title>
		<link>http://blogs.innodb.com/wp/2011/12/innodb-full-text-search-in-mysql-5-6-4/</link>
		<comments>http://blogs.innodb.com/wp/2011/12/innodb-full-text-search-in-mysql-5-6-4/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 17:16:00 +0000</pubDate>
		<dc:creator>Jimmy Yang</dc:creator>
				<category><![CDATA[InnoDB FTS]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1474</guid>
		<description><![CDATA[InnoDB full-text search (FTS) is finally available in MySQL 5.6.4 release. The feature has been on trial through MySQL&#8217;s summer lab release, thus we had several blogs covering the feature. In this blog, we will leave the “how to” part of the feature to those blogs, and focus on some important characteristics of this new [...]]]></description>
			<content:encoded><![CDATA[<p>InnoDB full-text search (FTS) is finally available in MySQL 5.6.4 release. The feature has been on trial through MySQL&#8217;s summer lab release, thus we had several blogs covering the feature. In this blog, we will leave the “how to” part of the feature to those blogs, and focus on some important characteristics of this new feature, so you will have a better understanding when trying on the feature.</p>
<p><span style="font-size: medium;"><strong>The InnoDB Full-text Index as an Inverted Index</strong></span></p>
<p>When comes to the basic design, InnoDB takes a traditional way to implementation the full-text index, which is a so called “Inverted Index”. It composes of a set of auxiliary “index tables” that stores the “Word” “Doc ID” pair, as well as each word&#8217;s position in the original text.</p>
<p>Incoming text strings in the inserting records are extracted out, tokenized and decomposed into individual words, and such words are then inserted into the auxiliary “index tables” along with their position info and the Doc ID associated with the record. With the position info, we will be able to support proximity search that is lacking in MyISAM FTS.</p>
<p><span style="font-size: medium;"><strong>Create the Full-text Index in Parallel</strong></span></p>
<p><span id="more-1474"></span></p>
<p>The Full-text Index is created in parallel. By default, the parallel degree is two, which means two threads are used to tokenize, sort and final insertion to the Full-text “index tables”.</p>
<p>To support parallel create index and future parallel processing, InnoDB partitions the “full-text index” into six auxiliary “index tables”. The words are divided among these tables based on their first character&#8217;s charset sort weight. Currently, the partition criteria is hard-coded, targeted to the Latin characters. In the future, we will allow user to define their own partition criteria, to better support other character sets.</p>
<p><span style="font-size: medium;"><strong>Batching the insert value with InnoDB Full-text Index&#8217;s “index cache”</strong></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">As just discussed, when inserting into an “Inverted Index”, each inserting string will be tokenized, and decomposed into individual words before inserting into the auxiliary table. A single insertion could result in many small insertions into the inverted index tables. This magnifies the insertion operations by several or even dozens of fold, thus becomes normal insertion a disruptive fact for concurrent access to the table.</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">Our solution is to build an “internal” FTS “index cache” to temporarily cache these insertions, and batch flush to the disk once this index cache is full. Thus, it avoids frequent updates to the “Index Table” during busy inserts and updates, so the index table only needs to be synchronized when the index cache is full. The batching technique also avoids repetitively storing the same word, minimizes the number of entries for each word in the “Index Table”. So instead of flushing each word with a single “ilist” entry (with a single Doc ID), it batches result from many inserted documents so to create an “ilist” with multiple DocID/position pairs, before we flush this info to disk and also make a single entry. This reduces the redundancy and make the “Index Table” smaller.</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">The index cache is index specific. And has a configuration parameter (innodb_ft_cache_size) to configure the size of the cache. It stores the same information as those auxiliary tables, using a red-black tree data structure. However, this cache is different from an index tree in that it is only used to cache the word of the inserted documents, words on disk do not need to be brought back to this cache before they can be queried. In another word, the words in the “Index Table” are queried directly as we query into relational tables. And such result from “Index Table” will merge (union) with the query results from the Index Cache before sending back to user. </span></span></p>
<p><span style="font-size: medium;"><strong>How InnoDB </strong><strong>Full-text Index handles Deletes</strong></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">Similar to inserts, each delete of the record with full-text index could result in many small “deletes”, if we had implemented it as normal deletes. Again, this could be very disruptive.</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">To avoid such disruptive operation, InnoDB Full-text Index develops a new scheme that only logs the Doc ID of the deleted Documents in a separate “DELETED” auxiliary table. The actually “indexed” record would still remain in the FTS index. However, these deleted Doc Ids will be filtered out from the final results by consulting the “DELETED” table before returning the query result.</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">The benefit of this design is obvious. Delete operation then becomes a trivial and fast operation, with minimum impact on the index itself. The shortcoming is that the index would not shrink along with record deletion. However, the benefits far overweight the drawbacks.</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">To cleanup the deleted records in the index, you will resort to the InnoDB optimize table utility, which rebuilt the Full-text index online. And we will discuss it in the next section.</span></span></p>
<p><strong><span style="font-size: medium;">Index Optimization</span></strong></p>
<p>The optimize table on the Full-Text index essentially rebuilds the full-text index, and leaves those “deleted” Docs out of the new index. This operation does two things:</p>
<p>1) Remove the deleted Doc ID from the word’s DocID/Position pair list (ilist).</p>
<p>2) Consolidate multiple entries for the same word to one (or less) entries if possible by consolidating their DocID/Position pair list (ilist), as we will have as little entry as possible.</p>
<p>Currently, we overload this optimization operation with the “Optimize Table” command, and runs only if you turn on “innodb_optimize_fulltext_only” system configure variable:</p>
<p>mysql&gt; set global innodb_optimize_fulltext_only=1;</p>
<p>mysql&gt; optimize table articles;</p>
<p><span style="font-size: medium;"><span style="font-size: small;">Since the table could be large, and optimization (reorg rebuild index) may take a tremendous amount of time, we allow the optimization to be done in stages. The system configuration variable “innodb_ft_num_word_optimize” specifies how many words to optimize for each “optimize table” command. Its default value is 2000, meaning each time it optimizes 2000 words. And when the next “optimize table” command is issued, the server continues the process from where it left off from last run.</span></span></p>
<p><span style="font-size: medium;"><strong>InnoDB Full-text search Transaction Behavior</strong></span></p>
<p><span style="font-size: small;">As you could see from last two sections, the main idea behind InnoDB Full-text index DML is to batch the operations as much as possible. This determines there will be some special characteristics when coming to transaction handling.</span></p>
<p><span style="font-size: small;">In fact, all of the DML operations (insert/delete/update) involving Full-text indexed columns are processed at the transaction commit time. For example, for insertion, the tokenization for inserted strings is performed only at commit time, as a result, a full-text search only sees the committed data. This “delayed” process/synchronization behavior presents in all transactional DBMS text handling. And we do so at the transaction commit time.</span></p>
<p><span style="font-size: medium;"><strong>InnoDB FTS Document ID </strong></span></p>
<p><span style="font-size: small;">All of above design can&#8217;t be done without the support of a so called FTS Doc ID identifier. The mapping from word to original table record goes through such a unique ID. So there must be a Doc ID column in the table with Full-text index.</span></p>
<p><span style="font-size: small;">In our case, it is represented by the “FTS_DOC_ID” (uppercase required) column. If this column is not defined, InnoDB will automatically add it to the user table when creating the full-text index. The column itself must be of “BIGINT UNSIGNED NOT NULL” type, with a unique index named FTS_DOC_ID_INDEX. When you define this column during table creation, it saves considerable time in creating the full-text index after loading data, since InnoDB does not need to copy the table for adding such column (and also rebuild all indexes include primary index). In such case, user will be responsible to properly manage the Doc ID column so that document will not be inappropriately represented. If create index performance is not a concern, you can leave Doc ID management to InnoDB, by leaving out this column. InnoDB will added “FTS_DOC_ID” as a hidden columns. The “ FTS_DOC_ID_INDEX” will also be created automatically.</span></p>
<p><strong><span style="font-size: medium;">Stopword Handling</span></strong></p>
<p>Stopwords are common or trivial words that are omitted from the full-text index. The InnoDB FTS provides two sources of stopwords:</p>
<p>1) InnoDB predefined default stopwords &#8211; If no user stopword list is defined, this default stopwords list is used.</p>
<p>You can view this list by querying the table INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD:</p>
<p>mysql&gt; select * from INNODB_FT_DEFAULT_STOPWORD;</p>
<p>2) User-defined stopwords – You can define your own stopwords by creating a table with a single column named “value”, with datatype “varchar”, and pointing the global variable “innodb_ft_server_stopword_table” to this table. MySQL loads stopwords from this user table, rather than the default stopword list, when creating the FTS index. And an example will be here:</p>
<ul>
<li># Define a correctly formatted user stopword table</li>
</ul>
<p>create table user_stopword(value varchar(30)) engine = innodb;</p>
<ul>
<li># Point to this stopword table with “db name/table name”</li>
</ul>
<p><span style="font-size: small;">set global innodb_ft_server_stopword_table = “test/user_stopword”</span></p>
<p><strong><span style="font-size: medium;"><strong>Ranking</strong></span></strong></p>
<p><span style="font-size: small;">Currently, we use a very simple ranking mechanism (term frequency, inverse document frequency) for document ranking. This means the more the word appears in a document, and the less frequent the word appears in overall documents, the higher the selected document is ranked. We do have plans to add more sophisticated ranking mechanism and allow users to supplied the weight in the ranking calculation too.</span></p>
<p><strong><span style="font-size: medium;">Limitation</span></strong></p>
<p>As the first release of InnoDB FTS, it provides limited and very basic functionalities for Full-text searches. And it has some limitations that worth mentioning:</p>
<ol>
<li>It does not yet support stemming.</li>
<li>For ideographic languages such as CJK (Chinese, Japanese and Korea), which do not have word delimiters, InnoDB FTS does not yet support N-GRAM parsing (similar to MyISAM FTS).</li>
<li>Although the use of multiple character sets within a single table is supported, all columns in a FULLTEXT index must use the same character set and collation (similar to MyISAM FTS).</li>
<li><span style="font-size: small;">It does not support external parser plugins</span></li>
<li><span style="font-size: small;">Ranking mechanism is relatively simple </span></li>
</ol>
<p><strong><span style="font-size: medium;">Summary</span></strong></p>
<p><span style="font-size: small;">The InnoDB full-text search gives InnoDB an important capability in using MySQL to handle text documents, and we will further develop it to continue increase its performance and usability.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/12/innodb-full-text-search-in-mysql-5-6-4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>InnoDB 5.6.4 supports databases with 4k and 8k page sizes</title>
		<link>http://blogs.innodb.com/wp/2011/12/innodb-5-6-4-supports-4k-8k-page-sizes/</link>
		<comments>http://blogs.innodb.com/wp/2011/12/innodb-5-6-4-supports-4k-8k-page-sizes/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 17:00:24 +0000</pubDate>
		<dc:creator>Kevin Lewis</dc:creator>
				<category><![CDATA[Feature]]></category>
		<category><![CDATA[16k]]></category>
		<category><![CDATA[4k]]></category>
		<category><![CDATA[5.6.4]]></category>
		<category><![CDATA[8k]]></category>
		<category><![CDATA[Antelope]]></category>
		<category><![CDATA[Barracuda]]></category>
		<category><![CDATA[Compatibility]]></category>
		<category><![CDATA[Configuration parameter]]></category>
		<category><![CDATA[File format]]></category>
		<category><![CDATA[ibdata file]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[Page Size]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Row Formats]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1484</guid>
		<description><![CDATA[In the 5.6.4 release it is now possible to create an InnoDB database with 4k or 8k page sizes in addition to the original 16k page size. Previously, it could be done by recompiling the engine with a different value for UNIV_PAGE_SIZE_SHIFT and UNIV_PAGE_SIZE. With this release, you can set &#8211;innodb-page-size=n when starting mysqld, or [...]]]></description>
			<content:encoded><![CDATA[<p>In the 5.6.4 release it is now possible to create an InnoDB database with 4k or 8k page sizes in addition to the original 16k page size. Previously, it could be done by recompiling the engine with a different value for UNIV_PAGE_SIZE_SHIFT and UNIV_PAGE_SIZE. With this release, you can set &#8211;innodb-page-size=n when starting mysqld, or put innodb_page_size=n in the configuration file in the [mysqld] section where n can be 4k, 8k, 16k, or 4096, 8192, 16384.</p>
<p>The support of smaller page sizes may be useful for certain storage media such as SSDs. Performance results can vary depending on your data schema, record size, and read/write ratio. But this provides you more options to optimize your performance.</p>
<p>When this new setting is used, the page size is set for all tablespaces used by that InnoDB instance. You can query the current value with;</p>
<p>SHOW VARIABLES LIKE &#8216;innodb_page_size&#8217;;<br />
or<br />
SELECT variable_value FROM information_schema.global_status  WHERE LOWER(variable_name) = &#8216;innodb_page_size&#8217;;</p>
<p>It is a read-only variable while the engine is running since it must be set before InnoDB starts up and creates a new system tablespace. That happens when InnoDB does not find ibdata1 in the data directory. If you start mysqld with a page size other than the standard 16k, the error log will contain something like this;</p>
<p><span id="more-1484"></span></p>
<p>111214 15:55:05 InnoDB: innodb-page-size has been changed from the default value 16384 to 4096.</p>
<p>If your system tablespace already exists using one page size and innodb-page-size is something else, the engine will not start. There will be a message logged like this;</p>
<p>111214 16:06:51 InnoDB: Error: data file .\ibdata1 uses page size 4096,<br />
111214 16:06:51 InnoDB: but the start-up parameter is innodb-page-size=16384</p>
<p>InnoDB knows the page size used in an existing tablespace created by version 5.6.4 because it stamps that page size in the header page. But this is not readable to older engines, of course. If an older engine opens a database with a page size other than 16k, it will report a corrupted page and quit.</p>
<p>All features in InnoDB work the same with smaller page sizes. But some limits are affected. The maximum record size is proportionately less with smaller pages. Record length limits are calculated within InnoDB based on a variety of factors including row type, column type and length, number of columns, secondary indexes, index prefix lengths, and of course, the page size. The main record is stored in a clustered index and a minimum of two records must fit into each page. So the maximum record length for 8k pages is about half that of 16k pages and the maximum record size with 4k pages is about half that of 8k pages.</p>
<p>In addition to record lengths, the maximum key lengths are proportionately smaller. For 16k pages, MySQL prevents key definitions from containing over 3072 bytes of data. This means that the primary key in the clustered index cannot use more than 3072 bytes of data. Secondary indexes can only contain up to 3072 bytes of data in the key also. But within a secondary index, InnoDB must store the primary key as the record pointer.  So if you have a 3072 byte primary key and a 3072 byte secondary key, each entry in the secondary index contains 6144 bytes of data plus internal record overhead. The amount of internal overhead is dependent upon the column types, but this gets the secondary record close to half the page size which is its natural limit. So this limit of 3072 bytes per key is less than but close to what InnoDB would have to impose on a table by table basis.  Based on that, InnoDB now reports to MySQL that any key defined for 8k page sizes must be less than 1536 bytes.  Likewise, the maximum key length when InnoDB uses 4k page sizes is 768 bytes.</p>
<p>If you have a database schema with any large records or keys defined, you may not be able to use smaller page sizes. Even if your records do barely fit in the clustered index page, it may not be advisable to use these smaller pages because the btree will be a lot deeper.  For example, if only 2 records fit on the page and there are 1,000,000 records, leaf pages are 20 levels deep, meaning InnoDB will need to read 20 pages to find the leaf page.  If that were on 4k pages, then using the same table on 16k pages would give 8 records per page and the leaf pages would only be 7 levels down.</p>
<p>There is a trick to reducing the size of records on the clustered index page;<br />
1) Use Dynamic or Compressed row format.<br />
2) Convert VARCHAR fields to TEXT fields.  (VARBINARY can be converted to BLOB)</p>
<p>There are 4 ROW FORMATS in InnoDB. The first two, Redundant and Compact, which are considered the Antelope file version, store at least 768 bytes of each field in the clustered record.  The Barracuda file version consists of Compact and Dynamic ROW FORMATS. These have the ability to put all of a VARCHAR, VARBINARY, TEXT or BLOB field onto a separate BLOB page for storage.  So one good way to prepare a table structure to use smaller page sizes is to use Dynamic or Compressed row format.</p>
<p>The decision of how big a record will be in the clustered record is made during the INSERT or UPDATE.  Each record is evaluated for its own length.  If the record is too long to fit in half the page, InnoDB will look for the longest actual field in that record and put as much of that field off-page as possible based on the row type.  Then if it is still to long, it will shorten the longest field remaining.  Since this is done when the record is added to the page, different records may have different columns stored off-page when there are multiple long fields in the record.</p>
<p>VARCHAR/VARBINARY fields are treated like TEXT/BLOB fields if they are over 255 bytes long.  If you are using Compressed or Dynamic row format and your record is too long because you have too many VARCHAR fields 255 bytes or less, you can reduce the record length by converting them to TEXT fields. Likewise, VARBINARY fields 255 bytes or less can be converted to BLOB fields to take advantage of this ability to store the whole TEXT or BLOB field on a separate page.</p>
<p>A file extent in InnoDB is 1 Mb independent of the page size. So an extent will hold 64 16k pages, 128 8k pages and 256 4k pages.  This means that the read ahead mechanisms will read more pages with smaller page sizes since they read a whole extent at a time.  The doublewrite buffer, which is based on the size of an extent, will also contain more pages.</p>
<p>If you want to use smaller page sizes with existing data, export the data first with a logical export utility such as mysqldump. Then create the new mysql instance with innodb-page-size=4k or 8k and import the data. Do not use a physical export method such as alter table … discard tablespace.</p>
<p><strong>Summary:</strong></p>
<p>This feature makes it easier to try smaller page sizes in an InnoDB database. And with the 5.6.4 release, those smaller page sizes are fully supported by MySQL. Just export your data, move or delete the system database (ibdata1) and the log files (ib_logfile0 &amp; ib_logfile1), set innodb-page-size to either 4k or 8k, and restart MySQL. A new InnoDB instance will be created with the smaller page size. Then you can import your data and run your tests, all without recompiling InnoDB.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/12/innodb-5-6-4-supports-4k-8k-page-sizes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>InnoDB Memcached with Binlog Capability</title>
		<link>http://blogs.innodb.com/wp/2011/10/innodb-memcached-with-binlog-capability/</link>
		<comments>http://blogs.innodb.com/wp/2011/10/innodb-memcached-with-binlog-capability/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 22:23:54 +0000</pubDate>
		<dc:creator>Jimmy Yang</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1431</guid>
		<description><![CDATA[In our earlier Labs release, we presented a MySQL NoSQL solution through InnoDB Memcached Daemon Plugin (see earlier Calvin&#8217;s and my posts). That earlier release allows the Memcached Plugin directly interacting with InnoDB, completely bypassing MySQL optimizer and QP layers. It differs with another popular MySQL NoSQL solution, HandlerSocket, by skipping even the Handler API [...]]]></description>
			<content:encoded><![CDATA[<p>In our earlier Labs release, we presented a MySQL NoSQL solution through InnoDB Memcached Daemon Plugin (see earlier <a href="../2011/04/nosql-to-innodb-with-memcached/">Calvin&#8217;s</a> and <a href="../2011/04/get-started-with-innodb-memcached-daemon-plugin/">my</a> posts). That earlier release allows the Memcached Plugin directly interacting with InnoDB, completely bypassing MySQL optimizer and QP layers. It differs with another popular MySQL NoSQL solution, HandlerSocket, by skipping even the Handler API layer and directly access the InnoDB through InnoDB APIs. Thus, in theory, it would be simpler and more efficient.</p>
<p>However, there is one major functionality we did not implement in the first release: the replication (binlog) capability. And this important feature is being done in the latest labs release (mysql-5.6.4-labs-innodb-memcached), in which all memcached commands are now supported for binlogging.</p>
<p>In the following sections, we will quick walk you through the prototype and show how to use the binlog capability.</p>
<p><span style="font-size: medium;"><strong>Set up the InnoDB Memcached:</strong></span></p>
<p>Our earlier post (<a href="../2011/04/get-started-with-innodb-memcached-daemon-plugin/">Get started with InnoDB Memcached Daemon plugin)</a> details the step to set up the InnoDB Memcached. We will go very briefly on some important steps here:<span id="more-1431"></span></p>
<ul>
<li><strong>Copy the plugins to the plugin directory</strong><em></em><em></em></li>
</ul>
<p><em></em><em>       </em>Find out your plugin directory:</p>
<p><span><span style="font-size: small;"><em>        mysql&gt; select @@plugin_dir;</em></span></span></p>
<dl>
<dd>
<table width="362" border="1" cellspacing="0" cellpadding="4">
<colgroup>
<col width="256*" /></colgroup>
<tbody>
<tr>
<td valign="TOP" width="100%"><span><span style="font-size: small;"><em>@@plugin_dir </em></span></span></td>
</tr>
<tr>
<td valign="TOP" width="100%"><span><span style="font-size: small;"><em>/home/jy/work2/mysql-5.6-memcached-labs/lib/plugin</em></span></span></td>
</tr>
</tbody>
</table>
</dd>
</dl>
<p>       After you download and unzipped mysql-5.6.4-labs-innodb-memcached-linux2.6-i686.tar.gz,</p>
<p>in the lib/plugin directory, you will find two plugin share lib:</p>
<p><em>       </em>1) innodb_engine.so</p>
<p><em>       </em>2) libmemcached.so</p>
<p><em>       </em>Copy them to your plugin directory:</p>
<p><span><span style="font-size: small;"><em></em><em>       shell &gt; cp mysql-5.6.4-labs-innodb-memcached-linux2.6-i686/lib/plugin/innodb_engine.so /home/jy/work2/mysql-5.6-memcached-labs/lib/plugin</em></span></span></p>
<p><em><span style="font-size: small;">       shell &gt; cp mysql-5.6.4-labs-innodb-memcached-linux2.6-i686/lib/plugin/libmemcached.so /home/jy/work2/mysql-5.6-memcached-labs/lib/plugin</span></em></p>
<ul>
<li><strong>Install the </strong><strong></strong><strong>c</strong><strong>onfiguration tables:</strong></li>
</ul>
<p><em>       </em>In the scripts/ directory, find the configuration scripts: innodb_memcached_config.sql, and install it:</p>
<p><span style="font-size: small;"><em>      mysql &lt; scripts/nnodb_memcached_config.sql</em></span></p>
<ul>
<li><strong>Install the Daemon Plugin</strong></li>
</ul>
<p><strong>      </strong>Now install the daemon plugin:</p>
<p><span style="font-size: small;"><em>       mysql&gt; install plugin daemon_memcached soname &#8216;libmemcached.so&#8217;; </em></span></p>
<p><span style="font-size: small;"><em>      Query OK, 0 rows affected (0.05 sec)</em></span></p>
<p><span style="font-size: medium;"><strong>Enable InnoDB Memcached binlog with &#8220;innodb_direct_access_enable_binlog&#8221;:</strong></span></p>
<ul>
<li>One new system configuration option &#8211; &#8220;innodb_direct_access_enable_binlog&#8221; is added to enable the InnoDB Memcached binlog. This configure option is a Server Boot-time option, so you must turn it on at server start up time. In addition, you must enable MySQL binlog with the &#8211;log-bin option. You can add these option to your server configure file my.cnf or just add these at command line.</li>
</ul>
<p><span><span style="font-size: small;"><em></em>      <em> mysqld …. &#8211;log-bin –innodb_direct_access_enable_binlog=1</em></span></span></p>
<ul>
<li>Then you need to configure your master and slave server, you can follow the guidance from the manual to <a href="http://dev.mysql.com/doc/refman/5.6/en/replication-howto.html">set up the replication for MySQL, </a></li>
</ul>
<ul>
<li>Use mysqldump to create a master data snapshot, and sync it to slave.</li>
</ul>
<p><span><span style="font-size: small;"><em></em>       <em>master shell &gt; mysqldump &#8211;all-databases &#8211;lock-all-tables &gt; dbdump.db</em></span></span></p>
<p><em><span style="font-size: small;">        slave shell &gt; mysql &lt; dbdump.db</span></em><code></code></p>
<ul>
<li>In Master, call “show master status” to obtain Master Binary Log Coordinates</li>
</ul>
<p><span><span style="font-size: x-small;"><em></em><em>       mysql&gt; show master status; </em></span></span></p>
<dl>
<dd>
<table width="328" border="1" cellspacing="0" cellpadding="4">
<colgroup>
<col width="47*" />
<col width="64*" />
<col width="67*" />
<col width="78*" /></colgroup>
<tbody>
<tr valign="TOP">
<td width="18%"><em><span style="font-size: x-small;">File</span></em></td>
<td width="25%"><em><span style="font-size: x-small;">Position</span></em></td>
<td width="26%"><em><span style="font-size: x-small;">Binlog_Do_DB</span></em></td>
<td width="31%"><em><span style="font-size: x-small;">Binlog_Ignore_DB </span></em></td>
</tr>
<tr valign="TOP">
<td width="18%"><em><span style="font-size: x-small;">0</span></em></td>
<td width="25%"><em><span style="font-size: x-small;">114</span></em></td>
<td width="26%"></td>
<td width="31%"></td>
</tr>
</tbody>
</table>
</dd>
</dl>
<p><span><span style="font-size: x-small;"><em></em><em>       </em>1 row in set (0.00 sec)</span></span></p>
<ul>
<li><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;">In Slave, use “change master to” to set up slave with above coordinates:</span></span></li>
</ul>
<p><span><span style="font-size: x-small;"><em>         mysql&gt; CHANGE MASTER TO </em></span></span></p>
<p><span><span style="font-size: x-small;"><em>                 MASTER_HOST=&#8217;localhost&#8217;, </em></span></span></p>
<p><span><span style="font-size: x-small;"><em>                 MASTER_USER=&#8217;root&#8217;, </em></span></span></p>
<p><span><span style="font-size: x-small;"><em>                 MASTER_PASSWORD=&#8221;, </em></span></span></p>
<p><span><span style="font-size: x-small;"><em>                MASTER_PORT = 13000, </em></span></span></p>
<p><span><span style="font-size: x-small;"><em>                MASTER_LOG_FILE=&#8217;0.000001, </em></span></span></p>
<p><span><span style="font-size: x-small;"><em>                MASTER_LOG_POS=114;</em></span></span></p>
<ul>
<li>Then start the slave:</li>
</ul>
<p><span><em></em>       <em>mysql&gt;start slave</em></span><em><code>;</code></em></p>
<p><code></code><br />
If the errolog prints following info, then the slave is ready for the replication:</p>
<p><span><span style="font-size: x-small;"><em>111002 18:47:15 [Note] Slave I/O thread: connected to master &#8216;root@localhost:13000&#8242;,replication started in log &#8217;0.000001&#8242; at position 114 </em></span></span></p>
<p><span style="font-size: medium;"><strong>Test with memcached telnet interfaces:</strong></span></p>
<p>Now let&#8217;s test the server with above replication setup. We use the memcached telnet interface for demonstration purpose. And we also connect to the master and slave server through SQL interfaces, and query the target table to verify the result.</p>
<p>In our configuration setup sql, one example table “demo_test” is created in the “test” database to take the memcached command by default. And we will use this default table for the demonstrations:</p>
<p>&nbsp;</p>
<ul>
<li>
<p align="JUSTIFY">Use set to insert a record, key “test1”, value “t1” and flag is “10”:</p>
</li>
</ul>
<p><span><span style="font-size: small;"><em>       telnet 127.0.0.1 11211</em></span></span></p>
<p><span><span style="font-size: small;"><em>       Trying 127.0.0.1&#8230; </em></span></span></p>
<p><span><span style="font-size: small;"><em>       Connected to 127.0.0.1. </em></span></span></p>
<p><span><span style="font-size: small;"><em>       Escape character is &#8216;^]&#8217;. </em></span></span></p>
<p><span><span style="font-size: small;"><em>       set test1 10 0 2 </em></span></span></p>
<p><span><span style="font-size: small;"><em>       t1</em></span></span></p>
<p><span><span style="font-size: small;"><em>       STORED </em></span></span></p>
<p><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;">         In the master server, you can see the row is inserted (c1 maps to the key, c2 maps to value, c3 is the flag, and c4 is the cas, c5 is the expiration):</span></span></p>
<p><span><span style="font-size: small;"><em>         mysql&gt; select * from demo_test; </em></span></span></p>
<dl>
<dd>
<table width="404" border="1" cellspacing="0" cellpadding="4">
<colgroup>
<col width="70*" />
<col width="67*" />
<col width="45*" />
<col width="38*" />
<col width="36*" /></colgroup>
<tbody>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">c1</span></em></td>
<td width="26%"><em><span style="font-size: small;">c2</span></em></td>
<td width="18%"><em><span style="font-size: small;">c3</span></em></td>
<td width="15%"><em><span style="font-size: small;">c4</span></em></td>
<td width="14%"><em><span style="font-size: small;">c5</span></em></td>
</tr>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">test1</span></em></td>
<td width="26%"><em><span style="font-size: small;">t1</span></em></td>
<td width="18%"><em><span style="font-size: small;">10</span></em></td>
<td width="15%"><em><span style="font-size: small;">2</span></em></td>
<td width="14%"><em><span style="font-size: small;">0</span></em></td>
</tr>
</tbody>
</table>
</dd>
</dl>
<p><span><span style="font-size: small;"><em>        1 row in set (0.00 sec) </em></span></span></p>
<p><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;">         In the slave server, you will see the same record is inserted by replication:</span></span></p>
<p><em><span style="font-size: small;">       mysql&gt; select * from demo_test; </span></em></p>
<dl>
<dd>
<table width="404" border="1" cellspacing="0" cellpadding="4">
<colgroup>
<col width="70*" />
<col width="67*" />
<col width="45*" />
<col width="38*" />
<col width="36*" /></colgroup>
<tbody>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">c1</span></em></td>
<td width="26%"><em><span style="font-size: small;">c2</span></em></td>
<td width="18%"><em><span style="font-size: small;">c3</span></em></td>
<td width="15%"><em><span style="font-size: small;">c4</span></em></td>
<td width="14%"><em><span style="font-size: small;">c5</span></em></td>
</tr>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">test1</span></em></td>
<td width="26%"><em><span style="font-size: small;">t1</span></em></td>
<td width="18%"><em><span style="font-size: small;">10</span></em></td>
<td width="15%"><em><span style="font-size: small;">2</span></em></td>
<td width="14%"><em><span style="font-size: small;">0</span></em></td>
</tr>
</tbody>
</table>
</dd>
</dl>
<p><span><span style="font-size: small;"><em>      1 row in set (0.00 sec) </em></span></span></p>
<ul>
<li><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;">Use set command to update the key “test1” to a new value “new”:</span></span></li>
</ul>
<p><span><span style="font-size: small;"><em></em>         <em>Connected to 127.0.0.1. </em></span></span></p>
<p><em><span style="font-size: small;">         Escape character is &#8216;^]&#8217;. </span></em></p>
<p><em><span style="font-size: small;">         set test1 10 0 3 </span></em></p>
<p><em><span style="font-size: small;">         new </span></em></p>
<p><em><span style="font-size: small;">         STORED </span></em></p>
<p><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;"><em>         </em>From the slave server, the update is replicated (notice the cas value also updated):</span></span></p>
<p><span><span style="font-size: small;"><em></em><em>         mysql&gt; select * from demo_test; </em></span></span></p>
<dl>
<dd>
<table width="395" border="1" cellspacing="0" cellpadding="4">
<colgroup>
<col width="70*" />
<col width="67*" />
<col width="45*" />
<col width="38*" />
<col width="36*" /></colgroup>
<tbody>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">c1</span></em></td>
<td width="26%"><em><span style="font-size: small;">c2</span></em></td>
<td width="18%"><em><span style="font-size: small;">c3</span></em></td>
<td width="15%"><em><span style="font-size: small;">c4</span></em></td>
<td width="14%"><em><span style="font-size: small;">c5</span></em></td>
</tr>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">test1</span></em></td>
<td width="26%"><em><span style="font-size: small;">new</span></em></td>
<td width="18%"><em><span style="font-size: small;">10</span></em></td>
<td width="15%"><em><span style="font-size: small;">3</span></em></td>
<td width="14%"><em><span style="font-size: small;">0</span></em></td>
</tr>
</tbody>
</table>
</dd>
</dl>
<p><span><span style="font-size: small;"><em></em>       <em>  1 row in set (0.00 sec) </em></span></span></p>
<ul>
<li><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;">Delete the record with delete command:</span></span></li>
</ul>
<p><span><span style="font-size: small;"><em></em>         <em>Connected to 127.0.0.1. </em></span></span></p>
<p><em><span style="font-size: small;">         Escape character is &#8216;^]&#8217;. </span></em></p>
<p><em><span style="font-size: small;">         delete test1 </span></em></p>
<p><em><span style="font-size: small;">         DELETED</span></em></p>
<p>&nbsp;</p>
<p><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;"><em>         </em>The delete is replicated to the slave, the record in slave is also deleted:</span></span></p>
<p><span><span style="font-size: small;"><em></em>       <em>  mysql&gt; select * from demo_test; </em></span></span></p>
<p><em><span style="font-size: small;">         Empty set (0.00 sec) </span></em></p>
<ul>
<li><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;">Truncated the table with the “flush all” command</span></span></li>
</ul>
<p><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;"><em>         </em>First insert two records:</span></span></p>
<p><span><span style="font-size: small;"><em></em>         <em>Connected to 127.0.0.1. </em></span></span></p>
<p><em><span style="font-size: small;">         Escape character is &#8216;^]&#8217;</span></em></p>
<p><em><span style="font-size: small;">         set test2 10 0 5 </span></em></p>
<p><em><span style="font-size: small;">         again </span></em></p>
<p><em><span style="font-size: small;">         STORED </span></em></p>
<p><em><span style="font-size: small;">         set test3 10 0 6 </span></em></p>
<p><span><span style="font-size: small;"><em></em>        <em> again1 </em></span></span></p>
<p><em><span style="font-size: small;">         STORED </span></em></p>
<p><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;"><em>         </em>In the slave server, there two records replicated:</span></span></p>
<p><span><span style="font-size: small;"><em></em>         <em>mysql&gt; select * from demo_test; </em></span></span></p>
<dl>
<dd>
<table width="404" border="1" cellspacing="0" cellpadding="4">
<colgroup>
<col width="70*" />
<col width="67*" />
<col width="45*" />
<col width="38*" />
<col width="36*" /></colgroup>
<tbody>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">c1</span></em></td>
<td width="26%"><em><span style="font-size: small;">c2</span></em></td>
<td width="18%"><em><span style="font-size: small;">c3</span></em></td>
<td width="15%"><em><span style="font-size: small;">c4</span></em></td>
<td width="14%"><em><span style="font-size: small;">c5</span></em></td>
</tr>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">test2</span></em></td>
<td width="26%"><em><span style="font-size: small;">again</span></em></td>
<td width="18%"><em><span style="font-size: small;">10</span></em></td>
<td width="15%"><em><span style="font-size: small;">5</span></em></td>
<td width="14%"><em><span style="font-size: small;">0</span></em></td>
</tr>
<tr valign="TOP">
<td width="27%"><em><span style="font-size: small;">test3</span></em></td>
<td width="26%"><em><span style="font-size: small;">again1</span></em></td>
<td width="18%"><em><span style="font-size: small;">10</span></em></td>
<td width="15%"><em><span style="font-size: small;">6</span></em></td>
<td width="14%"><em><span style="font-size: small;">0</span></em></td>
</tr>
</tbody>
</table>
</dd>
</dl>
<p><span><span style="font-size: small;"><em></em>         <em>2 rows in set (0.00 sec) </em></span></span></p>
<p><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;"><em>         </em>Call “flush_all” in telnet interface to truncate the table:</span></span></p>
<p><span><span style="font-size: small;"><em>         Connected to 127.0.0.1. </em></span></span></p>
<p><em><span style="font-size: small;">         Escape character is &#8216;^]&#8217;. </span></em></p>
<p><em><span style="font-size: small;">         flush_all </span></em></p>
<p><em><span style="font-size: small;">         OK </span></em></p>
<p><span style="font-family: Nimbus Roman No9 L,serif;"><span style="font-size: small;"><em>         </em>Then check the slave server, the truncate table is replicated:</span></span></p>
<p><span><span style="font-size: small;"><em></em>      <em>   mysql&gt; select * from demo_test; </em></span></span></p>
<p><em><span style="font-size: small;">         Empty set (0.00 sec) </span></em></p>
<p>In short, all memcached commands are supported in terms of replication. And we would not enumerate each of them here.</p>
<p><strong>Notes for the InnoDB Memcached Binlog:</strong></p>
<p>Binlog Format:</p>
<ul>
<li>Most Memcached operations are mapped to DMLs (insert/delete/update), and since there is no actually &#8220;statement&#8221; comes through memcached, all memcached commands (except for flush_all) use Row Based (RBR) logging. This is independent of any server binlog_format stetting.</li>
<li>The Memcached &#8220;flush_all&#8221; command is mapped to &#8220;truncate table&#8221; command. Since &#8220;DDL&#8221; type commands can only use statement-based logging, this &#8220;flush_all&#8221; command is replicated with a &#8220;hand-crafted&#8221; &#8220;truncate table&#8221; statement.</li>
</ul>
<p>Transactions:</p>
<ul>
<li>The transaction concept is not well defined when coming to Memcached. We use &#8220;daemon_memcached_r_batch_size&#8221; and &#8220;daemon_memcached_w_batch_size&#8221; to control the read and write &#8220;transaction&#8221; batch size for performance consideration. However, for replication, each command is replicated right after successful completion of each command.</li>
<li>In this release, we adjusted the default value of &#8220;daemon_memcached_w_batch_size&#8221; from 32 to 1, so each Memcached “write” operation are directly committed (it used to commit every 32 operations). This is to avoid any confusion that records shows up in slave server while they can&#8217;t be seen from master server without turning on “set transaction isolation level read uncommitted” to view uncommitted records. The side effect of this reduced is certain degradation of performance.</li>
</ul>
<p>Other minor updates:</p>
<ul>
<li>The memcached used has upgraded to the latest 1.6.0 (beta 1). And the libevent used for memcached has been updated to version 1.4.12.</li>
<li>InnoDB memcached now supports on Linux, Solaris and OSX platforms.</li>
</ul>
<p><strong>Summary:</strong></p>
<p>In this release, we added the binlog support for InnoDB Memcached Daemon Plugins. This is an important feature to allow any updates through the memcached interface being able to be replicated for backup and high availability. More importantly, this demonstrate the capability of InnoDB APIs,  which not only support direct access to the InnoDB storage, but also being able to backup  any of such operations.</p>
<table width="11" border="0" cellspacing="0" cellpadding="2">
<colgroup>
<col width="5" /></colgroup>
<tbody>
<tr>
<td width="5" height="21"></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/10/innodb-memcached-with-binlog-capability/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>InnoDB at Oracle OpenWorld</title>
		<link>http://blogs.innodb.com/wp/2011/09/innodb-at-oracle-open-world/</link>
		<comments>http://blogs.innodb.com/wp/2011/09/innodb-at-oracle-open-world/#comments</comments>
		<pubDate>Wed, 28 Sep 2011 21:58:59 +0000</pubDate>
		<dc:creator>Calvin Sun</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1425</guid>
		<description><![CDATA[Sunny and I will be presenting at the Oracle OpenWorld next week: Introduction to InnoDB, MySQL&#8217;s Default Storage Engine,  10/04/11 Tuesday 01:15 PM,   Marriott Marquis &#8211; Golden Gate C3,     Calvin Sun InnoDB Performance Tuning,  10/04/11 Tuesday  03:30 PM,   Marriott Marquis &#8211; Golden Gate C2,   Sunny Bains The first session is [...]]]></description>
			<content:encoded><![CDATA[<p>Sunny and I will be presenting at the Oracle OpenWorld next week:</p>
<ul>
<li>Introduction to InnoDB, MySQL&#8217;s Default Storage Engine,  10/04/11 Tuesday 01:15 PM,   Marriott Marquis &#8211; Golden Gate C3,     Calvin Sun</li>
<li>InnoDB Performance Tuning,  10/04/11 Tuesday  03:30 PM,   Marriott Marquis &#8211; Golden Gate C2,   Sunny Bains</li>
</ul>
<p>The first session is for beginners, who are new to InnoDB and MySQL. The second session will cover many new performance features in MySQL 5.5 and 5.6, and share some tuning tips to maximize MySQL performance.</p>
<p>What to learn more about MySQL? There will be <a title="Focus on MySQL" href="http://www.oracle.com/openworld/oow11-focuson-mysql-486114.pdf">something for everyone</a>. Come to join us!</p>
<p><img src="data:image/png;base64,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" alt="" /></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/09/innodb-at-oracle-open-world/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>InnoDB 2011 Summer Labs Releases</title>
		<link>http://blogs.innodb.com/wp/2011/07/innodb-2011-summer-labs-releases/</link>
		<comments>http://blogs.innodb.com/wp/2011/07/innodb-2011-summer-labs-releases/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 16:08:18 +0000</pubDate>
		<dc:creator>Calvin Sun</dc:creator>
				<category><![CDATA[Feature]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[labs release]]></category>
		<category><![CDATA[MySQL 5.6]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1137</guid>
		<description><![CDATA[In April of 2011, InnoDB team published the early access of NoSQL to InnoDB with memcached, plus several new features as part of MySQL 5.6.2 milestone release. This week, we announced additional early access to new InnoDB features for the community to test, and provide feedback. There are two release packages from InnoDB team on [...]]]></description>
			<content:encoded><![CDATA[<p>In April of 2011, InnoDB team published the early access of <a href="http://blogs.innodb.com/wp/2011/04/get-started-with-innodb-memcached-daemon-plugin/">NoSQL to InnoDB with memcached</a>, plus several new features as part of <a href="http://blogs.oracle.com/MySQL/entry/top_features_in_mysql_562_development_milestone_release">MySQL 5.6.2 milestone release</a>. This week, we announced additional early access to new InnoDB features for the community to test, and provide feedback.</p>
<p>There are two release packages from InnoDB team on <a href="http://labs.mysql.com/">MySQL Labs</a>: InnoDB full-text search, and InnoDB new features.</p>
<h4>InnoDB Full-Text Search</h4>
<p>MySQL 5.5 makes InnoDB the default storage engine, so everyone can benefit from ACID-compliant transactions, referential integrity, crash recovery.  However, some users need InnoDB to have built-in full-text search, similar to MyISAM&#8217;s full-text search.</p>
<p>InnoDB full-text search provides users with the ability to build full text indices and search for specific text-based content stored in InnoDB tables.  This new functionality supports fast and accurate search on document content using natural language, boolean, wildcard, and proximity search.</p>
<p><span id="more-1137"></span></p>
<p>The design and implementation of InnoDB full-text search can trace back to 2005, when Osku Salerma detailed the design in his master thesis &#8220;<a href="http://www.oskusoft.com/osku/publications.html">Design of a Full Text Search index for a database management system</a>&#8220;. Later, Sunny Bains and Jimmy Yang from the InnoDB team took over the development and made major contributions to this important feature.</p>
<p>Jimmy gave an <a href="http://blogs.innodb.com/wp/2011/07/overview-and-getting-started-with-innodb-fts/">overview of InnoDB full-text search</a>, and the <a href="http://blogs.innodb.com/wp/2011/07/difference-between-innodb-fts-and-myisam-fts/">main differences in design between InnoDB full-text search and MyISAM full-text search</a>. John provided a set of examples in the <a href="http://blogs.innodb.com/wp/2011/07/innodb-full-text-search-tutorial/">tutorial</a>. What about the performance of InnoDB full-text search, you can find out in <a href="http://blogs.innodb.com/wp/2011/07/innodb-fts-performance/">Vinay and Jimmy&#8217;s article</a>.</p>
<p>Please download mysql-5.6-labs-innodb-fts from <a href="http://labs.mysql.com/">MySQL Labs</a> and give a try.</p>
<h4>InnoDB New Features</h4>
<p>The package mysql-5.6-labs-innodb-features on <a href="http://labs.mysql.com/">MySQL Labs</a> consists of a set of InnoDB new features since MySQL 5.6.2 milestone release, except InnoDB full-text search. Some of the new features are already in MySQL server main development tree, and the rest of them are intended to move into the main development tree toward future development milestone releases and GA releases.</p>
<p>The new InnoDB features included in this package are:</p>
<ul>
<li>Increase the max size of redo log files from 4GB to 2TB</li>
<li>Reduce contention during file extension</li>
<li>Make deadlock detection non-recursive</li>
<li>Improve thread scheduling</li>
<li>Change rw-lock to mutex for trx_sys_t</li>
<li>Option to preload InnoDB buffer pool</li>
<li>Allow UNDO logs to reside in their own tablespace</li>
<li>Reintroduce random readahead</li>
<li>Support smaller page sizes (4K &amp; 8K)</li>
<li>Increase the max length of prefix index from 767 bytes to 3072 bytes</li>
</ul>
<p>In additional to continue improvements of InnoDB performance and scalability, we are also focusing on optimizing InnoDB for flash drives. InnoDB with flash drives could benefit from new features such as larger REDO log files, separate UNDO logs, smaller page sizes, and preloaded buffer pool.</p>
<p>Group commit with binlog is released separately by MySQL replication team, also on <a href="http://labs.mysql.com/">MySQL Labs</a>.</p>
<p>Want to learn the details of InnoDB new features? Download mysql-5.6-labs-innodb-features from <a href="http://labs.mysql.com/">MySQL Labs</a>, play with it, and read the blogs from InnoDB engineers:</p>
<ul>
<li><a href="http://blogs.innodb.com/wp/2011/07/allow-undo-logs-to-reside-in-their-own-tablespace/">Allow UNDO logs to reside in their own tablespace</a> (Sunny)</li>
<li><a href="http://blogs.innodb.com/wp/2011/07/improve-innodb-thread-scheduling/">Improve InnoDB thread scheduling</a> (Sunny, Ranger)</li>
<li><a href="http://blogs.innodb.com/wp/2011/07/reintroducing-random-readahead-in-innodb/">Reintroducing Random Readahead in InnoDB</a> (Inaam)</li>
<li><a href="http://blogs.innodb.com/wp/2011/07/reduced-contention-during-datafile-extension/">Reduced contention during datafile extension</a> (Inaam)</li>
<li><a href="http://blogs.innodb.com/wp/2011/07/shortened-warm-up-times-with-a-preloaded-innodb-buffer-pool/">Shortened warm-up times with a preloaded InnoDB buffer pool</a> (Vasil)</li>
<li><a href="http://blogs.innodb.com/wp/2011/07/innodb-databases-with-4k-and-8k-page-sizes/">Create InnoDB databases with 4k and 8k page sizes without recompiling</a> (Kevin)</li>
</ul>
<p>BTW, do not forget to send us feedback. Thanks for being interested in InnoDB!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/07/innodb-2011-summer-labs-releases/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>InnoDB Full-Text Search Performance</title>
		<link>http://blogs.innodb.com/wp/2011/07/innodb-fts-performance/</link>
		<comments>http://blogs.innodb.com/wp/2011/07/innodb-fts-performance/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 12:07:23 +0000</pubDate>
		<dc:creator>Vinay</dc:creator>
				<category><![CDATA[InnoDB FTS]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1052</guid>
		<description><![CDATA[Long awaited InnoDB support for full-text index is available in InnoDB lab release. This post talks about the performance of InnoDB&#8217;s full-text support over MyISAM&#8217;s full-text support. (There are multiple aspect of full-text index performance, the most important ones are full-text index creation time and query execution time). We are not focusing on performance with [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } -->Long awaited InnoDB support for full-text index is available in InnoDB lab release. This post talks about the performance of InnoDB&#8217;s full-text support over MyISAM&#8217;s full-text support. (There are multiple aspect of full-text index performance, the most important ones are full-text index creation time and query execution time). We are not focusing on performance with &#8220;DML&#8221; (expect some simple insert on loaded data) and &#8220;other supported character sets&#8221; (numbers are based on latin1 char-set data).</p>
<p>Numbers are encouraging in terms of &#8216;create index&#8217;  time where InnoDB is comparable or faster than MyISAM. And query execution time are comparable with MyISAM. Over the time, we can expect optimization for query performance.</p>
<p>Please refer <a href="http://blogs.innodb.com/wp/2011/07/overview-and-getting-started-with-innodb-fts/" target="_blank"> &#8220;Overview and Getting Started with InnoDB FTS&#8221;</a> , <a href="http://blogs.innodb.com/wp/2011/07/innodb-full-text-search-tutorial/" target="_blank">&#8220;InnoDB Full-Text Search Tutorial&#8221;</a> , as this blog focuses on full-text search performance part.</p>
<p><strong>a) Full-Text Search Create Index Time</strong><br />
Full-text index creation time depend(s) on (the) number of words to be  indexed which is indirectly dependent on the length of word which you  want to index. By default , all words with length &gt;= 3 bytes get indexed  in InnoDB. (MyISAM default word length is 4).</p>
<p>When you are comparing &#8216;create index&#8217; time then just make sure MyISAM  and InnoDB are indexing the same number of words from the data.  InnoDB uses &#8220;InnoDB_ft_min_token_size&#8221; variable to set the minimum word  length. It is also dependent on max word length to be indexed but  it is generally not changed. Default stop-word list for InnoDB contain  less word than that of MyISAM stop-word list so it will index more word(s).</p>
<p><span id="more-1052"></span></p>
<p>Looking at InnoDB full-text search architecture details , it is clear that usage of  (user defined &#8220;FTS_DOC_ID&#8221;) column and server parameter  &#8220;InnoDB_ft_sort_pll_degree&#8221; (could affect performance)  help  to increase the performance. Let us see what do these parameter mean  so we will get an idea why they are used/tuned to get better performance.</p>
<p>1)<br />
InnoDB full-text search requires a monotonically increasing &#8220;Doc ID&#8221; column for  fulltext index. There is no requirement that user must add this column but InnoDB will add it automatically if the column is missing and  rebuild of unique/primary index. From performance point of view , its  good that user could pre-define this column saving rebuild of   index. As of now, it needs to be a 8 bytes unique non-null BIGINT  column and it must have the reserved name &#8220;FTS_DOC_ID&#8221; (all upper  case).</p>
<p>Example , User can  avoid a index rebuild by server , using  &#8220;FTS_DOC_ID&#8221; column when creating the table<br />
CREATE TABLE wp (<br />
FTS_DOC_ID BIGINT unsigned NOT NULL AUTO_INCREMENT,<br />
title varchar(255) NOT NULL DEFAULT &#8221;,<br />
text mediumtext NOT NULL,<br />
PRIMARY KEY (`FTS_DOC_ID`)<br />
) ENGINE=InnoDB DEFAULT CHARSET=latin1;</p>
<p>CREATE UNIQUE INDEX FTS_DOC_ID_INDEX on wp(FTS_DOC_ID);</p>
<p>Note: &#8220;FTS_DOC_ID&#8221; (reserved column name, all upper case) column and FTS_DOC_ID_INDEX  (reserved index name) are added. These two are used by InnoDB internally, if either is missing, InnoDB will create them for you.</p>
<p>If you are not in a hurry, and don&#8217;t want to manage your own Doc ID, then you can just create table as following. Subsequent &#8220;create fulltext index&#8221; call will do a rebuild on the table and add FTS_DOC_ID column as hidden column, and FTS_DOC_ID_INDEX on FTS_DOC_ID.<br />
CREATE TABLE wp (<br />
title varchar(255) NOT NULL DEFAULT &#8221;,<br />
text mediumtext NOT NULL,<br />
) ENGINE=InnoDB DEFAULT CHARSET=latin1;</p>
<p>2)<br />
InnoDB full-text search has tokenization and sort phases which are handled using  threads. &#8220;InnoDB_ft_sort_pll_degree&#8221; variable determine how many  parallel threads to use for tokenization and sorting. It has been  observed that &#8216;create index&#8217; is faster with large values of  InnoDB_ft_sort_pll_degree on multi-core machines.</p>
<p>Default value for &#8220;InnoDB_ft_sort_pll_degree&#8221; is 2 . This is a static  variable so it required to be set at server start-up time and it  will/can be moved as dynamic variable at later enhancement of InnoDB full-text search.<br />
* Use higher value for InnoDB_ft_sort_pll_degree ( it takes values  2,4,8,16,..)</p>
<p>Following Numbers are obtained with setup as</p>
<p>Schema: Table with number of words (as defined above)<br />
Index : (title, text) columns<br />
Data Size : Approx 2.7GB, 1 million row , 238 million word<br />
Platform: Linux x86 64 bit , 3Ghz , 8 cores , 32 GB RAM</p>
<p><strong>&#8216;Create Index&#8217; Performance</strong></p>
<table style="height: 72px" border="1" cellspacing="0" cellpadding="4" width="645">
<col width="51*"></col>
<col width="51*"></col>
<col width="51*"></col>
<col width="51*"></col>
<col width="51*"></col>
<tbody>
<tr valign="TOP">
<td width="20%"></td>
<td width="20%">Default</td>
<td width="20%">4</td>
<td width="20%">8</td>
<td width="20%">16</td>
</tr>
<tr valign="TOP">
<td width="20%">InnoDB</td>
<td width="20%">7 min 48.12</td>
<td width="20%">5 min 12.06</td>
<td width="20%">4 min 10.95</td>
<td width="20%">3 min 33.4</td>
</tr>
<tr valign="TOP">
<td width="20%">MyISAM</td>
<td width="20%">11min 42.57</td>
<td width="20%">11 min 32.27</td>
<td width="20%">11min 32.79</td>
<td width="20%">11 min 25.17</td>
</tr>
</tbody>
</table>
<p>Note: &#8220;innodb_ft_sort_pll_degree&#8221; do not affect myisam , hence &#8216;create index&#8217; time is almost same around 11 min.</p>
<p>One thing to note is that InnoDB full-text search create index use extensive merge sort. So on some system we see memory usage larger than expected, due to OS file system cache.  You can turn off such OS file system cache on Linux or Solaris by setting &#8220;innodb_disable_sort_file_cache&#8221; to TRUE, which enables direct I/O. However, doing such might hurt performance to the merge sort to some extent.</p>
<p>Its been observed that CPU utilization is in proportion to  &#8220;innodb_ft_sort_pll_degree&#8221; values. &#8216;Create index&#8217; in Innodb goes  through phases called tokenization, merge sort and insert . CPU  utilization is listed for each phase receptively along with Memory  utilization for default(2) value of innodb_ft_sort_pll_degree. ( Note:  CPU utilization values of different phases are snapshot values of that  phase).</p>
<table border="1" cellspacing="0" cellpadding="4" width="100%">
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<col width="23*"></col>
<tbody>
<tr valign="TOP">
<td width="9%">Variable</td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
</tr>
<tr valign="TOP">
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%">core 0</td>
<td width="9%">core 1</td>
<td width="9%">core 2</td>
<td width="9%">core 3</td>
<td width="9%">core 4</td>
<td width="9%">core 5</td>
<td width="9%">core 6</td>
<td width="9%">core 7</td>
</tr>
<tr valign="TOP">
<td width="9%">Default(2)</td>
<td width="9%">CPU (%)</td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
</tr>
<tr valign="TOP">
<td width="9%"></td>
<td width="9%"></td>
<td width="9%">Tokenization</td>
<td width="9%">0</td>
<td width="9%">0</td>
<td width="9%">0</td>
<td width="9%">0</td>
<td width="9%">96.97</td>
<td width="9%">0</td>
<td width="9%">0</td>
<td width="9%">97.11</td>
</tr>
<tr valign="TOP">
<td width="9%"></td>
<td width="9%"></td>
<td width="9%">Merge Sort</td>
<td width="9%">20.23</td>
<td width="9%">0</td>
<td width="9%">0</td>
<td width="9%">1</td>
<td width="9%">0</td>
<td width="9%">46.56</td>
<td width="9%">0</td>
<td width="9%">1</td>
</tr>
<tr valign="TOP">
<td width="9%"></td>
<td width="9%"></td>
<td width="9%">Insert Data</td>
<td width="9%">26</td>
<td width="9%">24.14</td>
<td width="9%">36.14</td>
<td width="9%">28.14</td>
<td width="9%">37</td>
<td width="9%">36.68</td>
<td width="9%">39.7</td>
<td width="9%">31</td>
</tr>
<tr valign="TOP">
<td width="9%"></td>
<td width="9%">Memory (%)</td>
<td width="9%">5.8%  across all core</td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
<td width="9%"></td>
</tr>
</tbody>
</table>
<p>(Variable = innodb_ft_sort_pll_degree )</p>
<p>Above scenario when repeated with utf8 character-set on table also  showed improvement in &#8216;create index&#8217; time with increased values of   innodb_ft_sort_pll_degree. Insertion of 100 records on top of 1M record  was faster for Innodb than MyISAM. InnoDB inserted 100 records in 10  millisec where as MyISAM took 30 millisec.</p>
<p><strong>b) Query Execution Time With Full-text Index</strong><br />
In this section, we briefly go over the execution time of some typical full-text search queries:</p>
<p>Queries used are :<br />
1) select count(*) from wp where match(title,text) against  (&#8216;Creationist +Abrahamic -creationism&#8217; in boolean mode);<br />
2) select count(*) from wp where match(title,text) against (&#8216;Abrahamic&#8217;);<br />
3) select count(*) from wp where match(title,text) against  (&#8216;preassumtions +orangutan&#8217; in boolean mode);<br />
4) select count(*) from wp where match(title,text) against (&#8216;orangutan  +falsified ~naturalistically&#8217; in boolean mode);<br />
5) select count(*) from wp where match(title,text) against (&#8216;+india*  -leader +gandh*&#8217; in boolean mode);<br />
6) select count(*) from wp where match(title,text) against (&#8216;&#8221;american  culture&#8221;@09&#8242; in boolean mode);<br />
<!-- 		@page { margin: 0.79in } 		TD P { margin-bottom: 0in } 		P { margin-bottom: 0.08in } --></p>
<table style="height: 155px" border="1" cellspacing="0" cellpadding="4" width="664">
<col width="64*"></col>
<col width="64*"></col>
<col width="64*"></col>
<col width="64*"></col>
<tbody>
<tr valign="TOP">
<td width="25%">Query</td>
<td width="25%">InnoDB (ms)</td>
<td width="25%">* InnoDB FTS Search Processing Time</td>
<td width="25%">MyISAM (ms)</td>
</tr>
<tr valign="TOP">
<td width="25%">1</td>
<td width="25%">10</td>
<td width="25%">2</td>
<td width="25%">10</td>
</tr>
<tr valign="TOP">
<td width="25%">2</td>
<td width="25%">130</td>
<td width="25%">1</td>
<td width="25%">10</td>
</tr>
<tr valign="TOP">
<td width="25%">3</td>
<td width="25%">1</td>
<td width="25%">1</td>
<td width="25%">10</td>
</tr>
<tr valign="TOP">
<td width="25%">4</td>
<td width="25%">2</td>
<td width="25%">2</td>
<td width="25%">10</td>
</tr>
<tr valign="TOP">
<td width="25%">5</td>
<td width="25%">320</td>
<td width="25%">116</td>
<td width="25%">1000</td>
</tr>
<tr valign="TOP">
<td width="25%">6 (New InnoDB Feature)</td>
<td width="25%">5250</td>
<td width="25%"></td>
<td width="25%">NA</td>
</tr>
</tbody>
</table>
<p><!--   		BODY,DIV,TABLE,THEAD,TBODY,TFOOT,TR,TH,TD,P { font-family:"Liberation Sans"; font-size:x-small } --><br />
* FTS Search processing time is the actual time spend by InnoDB full-text index scan.</p>
<p>There are still activities going to to synchronize the MySQL Optimizer and QP to the InnoDB FTS, so some queries types are not yet fully tuned. So there are further rooms to improve for various queries.</p>
<dl>
<dd> </dd>
</dl>
<p><strong>Summary:</strong></p>
<p>We see &#8216;create index&#8217; performance scale well align with the number of parallel degree and overall comparable performance with MyISAM in terms of query execution time.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/07/innodb-fts-performance/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>InnoDB Full-Text Search Tutorial</title>
		<link>http://blogs.innodb.com/wp/2011/07/innodb-full-text-search-tutorial/</link>
		<comments>http://blogs.innodb.com/wp/2011/07/innodb-full-text-search-tutorial/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 00:03:55 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Feature]]></category>
		<category><![CDATA[InnoDB FTS]]></category>
		<category><![CDATA[5.6]]></category>
		<category><![CDATA[fts]]></category>
		<category><![CDATA[search]]></category>

		<guid isPermaLink="false">http://blogs.innodb.com/wp/?p=1115</guid>
		<description><![CDATA[The InnoDB full-text search capability is an exciting feature. The full-text search itself is generally useful to have in an RDBMS. If an application is using all InnoDB tables except for one that is used for full-text searches, now that last table can be switched to InnoDB. If putting the full-text data in a MyISAM [...]]]></description>
			<content:encoded><![CDATA[<p>
The InnoDB full-text search capability is an exciting feature. The full-text search itself is generally useful to have in an RDBMS. If an application is using all InnoDB tables except for one that is used for full-text searches, now that last table can be switched to InnoDB. If putting the full-text data in a MyISAM table led to scalability problems, duplication, or a less-than-ideal schema design, now those issues can be addressed.
</p>
<p>
In this post, I&#8217;ll take you through some of the basics of setting up and querying an InnoDB <code>FULLTEXT</code> search index. I&#8217;ll leave the scalability and performance aspects to <a href="http://blogs.innodb.com/wp/2011/07/overview-and-getting-started-with-innodb-fts/">Jimmy&#8217;s</a> and <a href="http://blogs.innodb.com/wp/2011/07/innodb-fts-performance/">Vinay&#8217;s</a> blog posts, and just use some toy-sized data for demonstration purposes.
</p>
<h3>Creating a Table with a Full-Text Search Index</h3>
<p>
The key component of this feature is an index of type <code>FULLTEXT</code>, applied to one or more columns of an InnoDB table.
</p>
<p>
In <a href="http://blogs.innodb.com/wp/2011/07/overview-and-getting-started-with-innodb-fts/">Jimmy&#8217;s post</a>, he mentions some scalability considerations where you might create the table (including a special <code>FTS_DOC_ID</code> column), load the data, then create the <code>FULLTEXT</code> index afterward. For simplicity (and since the data volume is so small), I&#8217;ll create the table with the index in place, then load the data afterward.
</p>
<p><span id="more-1115"></span></p>
<pre>
use test;
-- We will do some commits and rollbacks to demonstrate transactional features.
-- So turn off the default setting that commits immediately after each statement.
set autocommit=0;

drop table if exists quotes;
-- The InnoDB full-text search feature in the 5.6 Labs release
-- lets us define the FULLTEXT index on an InnoDB table.
-- The ENGINE=INNODB clause is just to illustrate the InnoDB aspect.
-- In 5.5 and above, new tables use InnoDB by default.

create table quotes
  (    id int unsigned auto_increment primary key
    , author varchar(64)    , quote varchar(4000)
    , source varchar(64)
    , fulltext(quote)
  ) engine=innodb;

-- Get some words and phrases to search for into the table.
insert into quotes (author, quote, source) values
  ('Abraham Lincoln', 'Fourscore and seven years ago...',
  'Gettysburg Address')
, ('George Harrison', 'All those years ago...',
  'Live In Japan')
, ('Arthur C. Clarke', 'Then 10 years ago the monolith was discovered.',
  '2010: The Year We Make Contact')
, ('Benjamin Franklin',
  'Early to bed and early to rise, makes a man healthy, wealthy, and wise.',
  'Poor Richard''s Almanack')
, ('James Thurber',
  'Early to rise and early to bed makes a male healthy and wealthy and dead.',
  'The New Yorker')
, ('K', '1500 hundred years ago, everybody knew that the Earth was the center of the universe.',
  'Men in Black')
;

-- Since this is an InnoDB table, we are mindful of transactions.
commit;
</pre>
<h3>Word and Phrase Search &#8211; Natural Language Mode</h3>
<p>
Once the data is loaded <i>and committed</i>, you can run queries using the <code>MATCH(<em>columns</em>) AGAINST (<em>search expression</em>)</code> operator to do the actual searches. You can combine this operator with all the usual <code>WHERE</code> and similar clauses in the <code>SELECT</code> statement.
</p>
<p>
The simplest kind of search is to find a single word, or a phrase with all words in exact order. For this type of search, use the <code>IN NATURAL LANGUAGE</code> clause inside the <code>AGAINST()</code> call. This technique typically involves a user-entered string that you pass verbatim to the query (of course, after escaping any quotation marks or other special characters to prevent SQL injection attacks).
</p>
<pre>
-- Search for a single word.
select author as "Monolith" from quotes
  where match(quote) against ('monolith' in natural language mode);
+------------------+
| Monolith         |
+------------------+
| Arthur C. Clarke |
+------------------+
1 row in set (0.01 sec)

-- Unlike with MyISAM full-text search, the default minimum
-- length is 3 rather than 4, and the search returns words that
-- appear in a high proportion of the table rows.
select author as "Ago" from quotes
  where match(quote) against ('ago' in natural language mode);
+------------------+
| Ago              |
+------------------+
| Abraham Lincoln  |
| George Harrison  |
| Arthur C. Clarke |
| K                |
+------------------+
4 rows in set (0.00 sec)
</pre>
<h3>AND / OR / NOT Operators &#8211; Boolean Mode</h3>
<p>
For more complicated searches, you can have multiple words and phrases and search for different combinations of optional and required terms, not necessarily in the same order. This technique typically involves several data values that you query from elsewhere, or splitting apart a user-entered string and applying your own rules to the words and phrases inside.
</p>
<pre>
-- Search for a combination of words, not in the same order as the original.
select author as "Ago and Years" from quotes
  where match(quote) against ('+ago +years' in boolean mode);
+------------------+
| Ago and Years    |
+------------------+
| Abraham Lincoln  |
| George Harrison  |
| Arthur C. Clarke |
| K                |
+------------------+
4 rows in set (0.00 sec)

-- Search for other Boolean combinations of words.
select author as "Fourscore or Monolith" from quotes
  where match(quote) against ('fourscore monolith' in boolean mode);
+-----------------------+
| Fourscore or Monolith |
+-----------------------+
| Abraham Lincoln       |
| Arthur C. Clarke      |
+-----------------------+
2 rows in set (0.00 sec)

select author as "Years and not Monolith" from quotes
  where match(quote) against ('+years -monolith' in boolean mode);
+------------------------+
| Years and not Monolith |
+------------------------+
| Abraham Lincoln        |
| George Harrison        |
| K                      |
+------------------------+
3 rows in set (0.00 sec)
</pre>
<h4>Proximity Search</h4>
<p>
Proximity search is new feature for InnoDB full-text search. It is a special case of Boolean search using the <code>@</code> operator within the <code>AGAINST()</code> string. You supply 2 or more words, double-quoted, within the single-quoted <code>AGAINST()</code> string, followed by <code>@<em>distance</em></code> to specify how far apart these words can be. The distance represents the maximum number of bytes (which might not be equal to the number of characters) between the starting points of all these words.
</p>
<pre>
-- The starting points for these words are too far apart
-- (not within 20 bytes), so no results.
select quote as "Too Far Apart" from quotes
  where match(quote) against ('"early wise" @20' in boolean mode);
Empty set (0.00 sec)

-- But the starting points of all words are within 100 bytes,
-- so this query does give results.
select quote as "Early...Wise" from quotes
  where match(quote) against ('"early wise" @100' in boolean mode);
+-------------------------------------------------------------------------+
| Early...Wise                                                            |
+-------------------------------------------------------------------------+
| Early to bed and early to rise, makes a man healthy, wealthy, and wise. |
+-------------------------------------------------------------------------+
1 row in set (0.00 sec)

-- In this case, the smallest distance that produces results is 49.
select quote as "Early...Wise" from quotes
  where match(quote) against ('"early wise" @49' in boolean mode);
+-------------------------------------------------------------------------+
| Early...Wise                                                            |
+-------------------------------------------------------------------------+
| Early to bed and early to rise, makes a man healthy, wealthy, and wise. |
+-------------------------------------------------------------------------+
1 row in set (0.00 sec)

-- Here is an example showing 2 results, with the words close to each other.
select quote as "Early...Bed" from quotes
  where match(quote) against ('"early bed" @20' in boolean mode);
+---------------------------------------------------------------------------+
| Early...Bed                                                               |
+---------------------------------------------------------------------------+
| Early to bed and early to rise, makes a man healthy, wealthy, and wise.   |
| Early to rise and early to bed makes a male healthy and wealthy and dead. |
+---------------------------------------------------------------------------+
2 rows in set (0.00 sec)
</pre>
<h3>Relevance Ranking</h3>
<p>
The relevance ranking is fairly basic, derived from word frequencies within each document and the search data overall. Typically, you would only <code>ORDER BY</code> this value for very simplistic searches of small documents; for any important search you would layer your own ranking logic on top, perhaps with the MySQL relevance value as one factor in the overall rank.
</p>
<pre>
-- Get the relevance of a single word.
select substr(quote,1,20) as "And",
  match(quote) against ('and' in natural language mode) as Relevance
  from quotes order by Relevance desc;
+----------------------+--------------------+
| And                  | Relevance          |
+----------------------+--------------------+
| Early to rise and ea | 0.2718571722507477 |
| Early to bed and ear | 0.1812381148338318 |
| Fourscore and seven  | 0.0906190574169159 |
| All those years ago. |                  0 |
| Then 10 years ago th |                  0 |
| 1500 hundred years a |                  0 |
+----------------------+--------------------+

6 rows in set (0.00 sec)
</pre>
<h3>Transactions</h3>
<p>
The key idea behind bringing full-text search to InnoDB tables is to make this feature compatible with transactions, so that you can include full-text columns alongside other columns in tables in ways that make sense in terms of schema design, and multiple sessions can update the full-text column data (and/or other columns in the table) simultaneously. The full-text data doesn&#8217;t have to be treated as read-only or read-mostly.
</p>
<p>
As mentioned in <a href="http://blogs.innodb.com/wp/2011/07/overview-and-getting-started-with-innodb-fts/">Jimmy&#8217;s blog post</a>, the table structures that manipulate the full-text data behind the scenes are only updated at <code>COMMIT</code> time. So make sure to insert or update full-text data in one transaction, commit, and then run any full-text queries in a subsequent transaction. (Actually, in the examples below, it looks like the data is taken out of the full-text results as soon as a <code>DELETE</code> is issued, then comes back if the deletion is rolled back. I think that is explained in Jimmy&#8217;s blog post by the discussion about the delete-marking optimization to avoid huge updates to the full-text index for deleted data.)
</p>
<pre>
drop table if exists quotes_uncommitted;

create table quotes_uncommitted
  (
      author varchar(64)
    , quote varchar(4000)
    , source varchar(64)
    , fulltext(quote)
    , primary key (author, quote(128))
  );

-- We insert but don't immediately commit.
insert into quotes_uncommitted select author, quote, source from quotes;
-- Within the same transaction, a full-text search does not see the uncommitted data.
select count(author), author as "Uncommitted Results" from quotes_uncommitted
  where match(quote) against ('ago' in natural language mode);
+---------------+---------------------+
| count(author) | Uncommitted Results |
+---------------+---------------------+
|             0 | NULL                |
+---------------+---------------------+
1 row in set (0.00 sec)

-- If the newly inserted rows are rolled back...
rollback;
-- ...then the full-text search still doesn't see them.
select count(author), author as "Rolled-Back Results" from quotes_uncommitted
  where match(quote) against ('ago' in natural language mode);
+---------------+---------------------+
| count(author) | Rolled-Back Results |
+---------------+---------------------+
|             0 | NULL                |
+---------------+---------------------+
1 row in set (0.00 sec)

-- OK, let's start with some committed data in the table, then empty the table,
-- and then try some FTS queries
-- both before and after the commit.
insert into quotes_uncommitted select author, quote, source from quotes;
commit;
delete from quotes_uncommitted;
select count(author), author as "Deleted but still not committed" from quotes_uncommitted
  where match(quote) against ('ago' in natural language mode);
+---------------+---------------------------------+
| count(author) | Deleted but still not committed |
+---------------+---------------------------------+
|             0 | NULL                            |
+---------------+---------------------------------+
1 row in set (0.00 sec)

rollback;
select count(author), author as "Deleted and rolled back" from quotes_uncommitted
  where match(quote) against ('ago' in natural language mode);
+---------------+-------------------------+
| count(author) | Deleted and rolled back |
+---------------+-------------------------+
|             4 | Abraham Lincoln         |
+---------------+-------------------------+
1 row in set (0.00 sec)

delete from quotes_uncommitted;
commit;
select count(author), author as "Deleted and committed" from quotes_uncommitted
  where match(quote) against ('ago' in natural language mode);
+---------------+-----------------------+
| count(author) | Deleted and committed |
+---------------+-----------------------+
|             0 | NULL                  |
+---------------+-----------------------+
1 row in set (0.00 sec)

insert into quotes_uncommitted select author, quote, source from quotes;
commit;
truncate table quotes_uncommitted;
select count(author), author as "Truncated" from quotes_uncommitted
  where match(quote) against ('ago' in natural language mode);
+---------------+-----------+
| count(author) | Truncated |
+---------------+-----------+
|             0 | NULL      |
+---------------+-----------+
1 row in set (0.00 sec)
</pre>
<h3>Multi-Column Searches</h3>
<p>
Although you can only have one <code>FULLTEXT</code> index in an InnoDB table, that index can apply to multiple columns, allowing you to search when you aren&#8217;t sure which column contains the term. With a multi-column index, we can <code>MATCH()</code> against all the columns to find words that appear in any of those columns. Always reference all the same columns in the <code>MATCH()</code> clause as in the <code>FULLTEXT</code> index definition, because the information about which column the words appear in is not included in the full-text search data.
</p>
<pre>
drop table if exists quotes_multi_col;

create table quotes_multi_col
  (
    id int unsigned auto_increment primary key
    , author varchar(64)
    , quote varchar(4000)
    , source varchar(64)
    , fulltext(author, quote, source)
  );

insert into quotes_multi_col select * from quotes;
commit;

select author as "Poor 1 (NL)", substr(quote,1,15) as "Poor 2 (NL)", source as "Poor 3 (NL)" from
  quotes_multi_col where match(author, quote, source)
  against ('poor' in natural language mode);
+-------------------+-----------------+-------------------------+
| Poor 1 (NL)       | Poor 2 (NL)     | Poor 3 (NL)             |
+-------------------+-----------------+-------------------------+
| Benjamin Franklin | Early to bed an | Poor Richard's Almanack |
+-------------------+-----------------+-------------------------+
1 row in set (0.00 sec)

select author as "Poor 1 (BOOL)", substr(quote,1,15) as "Poor 2 (BOOL)", source as "Poor 3 (BOOL)"
  from quotes_multi_col where match(author, quote, source)
  against ('poor' in boolean mode);
+-------------------+-----------------+-------------------------+
| Poor 1 (BOOL)     | Poor 2 (BOOL)   | Poor 3 (BOOL)           |
+-------------------+-----------------+-------------------------+
| Benjamin Franklin | Early to bed an | Poor Richard's Almanack |
+-------------------+-----------------+-------------------------+
1 row in set (0.00 sec)

select author as "Clarke 1 (NL)", substr(quote,1,15) as "Clarke 2 (NL)", source as "Clarke 3 (NL)"
  from quotes_multi_col where match(author, quote, source)
  against ('clarke' in natural language mode);
+------------------+-----------------+--------------------------------+
| Clarke 1 (NL)    | Clarke 2 (NL)   | Clarke 3 (NL)                  |
+------------------+-----------------+--------------------------------+
| Arthur C. Clarke | Then 10 years a | 2010: The Year We Make Contact |
+------------------+-----------------+--------------------------------+
1 row in set (0.00 sec)
</pre>
<h3>Interaction with Other Indexes</h3>
<p>
Remember that the design of your primary key index and secondary indexes is a big factor in query performance for InnoDB tables.
</p>
<ul>
<li>You can include parts (prefixes) of the full-text column(s) within the primary key.</li>
<li>However, that might not be a good idea if (a) the associated columns will ever be updated &#8212; which causes an expensive reorganization within the InnoDB table, or (b) if the table will have any other secondary indexes &#8212; the primary key values for a row are duplicated in the entry for that row in every secondary index, making index operations require more I/O and memory.</li>
<li>As mentioned in <a href="http://blogs.innodb.com/wp/2011/07/overview-and-getting-started-with-innodb-fts/">Jimmy&#8217;s blog post</a>, adding the <code>FULLTEXT</code> index to the table is going to create a new column and associated index in the original table, so you could set up the column and index ahead of time, to avoid table reorganization later.</li>
<li>You can use the unique constraint of the primary key or a <code>UNIQUE</code> index to prevent duplicate values or combinations of values from being entered.</li>
<li>You can use the not-null constraint of the primary key to prevent blank values or combinations of values from being entered.</li>
<li>For the Labs release, the InnoDB <code>FULLTEXT</code> processing isn&#8217;t integrated with the MySQL optimizer and its estimates for which index is best to use, so don&#8217;t draw conclusions about performance characteristics from this early preview.</li>
</ul>
<h3>Stopwords</h3>
<p>
Stopwords are typically short, commonly used words that you designate as not significant for a search. They are left out of the <code>FULLTEXT</code> index and ignored when entered in <code>FULLTEXT</code> queries. For example, a search for &#8216;the&#8217; is unsuccessful because it&#8217;s in the default stopword list. For your own customized search, you might create a bigger list (say, with common words from several languages) or a smaller one (for example, a music or movie site where words such as &#8220;The&#8221; in names and titles are significant). The details about customizing the stopword list are in <a href="http://blogs.innodb.com/wp/2011/07/overview-and-getting-started-with-innodb-fts/">Jimmy&#8217;s blog post</a>.
</p>
<pre>
select count(*), author as "Stopword 1", quote as "Stopword 2", source as "Stopword 3"
  from quotes_multi_col
  where match(author, quote, source) against ('the' in natural language mode);
+----------+------------+------------+------------+
| count(*) | Stopword 1 | Stopword 2 | Stopword 3 |
+----------+------------+------------+------------+
|        0 | NULL       | NULL       | NULL       |
+----------+------------+------------+------------+
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blogs.innodb.com/wp/2011/07/innodb-full-text-search-tutorial/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

