Category Archives: InnoDB

The InnoDB Change Buffer

One of the challenges in storage engine design is random I/O during a write operation. In InnoDB, a table will have one clustered index and zero or more secondary indexes.  Each of these indexes is a B-tree.  When a record is inserted into a table, the record is first inserted into clustered index and then into each of the secondary indexes. …

InnoDB 全文検索 : MeCab Parser

(この記事は InnoDB Full-Text: MeCab ParserYoshiaki Yamasaki が翻訳したものです)

このブログ記事で紹介した一般的なCJK(中国語、日本語、韓国語)のサポートに加えて、私達はMeCabパーサーも追加しました。MeCabは日本語の形態素解析エンジンで、私達は今MeCabをベースにした全文検索プラグインパーサーを持っています!

使用方法

  1. mecab_rc_fileオプションを設定する — mecab_rc_fileはMeCabパーサーに関連する読み取り専用のシステム変数です。mecab_rc_fileが指すmecabrcファイルはMeCabが必要とする設定ファイルです。そして、MeCabに辞書をどこからロードすればいいかを伝えるために、 dicdir=/path/to/ipadicというエントリが必要です。MySQLがインストールされると、デフォルトでバンドルされているmecabrcファイルは /path/to/mysql/install/lib/mecab/etc/mecabrcにあります。また、ipadic_euc-jp, ipadic_sjis, ipadic_utf-8という3つの辞書が /path/to/mysql/install/lib/mecab/dicディレクトリにあります。私たちはこれら3つの内から使用したい辞書を1つ指定するために、mecabrcファイルを修正する必要があります。
    注意:あなたが独自の辞書を持っている場合は、代わりにその辞書を使用できます。mecabrcファイル内で指定できる多くの追加オプションも有ります。設定ファイルの詳細に関しては、こちらのマニュアルを参照して下さい。ここではテスト目的で、以下の手順でipadic_utf-8をロードしてみましょう。(以下の例では、MySQL 5.7.7は/usr/local/mysqlにインストールされています) :
    1. この様なエントリをmecabrcファイルに追加します:
      dicdir=/usr/local/mysql/lib/mecab/dic/ipadic_utf-8
    2. この様なエントリを/etc/my.cnfファイルの[mysqld]セクションに追加します:
      loose-mecab-rc-file=/usr/local/mysql/lib/mecab/etc/mecabrc
  2. innodb_ft_min_token_sizeを設定します— MeCabパーサーを使う場合の推奨値は1もしくは2です(デフォルト値は3です)。以下の例では1を使用します。
  3. MeCabプラグインをインストール:
  4. MeCabパーサーを使って全文検索インデックスを作成
    (注意:MySQL 5.7.6では、utf8mb4の代わりにut8を指定する必要があります。
    The MeCab parser plugin now supports the eucjpms, cp932, and utf8mb4 character sets in 5.7.7 and later—Bug#20534096):

MeCabトークン化の詳細

トークン化がどのように行われるのかを明確に示す例を見てみましょう:

MeCabを使った全文検索の詳細
テキスト検索

  • NATURAL LANGUAGE MODEでは、検索されるテキストは検索トークンの和集合に変換されます。例えば、’日本の首都’は’日本 の 首都’に変換されます。ここで具体例を紹介します:
  • BOOLEAN MODEでは、検索されるテキストはフレーズ検索に変換されます。例えば、’日本の首都’は'”日本 の 首都”‘に変換されます。ここで具体例を紹介します:

ワイルドカードを使った検索

  • ワイルドカードを使った検索はトークナイズされません。例えば、’日本の首都*’は接頭辞’日本の首都’を検索します。そして、一致する結果が得られないかもしれません。ここで2つの具体例を紹介します:

フレーズ検索

  • フレーズ検索はMeCabによってトークナイズされます。例えば、”日本の首都”は”日本 の 首都”に変換されます。ここで具体例を紹介します:

MeCabの制限

サポートしているキャラクタセットはeucjpms (ujis), cp932 (sjis), utf8 (utf8mb4)の3つです。MeCabが使用しているキャラクタセットとInnoDBが使用しているキャラクタセットに違いがある場合(例えばMeCabのキャラクタセットがujisで、全文検索インデックスがutf8/utf8mb4の場合)、検索しようとした時にキャラクタセット不一致のエラーが発生します。

InnoDBの全文検索全般に関して詳細を知りたい場合は、ユーザーマニュアルのInnoDB Full-Text Index セクションや、ジミーの素晴らしい記事(Dr.

InnoDB 全文検索 : N-gram Parser

(この記事は InnoDB Full-Text : N-gram ParserYoshiaki Yamasaki が翻訳したものです)

デフォルトのInnoDB全文検索パーサー(構文解析プログラム)は、空白がトークン(語句)もしくは単語の区切りとなっているラテン語ベースの言語に対して理想的です。しかし、個々の単語の区切り文字が存在せず、それぞれの単語は複数の文字で構成できる中国語・日本語・韓国語(CJK)のような言語には向いていません。そこで、私たちは異なった方法で単語/トークンを識別する方法を必要とします。
私は今MySQL 5.7.6で、CJKで使用できるn-gramパーサーを提供するために、新しいプラガブル全文検索パーサーをサポートすることをとても嬉しく思っています!

N-gramとは?

全文検索において、n-gramとは与えられた文字列中のn文字の連続した文字列です。例えば、n-gramで”abcd”という文字列をトークナイズすると以下のようになります。

どのようにしてN-gramパーサーをInnoDBで使うか?

新しいn-gramパーサーはデフォルトで有効になっているため、関連するDDL文にWITH PARSER句を追加するだけで使用できます。例えば、以下のDDL文はMySQL 5.7.6以降で有効です。

MySQL 5.7.6では、ngram_token_size (トークンはn文字からなる単語とほぼ同等) という新しいサーバー変数も導入されています。デフォルト値は2(bigram)で、1~10まで変更可能です。次の疑問として、「どのトークンサイズを選択すればいいか?」、という疑問が湧いてきます。2またはbigramはCJKの一般的な使用方法において推奨されていますが、この単純なルールに基づいて任意の有効な値を選択できます。
 ルール:あなたが検索時に期待する最大のトークンに合わせてトークンサイズを設定する。
もし、単一の文字を検索したい場合は、ngram_token_sizeを1に設定する必要があります。ngram_token_sizeが小さい方がインデックスを小さくでき、そのインデックスを使った全文検索がより高速になります。しかしながら欠点は、あなたが検索できるトークンのサイズを制限していることです。例えば、英語の「Happy Birthday」は伝統的な中国語では「生日高興」と翻訳されます。(「Happy」=「高興」、「Birthday」=「生日」)この例のように、それぞれの単語/トークンは2文字から構成されるため、このトークンを検索するためにはngram_token_sizeを2以上に設定する必要があります。

N-gramトークン化の詳細

n-gramパーサーはデフォルトの全文検索パーサーと以下の点が異なります。

  1. トークンサイズ : innodb_ft_min_token_sizeinnodb_ft_max_token_size は無視されます。代わりにトークンを制御するためにngram_token_sizeを指定します。
  2. ストップワードの処理: stopwordsの処理も少し異なります。通常、トークン化された単語自体(完全一致)がストップワードテーブルにあるならば、その単語には全文検索インデックスは作成されません。しかしながら、n-gramパーサーの場合は、トークン化された単語がストップワードを含んでいないか確認し、含んでいればインデックスを作成しません。このように動作が異なる理由は、私たちのCJKは非常に多くの頻繁に使われる無意味な文字、単語、句読点を持っているからです。ストップワードに一致する文字が含まれているかを確認する方式を使うと、より役に立たないトークンを除去できます。
  3. 空白 : 空白は常にストップワードです(ハードコードされています)。例を挙げると、’my sql’は’my’、’y ’、’ s’、’sq’、’ql’にトークナイズされ、’y ’と’ s’はインデックス化されません。

私達はINFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE テーブルとINFORMATION_SCHEMA.INNODB_FT_TABLEテーブルを参照することで、特定の全文検索インデックス内にどのようなトークンがインデックス化されているか正確に確認できます。これはデバッグの為に非常に便利なツールです。例えば、単語が期待通りに全文検索結果に表示されない場合、その単語は何らかの理由(ストップワード、トークンサイズ、など)でインデックス化されていないことを、これらのテーブルを参照することで確認できます。簡単な例を紹介します。

N-gramの検索処理の詳細

テキスト検索

  • NATURAL LANGUAGE MODEでは、検索されるテキストはn-gramの和集合に変換されます。例えば、’sql’は’sq ql’に変換されます(デフォルトのトークンサイズである2、もしくはbigramの場合)。
  • BOOLEAN MODEでは、検索されるテキストはn-gramフレーズ検索に変換されます。例えば、’sql’は'”sq ql”‘に変換されます。
    翻訳者注釈追記:”sq ql”は、’sq’と’ql’がこの順番で両方とも一致する必要があるため、’sq’や’ql’は検索結果に出てこない。

ワイルドカードを使った検索

  • プレフィックス(接頭辞)がngram_token_sizeより小さい場合、検索結果はその接頭辞で始まるn-gramのトークンを含む全ての行を返します。
  • プレフィックスの長さがngram_token_sizeと同じか大きい場合、ワイルドカードを使った検索はフレーズ検索に変換され、ワイルドカードは無視されます。例えば、’sq*’は'”sq”‘に変換され、’sql*’は'”sq ql”‘に変換されます。

フレーズ検索

  • フレーズ検索は、n-gramトークンのフレーズ検索に変換されます。例えば、”sql”は”sq ql”に変換されます。

InnoDBの全文検索全般に関して詳細を知りたい場合は、ユーザーマニュアルのInnoDB Full-Text Index セクションや、ジミーの素晴らしい記事(Dr.