速くしても全体はそこまで速くならない
読了目安 約3分
アムダールの法則で改善の上限を見積もり、ボトルネックが順に移動していく理由を理解します。
この章の目次
いちばん遅いクエリを 10 倍速くしても、全体は 10 倍になりません。 どこまで速くなるかは、そのクエリが全体の何割を占めるかで決まります。
改善の上限
全体のうち一部だけを速くしたとき、全体が何倍速くなるかを表す式があります。
- :速くする部分が、全体の時間に占める割合
- :その部分を何倍速くするか
- :その結果、全体が何倍速くなるか
全体の 60 パーセントを占めるクエリを 10 倍速くするなら、 、 です。
これがアムダールの法則です。 残りの 40 パーセントは 1 ミリ秒も減らないので、そこが天井を作ります。
| (占める割合) | |||
|---|---|---|---|
| 0.2 | 1.11 | 1.22 | 1.25 |
| 0.6 | 1.43 | 2.17 | 2.50 |
| 0.9 | 1.82 | 5.26 | 10.0 |
占める割合が小さいものは、無限に速くしても意味がありません。
だから合計時間の順に見る
ここから、計測結果の読み方が決まります。 1 回が最も遅いクエリではなく、呼ばれた回数を掛けた合計時間が最大のものから直します。
1 回 500 ミリ秒でも 1 分に 1 回しか呼ばれないクエリより、1 回 5 ミリ秒でも毎秒 200 回呼ばれるクエリのほうが、全体に占める割合は大きくなります。 alp とスロークエリログを合計時間順に並べるのは、f の大きいものを先に見つけるためです。
例外は、規定の応答時間を超えて失格や減点になる場合です。合計時間が小さくても、規定を破っているものは先に直します。
犯人は動く
f の大きいものを直すと、その部分の割合は小さくなります。 すると次に大きいものが繰り上がり、ボトルネックが移動します。
典型的な移り方です。
- 最初はアプリケーションの CPU
- インデックスと N+1 を解消すると、データベースとの往復そのものが支配的になる
- データベースを別のホストに分けると、今度はそのホストの CPU が先に飽和する
大事なのは、移動したあとの構成では以前の計測が無効になっていることです。 1 つ直したら測り直します。 前のラウンドの犯人を追い続けると、すでに f が 5 パーセントしかないものを磨くことになります。
直列部分は消えない
を無限大にしたときの上限は です。 どれだけ手を尽くしても、直列に残る部分より速くはなりません。
ISUCON では、次のようなものが直列部分として残ります。
- パスワードのハッシュ計算のような、仕様上省けない計算
- 1 つのロックで守られていて同時に 1 つしか動けない区間
- 依存関係があり、前の結果が出ないと始められない処理
前の 2 つは削れない固定費として受け入れます。 3 つ目は、依存していないなら並べれば消えるので、真っ先に疑う価値があります。
試してみよう
前章の計測の続きです。 データベースのサービス需要 9 ミリ秒の内訳が、次のようだったとします。
| 中身 | 1 件あたり |
|---|---|
| インデックスが無く全件走査しているクエリ | 6 ミリ秒 |
| その他のクエリ | 3 ミリ秒 |
- 全件走査のクエリが占める割合 はいくつですか
- そのクエリをインデックスで 20 倍速くしたとき、データベース全体は何倍速くなりますか
- 上限件数は 222 件/秒からいくつに動きますか
答えを見る
は 0.67。 倍。 は 9 ミリ秒から 3.3 ミリ秒に下がるので、上限は 222 件/秒から約 600 件/秒へ動きます。
20 倍速くしても全体は 2.7 倍です。 それでも上限が 3 倍近くへ動くのは、そこが全体の 3 分の 2 を占めていたからです。