maco's life

主にエンジニアリングと読書について書いていきます。

MyISAMの暖気してくれる君をgoで書いた

github.com

雑ですが、必要に迫られて作ってみました。

作成の経緯

RDS上でMyISAMの暖気がしたかったのです。RDSだとデータディレクトリcatでOSのキャッシュに載せるとかできないからクエリなどでできないか調べつつ作りました。先人の方々で作っていらっしゃる方いないかなと思って調べてたのですが、やはりInnoDBを使われているケースが殆どでMyISAMはなかなか見つかりませんでした。InnoDBの暖気はmysql5.6から簡単になったし本当に最高な感じしかないですね。(※1)

あと久しぶりにgolangを学びも兼ねて書いてみたくなったので、言語はgoを用いました。

MyISAMの暖気

以下の2つを実行したら再起動直後のウォームアップとして実行しました。

  • LOAD INDEX INTO CACHE <table_name> ※2
    • インデックスをmysqlのキャッシュに載せる
  • SELECT * FROM <table_name>
    • データをOSのキャッシュに載せる

はじめはLOAD INDEX INTO CACHEだけでいけるのかなと思ったけど、ある程度件数があるデータの場合インデックスを使ったクエリでもデータの読み込みに時間がかかったため、SELECT * FROM <table_name>を実行しデータがOSキャッシュにのるか試してみました。結果、約3千万レコードあるテーブルで15秒ちょっとかかってたクエリが1秒で返ってくるようになったし、SELECTでもちゃんとのってる感じはする…。

RDSとEC2 on MySQLの場合と2パターンで試したけど、

RDS EC2 on MySQL
読み込み速度 15秒 -> 1秒 15秒 -> 0.03秒
メモリ インスタンス作成時と変わらず cached memoryが2GB増

みたいな感じでRDSの方はちょっとどうみたらいいかわからなかった。AWSコンソール上でみれるRDSのメモリは純粋にmysqlで使われるメモリのみなのだろうか。一方MyISAMの場合EC2 on MySQLの方がパフォーマンス的にもメモリの使われ方的にも顕著な感じでした。

実装したもの

簡単先述したクエリ2つのクエリを各テーブルごとにgoroutineとして実行してくれるツールを作りました。使い方などはREADMEをご参照ください。

今後

  • 現状engineがMyISAMなテーブル全部に対して実行してるけど、きっと全部キャッシュに乗らないケースがあるだろうからtable名指定とかもできるようにしないとかも。
  • golangについて素人なので、実装の改善やらないと。
  • これでよかったの感ある。良い暖気の方法があれば知りたい。

参考

主にgoで実装するにあたり下記のドキュメント・記事を参考にさせていただきました。ありがとうございました。