MySQL5.1で日本語全文検索(その4;B-Tree,MeCab Parser, Bigram Parserの比較の巻)
まず、BigramパーサーとMeCabパーサーの動きを見てみる。
前回のログでつかったWikipediaのデータ(30000レコード;39MB程度)で実験。
Mecabパーサー
オミナエシ(女郎花)で実験する。
mysql> set names utf8; Query OK, 0 rows affected (0.00 sec) mysql> select count(*) from me where match(c) against('オミナエシ' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (4.03 sec) mysql> select count(*) from me where match(c) against('オミナエシ*' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (0.48 sec) <== これはキャッシュを読んでいる。 mysql> select count(*) from me where match(c) against('オミナ*' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (0.82 sec) <== これはキャッシュを読んでいる。 mysql> select count(*) from me where match(c) against('オミナ 女郎' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec) mysql> select count(*) from me where match(c) against('*オミナエシ' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.07 sec) mysql> select count(*) from me where match(c) against('女郎*' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (0.37 sec) <== これはキャッシュを読んでいる。 mysql> select count(*) from me where match(c) against('+オミナ* +女郎*' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (6.55 sec) mysql> select count(*) from me where match(c) against('オミナ* 女郎*' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (7.45 sec) mysql> select count(*) from me where match(c) against('オミナ* -女郎*' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (2.58 sec)
Bigramパーサー
- ワイルドカードなしの検索とありの検索が同等の結果となる(N-Gramだから)。ただし、MeCabの方が3倍ほど高速。
- ヒットしない場合とする場合のレスポンスに大きな開きがある。
- ‘+’ , ‘-’の扱いに不明瞭な点がある(下)。=> AND検索とOR検索のやり方が分からない。
mysql> select count(*) from bi where match(c) against('オミナエシ' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (4.41 sec) mysql> select count(*) from bi where match(c) against('オミナ' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (2.65 sec) mysql> select count(*) from bi where match(c) against('+オミ' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (0.61 sec) mysql> select count(*) from bi where match(c) against('+オミナ' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec) <== これは何故か? mysql> select count(*) from bi where match(c) against('+オミナ*' IN BOOLEAN MODE); +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.01 sec)
次に、B-Tree(Like をつかった普通の検索)、Bigram、MeCabパーサーの結果を比較すると、このスケールではB-Treeが一番早く、MeCabパーサーが次、Bigramはだいぶ遅い結果となった。
これは、自分のやり方がおかしいのかもしれない。
mysql> select count(*) from me where c LIKE '%オミナエシ%'; +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (0.30 sec)
実験する場合には、一旦Dropしてから、FULLTEXTインデックスなしで作成。インポート後にインデックスを張る。