Contents
- MySQL5.0.34+Senna1.0.1 on Linux2.6+AMD64
- テスト環境
- インデックスの構築
- 検索性能比較
- 更新性能比較
- まとめ
Tritonn性能検証
TritonnパッチはMySQLからSennaを使えるようにして、MySQL+Sennaによる高速全文検索を実現するためのものです。従って性能に関しては非常に重視しています。このページではTritonn開発者による性能検証の情報などを公開していく予定です。
性能面についてのバグが見つかった場合には、SourceForgeのバグ管理システムを利用して管理していく予定です。
MySQL5.0.34+Senna1.0.1 on Linux2.6+AMD64
OSC2007にて発表した内容です。
テスト環境
- ハードウェア/ソフトウェア構成
以下のハードウェア/ソフトウェア構成にて行っています。
| 機種 | HP ProLiant 385 |
| CPU | AMD Dual Core Opteron 2.6GHz *2 (1MB L2 cache *2) |
| RAM | DDR-SDRAM ECC PC3200 8GB |
| DISK | SAS 2.5inch 10000rpm 72GB *4 |
| RAID | BBWC付き 256MB |
| OS | Miracle Linux 4.0 (Asianux 2.0) / Linux Kernel 2.6.9-11AXCustom |
| アーキテクチャ | x86_64 (EM64T/AMD64) |
| MySQL | ver5.0.34 |
| Senna | ver1.0.1 |
| Tritonn | ver1.0.0の少し前 |
- チューニング値
以下の値を使用しています。
| mysql | myisam_sort_buffer_size | 1024MB |
| mysql | key_buffer_size | 1024MB |
| senna | initial_n_segments | 2048 |
- テストに使用したデータ
日本語版Wikipediaのダンプデータ から記事本体のテキストデータを抽出したもの。
以下のテーブルに格納した所、約57万行、MYDファイルサイズ1.4GB、平均行長2300バイトになった。
CREATE TABLE t1 ( c1 INT PRIMARY KEY AUTO_INCREMENT, c2 TEXT ) ENGINE = MyISAM DEFAULT CHARSET utf8;
- 負荷ツール
mbenchをMySQL C APIを使用してC言語で再実装したもの。表に出せるクオリティではないのでまだOSS化はしていません。。。
- ノード構成
サーバ用として上記のハードウェア1台と、クライアント用としてThinkPad T43を1台の構成。
インデックスの構築
前提条件として、テーブル作成、データ格納を行った後、以下のSQL文を実行して計測。
CREATE FULLTEXT INDEX ft USING NORMALIZE, 2048 ON t1(c2); CREATE FULLTEXT INDEX ft USING NGRAM, NORMALIZE, 2048 ON t1(c2);
これにより、データサイズ1.4GB/57万行の時のmecabとngramそれぞれのインデックス構築速度が分かる。
- 結果
ファイルサイズはngramの方が大きくなってしまうものの、速度自体はこちらの方が速い。
| index_type | 要した時間 | スループット | SENファイルのサイズ合計 | SENファイル内の語彙数 |
| mecab | 18分22秒 | 513.7行/秒 | 1.47GB | 417万語 |
| ngram | 14分32秒 | 649.2行/秒 | 2.13GB | 523万語 |
- 捕捉事項
- myisam_sort_buffer_sizeを大きくすると性能UP
- initial_n_segmentsを大きくすると性能UP
- myisam_repair_threadsは無関係
検索性能比較
あらかじめ10接続を作成しておき、mecab、ngram、インデックス無しのテーブルに対して、2分間、ラッシュ検索を実施。
mecab/ngramに対しては以下のSQL文を繰り返し実行。いわゆる全文検索。
SELECT COUNT(*) FROM t1 WHERE MATCH(c2) AGAINST("キーワード");
インデックス無しについては以下のSQL文を繰り返し実行。いわゆる部分一致検索。
SELECT COUNT(*) FROM t1 WHERE c2 LIKE '%キーワード%';
このとき使用するキーワードは、あらかじめ用意した約6万の日本語の名詞の中から各接続ごとに1万個選んでおき、それぞれがその選んでおいたものを使用している。
※ただし、ここで使用している名詞そのものはmecab-ipadicから抽出しているので、mecabに有利な結果が出やすいというのも考慮する必要あり。
- 結果(複数回計測した値の平均値)
※OSのファイルキャッシュの影響を著しく受けるため、OSのファイルキャッシュに十分乗り切った状態で計測している。
| index_type | スループット | 平均レスポンス | 相対値 |
| mecab | 3190.7 クエリ/秒 | 3.1 ミリ秒 | 10293 倍 |
| ngram | 1235.3 クエリ/秒 | 8.1 ミリ秒 | 3985 倍 |
| インデックス無し | 0.31 クエリ/秒 | 31.2 秒 | 1 |
部分一致検索(LIKE演算子)が圧倒的に遅い。データ量が数MBなら両者の差は少ないかもしれないが、ある程度以上大きくなってくると部分一致検索では太刀打が出来なくなる。
mecabの方がngramに比べて断然速い。とはいえ、ngramのほうもスループット/平均レスポンスともに十分実用可能な範囲と思われる。
- 補足
- ラッシュ時の同時接続数を1〜増やしていくと、CPUコア数まではスケールする。
- さらに同時接続数を増やすと、スループットが伸び無い分、平均レスポンスが低下していく。
更新性能比較
あらかじめ10接続を作成しておき、mecab、ngram、インデックス無しのテーブルに対して、2分間、ラッシュ更新を実施。
以下のSQL文を繰り返し実行。
INSERT INTO t1 (c2) SELECT c2 FROM t1_copy WHERE c1 = キー;
t1_copyはt1テーブルと同じデータを持つ別のテーブル。ここでも、日本語の文章として意味のあるものを入力データに使用する必要があったため、bestな案ではないが、この方法を採用した。"キー"には事前にランダムで選んでおいた数値(t1_copyに実在する数値)を使用。
- 結果
※OSのファイルキャッシュの影響を著しく受けるため、OSのファイルキャッシュに十分乗り切った状態で計測している。
| index_type | スループット | 平均レスポンス | 相対値 |
| mecab | 246.7 行/秒 | 43.7 ミリ秒 | 0.38 倍 |
| ngram | 254.3 行/秒 | 40.5 ミリ秒 | 0.40 倍 |
| インデックス無し | 641.2 行/秒 | 15.6 ミリ秒 | 1 |
インデックス無しの時に比べると、mecab/ngram双方とも半分弱に低下。
今回は平均行長が2300バイトもあるため、そもそもかなり重たいINSERTであった。平均行長がもっと短い場合には、絶対値はそれぞれもっと向上する。
- 補足
- MyISAMでは更新時に1CPUしか処理が行われないため、更新処理についてはマルチコアのメリットは受けられない。
まとめ
MySQL+Sennaを使うと、MySQLのみの場合に比べて全文検索処理についておよそ以下のような傾向があると考えられる。
- 検索性能が数千倍にあがる
- 更新性能が半分以下に落ちる