このページについて
isucon10 に出たのでその振り返りをしています。
内容
構成
2人チームで go で挑んだ。
結果
ベスト690点の惨敗。一度もスコアの明確な伸びを感じられない悔しい結果となった。初期スコアが400点だったので。
やったこと
- ssh config setup
- Github にコードアップ
-
Makefile 作成
- コマンドでビルド、ssh でコマンド流してサービス再起動できるようにした
-
アプリケーションにgit のリビジョン入れる
- 一応変更が反映されてるかのチェック
- pprof, newrelic 仕込む
- 各サーバに mackerel 仕込む
- db や nginx など設定ファイルのバックアップ
ここらへんは、1時間以内に終わり、アプリケーションを見ていくことにわりと専念できた。 改善までの準備はつまづくことなく終了
アプリケーションの改善
chair や estate が最初に 3万件近く入っていて、検索が行われるようになっており
この処理がアプリケーションの実行時間の 4割以上を占めていることがわかる。
特に N + 1 になっている様子もないので、index を仕込んでみることに。
必ず条件は設定されるので、条件フィールド + order by priority desc id asc の 3組を一通りindex 貼った。
しかし、スロークエリで一向に検索が改善されない。like concat '%?%' が使われると index が使われなくなってしまうので
ひとまず、その対象のフィールドを別テーブルにバラし、改善を図ることに。しかし、時間をかけたわりには改善せず、スコアが伸びない。
自分は、OR 条件でindex が効かないクエリを分割し、AND で取って、アプリケーションでマージする処理を書くも、フルスキャンが回避できず途方にくれる。
ちなみに、このクエリにも where XXXX > 100 order by priority desc id asc の指定があった。
スキャンを回避できれば、スコアが伸びると思ってたので、テーブルにパーティションを貼ってみる。しかし、これも特に効果がでなかった。
多少スキャンが減る程度だった。
最後のあがきで、アプリケーションを 2台にしてみるもスコアは改善されなかった。
反省、感想
反省は以下3つ
-
モニタリングからの考察が足りなかった
- DB がボトルネックになっているかつ、アプリケーション側で劇的な変化が見られないような場合はDBを2台にするという選択肢を考えてもよかった
-
unix 的に 1つのことを正しくやることに専念させられなかった
- chair と estate は join の関係にないので、別サーバのDBに分けて、DBはそれぞれの処理に専念させて上げららればと思った。
- ここでもモニタリングからの考察がたりなかったように思える
-
db 周りの知識不足
- 降順、昇順混在だと index が効かないのは全く知らなかったし、競技中ググっても出てこなかった気がする。ちゃんと公式を見ておけばよかった。。 https://dev.mysql.com/doc/refman/5.6/ja/order-by-optimization.html
- この辺の知識を知っていれば、下手にアプリケーションの改善の深みにはまらずにデータをどう扱うかといったことに考える時間をさけたんじゃないかな かといって、降順の対象を昇順でひくために、フィールドにマイナスつけて update するのは思い浮かんだかな、、どうだろ。
来年は
準備は高速にできるようになったので、サービスの構成からボトルネックの解消の仕方はアプリケーションじゃなくてミドルウェアからという 場合もあることを意識して本線に行きたいと思う。 DB 周りの知識は特にindex 周りの制約などはしっかり理解しておく。というか、記事書いておこう。(ちゃんと公式読んで書く)