RDS for MySQLのファーストタッチペナルティを解除する3ライナー
EC2+EBSの場合は、ddで触るといった方法でこれを解消することになるが、RDS for MySQLではもう少し複雑な作業が必要になる。
具体的には次の3つのことをしなければいけない。
primary keyをすべて読み込み
secondary keyをすべて読み込む
すべてのデータを読み込む
ファーストタッチペナルティの解除についてインターネットで探すと、「select count(*) from テーブル名 を全テーブルに打ちましょう」というのがよくでてくるが、これだけだとsecondary keyを読み込めてないので、本番投入後に特定のSQLが最初だけ遅いという現象が起きうる。なお、MySQLの count(*) は実データに触るので、3番目のすべてのデータを読み込むというのは達成できている。
さて、MySQL 5.6(RDS for MySQLの現時点で利用できる下限のバージョン)以上では、information_schemaにsecondary keyを含むすべてのインデックスの情報が入っているので、これを利用してファーストタッチペナルティを解除するスクリプトを作ることができる。それが以下の3ライナー。YOUR_DATABASE_NAMEをDB名に置き換え、ホスト名などの認証情報は~/.my.cnf等に書いておくと楽。
code: (bash)
mysql -sse "SELECT distinct table_name, index_name FROM information_schema.statistics WHERE table_schema = 'YOUR_DATABASE_NAME'" | while read table index ; do
mysql -sse "SELECT count(*) FROM $table FORCE INDEX($index)" YOUR_DATABASE_NAME > /dev/null &
done
どれくらいで終わるかはテーブルとレコードの量、インスタンスタイプに依存するので一概には言えないけど、こういうのを考える必要があるサービスの規模であれば、数時間は見ておいて方がいいだろう。終わったかどうかは実行したクライアントマシンのmysqlプロセスの数を見るか、MySQLサーバに入ってshow processlist等でSELECTクエリが残っているかをみればよい。
なお、新しいDBサーバの本番投入の前には、バッファプールも整えておいたほうが良い。これこそサービス依存なのでこうすればいいというのは存在しないが、SELECTされる回数の多いテーブルなどメモリにのっていてほしいデータをSELECTするクエリを流しておくとよい。
参考文献