footmark

ひよっこエンジニアの足跡

【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つのテーブルとして扱われていない)ようですね。

まとめ

  • 複合キー速い!
  • 内部結合するときはそれぞれのテーブルにインデックスを貼ると速い!