id:odan3240 さんと「情報処理部」というチームで出場してきました。
id:odan3240 さんの参加記もあるので合わせてどうぞ:
結果
- 最終スコア: 3270
何もできなかった...
時系列
結構前の話なのでうろ覚えだけど…大体こういう流れだったと思う。
- 10:00 競技開始
- 10:30 インスタント立てたりマニュアル読み合わせしたり
- 〜11:30 ソースコード取り出したり、デプロイスクリプト書いたり、Datadog 入れたり
- 11:30〜
- id:odan3240 N+1 修正、インデックス貼る
- id:mizdra sqlite から mysql に移行し始める
- 14:00
- id:odan3240 採番の実装を ulid にしたり
- id:mizdra まだ mysql 移行作業してる
- 15:00
- id:odan3240 Redis の導入を始める
- id:mizdra まだ mysql 移行作業してる
- 17:30
- Redis 導入も mysql 移行も間に合わない!となって、監視設定切ったりパラメータチューニングしてベンチマーク回し始める
- 3270 点出たところで終了
やったこと
- sqlite のスキーマに index を貼った
- ...のだけど、途中でやっぱり sqlite 脱出しよう!となって中断して、実際に貼ったのは 1 つだけ。
- sqlite のデータを mysql に移行する (失敗)
- 最初 sqlite3-to-sql を使って移行を始めたけど、40分くらい? (よく覚えていない) 掛かる上に、完走した後に
player_score
テーブルのレコード数を数えたら、20万件くらい欠けていることが判明した- 虚無へと消えるレコード...
- 警告とかエラーとかも出てなくて、何が起きていたのかさっぱり分からなかった
- 「なんで〜」となって試行錯誤しているうちに 1 時間くらい溶けていた
- そもそも 40 分掛かるのおかしいよね、ということで CSV に変換してから import する方法に切り替え始めた
for file in `ls ../../initial_data/*.db`; do sqlite3 -csv $file "select * from competition;" >> competition.csv sqlite3 -csv $file "select * from player;" >> player.csv sqlite3 -csv $file "select * from player_score;" >> player_score.csv done mysql -uisucon -pisucon -Disuports --enable-local-infile -e"load data local infile 'competition.csv' into table competition fields terminated by ',' OPTIONALLY ENCLOSED BY '\"';"; mysql -uisucon -pisucon -Disuports --enable-local-infile -e"load data local infile 'player.csv' into table player fields terminated by ',' OPTIONALLY ENCLOSED BY '\"';"; mysql -uisucon -pisucon -Disuports --enable-local-infile -e"load data local infile 'player_score.csv' into table player_score fields terminated by ',' OPTIONALLY ENCLOSED BY '\"';";
- これで 20 分くらいに短縮された
- けどレコードが虚無へと消えていくのは直らない...
- mysql のバッファに余裕がなくてレコードが欠けてしまっているのでは? と思って、mysql のパラメータチューニングをし始める
[mysqld] innodb_buffer_pool_size=4G innodb_buffer_pool_instances=4 innodb_log_buffer_size=200MB innodb_log_file_size=400M innodb_flush_method=O_DIRECT max_allowed_packet = 64M
- これで 3 分くらいに短縮された
- レコードが虚無へと消えることもなくなった!
- しかしベンチマークを回してみると
POST /initialize
がタイムアウトしてしまう!webapp/sql/init.sh
にこういう初期化用の sql を書いていたのだけど、created_at
レコードに index がなくて、そもそもwebapp/sql/init.sh
に時間がかかりすぎるらしい- index 貼った
- まだタイムアウトする!
GET /api/admin/tenants/billing
が遅すぎてタイムアウトしてた- N+1 直してなかったのが原因っぽかった
- 直そう、と思ったけど残り 30 分ほどしかなくて、ここであえなく時間切れ
- https://github.com/odanado/isucon12-qualifier/pull/9
- 最初 sqlite3-to-sql を使って移行を始めたけど、40分くらい? (よく覚えていない) 掛かる上に、完走した後に
- その他 import 中の待ち時間に nginx 周りでなにかできることないか探したり、シュッとできそうだったので
/api/me
をゲストユーザの時は nginx から返すようにしたりしたけど、ほとんど点数は変わらなかった
感想
sqlite to mysql に手を出したのが良くなかった… 危険な匂いを嗅ぎ分けて、先に他のボトルネック (それこそ最後に詰まっていた N+1 とか) から 1 つずつ潰していけばよかった。あとデータ量が多い時の mysql のパラメータチューニングの方法とかも事前に練習しておけばもっとスムーズだったかも。というよりは、業務でデータ量多い DB を扱う経験を積んだりとか、普段から色々なことに手を伸ばしていきましょうという話っぽい。もっと挑戦していきたい。
来年もがんばります。