MySQL5.1で日本語全文検索(その4;B-Tree,MeCab Parser, Bigram Parserの比較の巻)

まず、BigramパーサーとMeCabパーサーの動きを見てみる。
前回のログでつかったWikipediaのデータ(30000レコード;39MB程度)で実験。

Mecabパーサー

オミナエシ(女郎花)で実験する。

  • ワイルドカードなしの検索では、MeCab分かち書きされた「単語」でなければヒットしない。
  • ヒットしない場合とする場合のレスポンスに大きな開きがある。
  • AND検索より、OR検索が低速。
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インデックスなしで作成。インポート後にインデックスを張る。