🔩 ねじき教室 Go と Web の教室

振り返りと、残っているもの

読了目安 約3分

7 倍までの道のりを一覧で確認し、まだ手をつけていない場所を見ます。

この章の目次

スコアの推移

何をしたかスコア前回比
初期実装6072
インデックスを足した10319+70 %
ランキングの N+1 を消した10434+1 %
参加者詳細の N+1 を消した10105−3 %
CSV 入稿をまとめた35888+255 %
取る量を減らした38522+7 %
公開鍵・Debug・Logger41693+8 %
テナントの引き直しをやめた44139+6 %

大きく動いたのは 2 回だけです。 インデックスと、CSV 入稿の書き込みをまとめたところです。

どちらも、計測が回数や行数の異常を指していた場所でした。 一方、コードだけ読んで「これは N+1 だ」と判断した回は動きませんでした。

いまのアクセスログ

テキスト
+-------+--------+-------------------------------------------+-------+-------+----------+
| COUNT | METHOD |                    URI                    |  AVG  |  MAX  |   SUM    |
+-------+--------+-------------------------------------------+-------+-------+----------+
| 22642 | GET    | /api/player/player/[^/]+                  | 0.075 | 1.381 | 1693.848 |
| 10011 | GET    | /api/player/competition/[^/]+/ranking     | 0.102 | 1.344 | 1017.992 |
| 36    | POST   | /api/organizer/players/add                | 2.371 | 9.257 |   85.341 |
| 145   | GET    | /api/admin/tenants/billing                | 0.519 | 8.773 |   75.235 |
| 219   | GET    | /api/organizer/billing                    | 0.327 | 3.969 |   71.587 |
+-------+--------+-------------------------------------------+-------+-------+----------+

参加者の詳細は、平均 0.594 秒から 0.075 秒になりました。 同じ 60 秒で捌けた件数は 1987 件から 22642 件です。

残っているもの

参加者の追加が 1 件 2.4 秒

Go
for _, displayName := range displayNames {
	id, err := dispenseID(ctx)
	if err != nil {
		return fmt.Errorf("error dispenseID: %w", err)
	}
	// 1人ずつ INSERT
}

第 5 章で見たものと同じ形です。 参加者 1 人ごとに MySQL へ書きに行き、1 人ごとに INSERT しています。

請求レポートが大会ごとに集計している

/api/organizer/billing は、テナント内の大会を 1 つずつ回して集計します。 大会ごとにファイルロックを取り、MySQL と SQLite に 1 クエリずつ投げています。

大会が終了していれば、請求額はもう変わりません。 終了時に計算して保存しておけば、参照は取り出すだけになります。

データの置き場所そのもの

アプリが使う CPU の 4 割は、SQLite の行読み出しです。 テナント DB を MySQL に寄せると、この形は根本から変わります。

ただし、テナントの数だけあるファイルを 1 つのデータベースに移す作業です。 時間が残っているかどうかで判断が変わります。

1 台で足りているか

いまはアプリ・MySQL・nginx が同じ 1 台に載っています。 2 コアの平均使用率が 6 割、ピークで 9 割です。 その内訳はアプリが 0.78 コア、MySQL が 0.39 コアです。

Part 8 で見たとおり、分けるかどうかは、分けたあとに何が起きるかを見積もってから決めます。

この Part でやったこと

  1. 走らせて、アクセスログとスロークエリログを集計する
  2. 合計時間の上位と、回数や行数が異常なクエリを探す
  3. 直す場所を 1 つ決めて、直して、また走らせる
  4. 効かなかったら粘らずに計測へ戻る
  5. ログに出ない処理は pprof で見る

順番はこれだけです。 どの問題でも変わりません。

過去問はほかにもあります。 Part 6 に挙げた素振りのやり方で、次の問題に同じ手順を当ててみてください。