【MySQL】インデックスを貼ったら32.2倍で動いた
レコードを数えたり、重複を削除したりと便利なMySQLですが、思ったほど速度が出ない状況があります。
そんなときのKVSか!と思ったのですが、インデックス周りを見直すだけでもかなりチューニングできそうなので検証してみました。
テストデータ
処理
キーワードが与えられると、そのキーワードが各文書にどれだけ含まれているかを返す処理を想定します。
テーブル構造
文書と単語の中間テーブル
doc_word_id | doc_id | word_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
4 | 2 | 4 |
5 | 2 | 2 |
単語テーブル
word_id | surface | pos |
---|---|---|
1 | 私 | 名詞 |
2 | 名前 | 名詞 |
3 | 鈴木 | 名詞 |
4 | 趣味 | 名詞 |
5 | ギター | 名詞 |
中間テーブルのレコード数
count(doc_word_id) |
---|
143317 |
単語テーブルのレコード数
count(word_id) |
---|
4792 |
検証
上記の処理をするプログラムをPythonで書いて、time コマンドで実行時間を測ってみます。
結果はこんな感じになりました。
(realのみ掲載)
番号 | index | 実行時間 |
---|---|---|
1 | なし | 5m21.873s |
2 | doc_id | 2m55.429s |
3 | surface | 2m30.906s |
4 | doc_id, surface | 0m57.415s |
5 | 複合(doc_id, word_id) | 1m14.861s |
6 | 複合(doc_id, word_id), surface | 0m10.287s |
6番めっちゃ速い!
複合キー万歳ですね。
もう1点、
「MySQLでは、1つのクエリを実行するとき、1つのテーブルにつき1つのインデックスしか仕様できないのである。」
実践ハイパフォーマンスMySQL P66
とありますが、内部結合したときは結合後で1つのテーブルとして扱われるのかも気になっていました。
2番、3番と比べて4番が早くなっていることから結合前のテーブル数でカウントされている(結合後で1つのテーブルとして扱われていない)ようですね。
まとめ
- 複合キー速い!
- 内部結合するときはそれぞれのテーブルにインデックスを貼ると速い!