MySQLの高速化のメモ

最近Railsアプリを作成している中で、初めて高速化をやったので、その際のことをメモしておく。

高速化の手順

ベンチマークをとる

まずはベンチマークをとっておく。これによって、どのくらい早くなったか見極める。Railsなら、script/performance/benchmarkerを使って出来る。
テストコードとして、大量のフィクスチャを用意し、それに対して処理したベンチをとる方法もあるが、フィクスチャのデータがかなり現実味を帯びている必要があるため、本番環境でベンチをとった方がいい。
また、プロファイルして、本当にDBアクセスがボトルネックになっているのかを見ておく。

スロークエリログを見る

MySQLには、結果を得るのに一定時間以上かかったクエリを記録しておく、「スロークエリログ」という機能があるので、どのクエリがボトルネックになっているかをこのログを見て調べる。
ログファイルの場所は、設定ファイルに書いてある。僕の環境では、設定ファイルは/etc/mysql/my.cnfにあったので、そこを見たら以下のように書いてあった。

[mysqld]
log-slow-queries = /var/log/mysql/mysql-slow.log
long_query_time=1
log-queries-not-using-indexes

EXPLAINを使って遅いクエリを改善する

EXPLAIN構文は、以下の様にSELECT文に対して使う。よって、遅いクエリをログからコピーして、先頭にEXPLAINを加えて実行してみる。と、解析結果が得られる。

EXPLAIN SELECT * from users WHERE prefecture = '神奈川県';


あとは、クエリを改善しながら、EXPLAINを見て最適化して、ベンチとりながら実行してスロークエリをまた見てと繰り返す。スロークエリに出現しなくなったら大体成功。
高速化の基本はインデックスのため、EXPLAINは主にインデックスが上手く使われているかを見るために使う。また、MySQLノウハウも参考になる。


今回高速化したクエリは、JOINした結果に対してORで絞込みをし、ORDERを使い、その結果をLIMITで10件だすというものだった。
最初は、JOINが遅いと思ったり、ORが実は遅いのではとか思っていたけど、実際はORDERが遅かった。LIMITで10件しか出してないのになんで遅いのか分からなかったが、LIMITの前に得られた全レコードをソートするORDERがボトルネックになってた。EXPLAINすることでそれを知ることが出来た。

  • 実際EXPLAINして高速化した時のメモ

インデックスを使った高速化について - @luke_silvia.diary