<Hazm Blog />

MySQL全文検索について調べたこと

Cover Image for MySQL全文検索について調べたこと
Hazm
Hazm

業務案件で全文検索を使うことになった。とはいえ全文検索について全く知識がなかったのでここでインプットしておこうということで、いろいろ調べてみた。

全文検索とは

コンピュータにおいて、複数の文書から特定の文字列を検索すること。複数文書にまたがって文書に含まれる全文を対象とした検索。

grep型(逐次走査検索)

事前に索引を作成せず、複数のファイルを順次走査していく。検索対象の増加によって検索速度が低下する。

索引型(インデックス)

事前に検索対象となる文書を走査し、索引データを準備しておく。これをインデクシングとよび、これにより生成されるファイルをインデックス(インデクス)と呼ぶ。

索引文字列の抽出手法

インデックスを作成するために検索対象の文書を解析・分割を行う。その手法として主に下記2手法がある。

形態素解析

英文は単語の間にスペースが入るため、これで区切れば索引データの作成は容易である。しかし日本語の場合それができないため形態素解析技術を用いて、文書の解析、単語分解を行い、それをもとにインデックスを作成する。形態素解析を行うためには解析用の辞書が必要であり、辞書に品質を受けやすく、検索漏れが生じる場合がある。

N-Gram

「N-文字インデックス」「N-グラム法」なとどもいう。単語単位ではなく文字単位で分解し、後続のN-1文字を含めた状態で出現頻度を求める方法。N=1は「ユニグラム(uni-gram)」N=2は「バイグラム(bi-gram)」N=3は「トライグラム(tri-gram)」と呼ばれる。検索漏れが生じず、辞書の必要がない。しかし形態素解析と比べるとノイズの発生とインデックスサイズの肥大化という2つの欠点がある。

全文検索技術
↓
全文/文検/検索/索技/技術/術

MySQLにおける全文検索

MySQLでは、バージョン5.6.4より全文検索をサポートしている。 しかし、これは空白で単語が区切られるラテン語ベースの言語に対してのみ有効である。

これに対し、バージョン 5.7.6 よりCJK(日韓中文字)で使用できる n-gramパーサ がサポートされました。(組み込みのサーバープラグイン。サーバーの起動時に自動的にロードされる。)

同タイミングで MeCab全文パーサプラグイン も提供されていて、形態素解析によるインデクシングも可能。(RDSだと使えないらしい?要調査)

MySQLサーバー設定

プロパティ 説明 備考
innodb_ft_min_token_size 単語の最小長 0~16 デフォルト3
innodb_ft_max_token_size 単語の最大長 10~84 デフォルト10
ngram_token_size n-gramパーサを使用する際の分割文字数 デフォルト2
innodb_ft_sort_pll_degree インデックスを作成するスレッド数 1~32 デフォルト2 大きなテーブルにFULLTEXTインデックスを作成するときは、スレッドの数を増やすことを検討
innodb_ft_cache_size 補助インデックステーブルごとのキャッシュ容量 デフォルト 8000000bytes

InnnoDB全文検索の要素

InnoDB Full-Text Index Tables

InnoDB FULLTEXTインデックスを作成すると、FTS_から始まるインデックステーブルのセットが作成される。これらを転置インデックスという。

InnoDB Full-Text Index Cache

ドキュメントがインサートされると、FULLTEXT INDEXにもインサートが実行される。小さなドキュメントの場合でもインサートアクセスが実行されることになり、補助インデックステーブルへのアクセスが競合する場合があります。これを回避するために、最近インサートされた行の挿入はキャッシュされる。キャッシュ領域がいっぱいになると、ディスクに書き込まれまれる。これにより競合を防いでいる。Innodb_ft_cache_sizeはこのキャッシュ容量を設定できる。

InnoDB Full-Text Index Deletion Handling

FULLTEXT INDEX列をもつレコードを削除すると、補助インデックステーブルへの同時アクセスで競合が発生する場合があります。これを防ぐために削除されたドキュメントIDをFTS_DELETEDテーブルに記録する。クエリ結果を返す前に、FTS_DELETEDテーブルの情報を使用して削除されたドキュメントIDを除外する。補助インデックステーブルの値は保持されるため容量は減らない。補助インデックステーブルの値を削除するには、OPTIMIZE TABLE句を用いて実行できる。

一部引用元: https://ja.wikipedia.org/wiki/%E5%85%A8%E6%96%87%E6%A4%9C%E7%B4%A2 https://dev.mysql.com/doc/refman/5.7/en/fulltext-search.html