ふくふくHukuhuku Inc.
EP.02Performance 14分公開: 2026-09-16

ボトルネックの見つけ方 ── レイヤーを切り分ける

遅い原因はアプリ・DB・ネットワーク・ディスクのどこかにあります。全部を同時に疑うと進まないので、症状から候補を絞る手順と、各レイヤーの見分け方を整理します。

#パフォーマンス#切り分け#SRE#デバッグ
執筆 / 監修
松尾 亮合同会社ふくふく 代表社員

データ基盤・データパイプライン構築 / BI / 生成 AI 活用支援を専門とするエンジニア (28 年)。 本記事は AI 利用ポリシーに基づき、生成 AI の補助で執筆 → 人間が監修・編集して公開しています。

プロフィール詳細
シェア

計測して「遅い」と分かったら、次はどこが遅いかです。 は必ずどこか一箇所にあり、そこ以外をいくら速くしても全体は変わりません。

この回は切り分けの手順を扱います。全部を同時に疑うと進まないので、症状から候補を絞るという進め方をします。

1. まず「計算しているのか、待っているのか」

最初の分岐はここです。遅さには2種類しかありません。計算に時間がかかっているか、何かを待っているかです。判別は CPU の使用状況で概ねつきます。

最初の切り分け
CPU遅い理由疑う場所
高い(張り付いている)計算しているアルゴリズム、無駄な繰り返し、
低いのに遅い待っているディスク、ネットワーク、
高いが処理は進むそもそも処理量が多い件数を減らせないか

実務で圧倒的に多いのは待っている側です。業務システムの処理は、計算そのものより外部への問い合わせが時間を占めることがほとんどだからです。CPU が低いのに遅いなら、まず待ちを疑ってください。逆に言えば、アルゴリズムの改善から入るべき場面は思ったより少ないということでもあります。計算量の議論は魅力的ですが、実際の ボトルネック が待ちにあるなら、そこを詰めても全体は動きません。

「サーバーを増やす」が効かないとき

待ちが原因の場合、台数を増やしても改善しません。むしろ待ち先(DBなど)への負荷が増えて悪化することがあります。増やす前に、何を待っているかを確認してください。

2. 回数を数える

待ちが疑われるとき、最初に見るべきは時間ではなく回数です。1回あたりが十分速くても、回数が多ければ積み上がります。

外部への問い合わせ回数と合計時間を記録する
Python
import timefrom collections import defaultdictfrom contextlib import contextmanager
stats = defaultdict(lambda: {"count": 0, "total": 0.0})

@contextmanagerdef measure(label):    start = time.perf_counter()    try:        yield    finally:        elapsed = time.perf_counter() - start        stats[label]["count"] += 1        stats[label]["total"] += elapsed

def report():    print(f"{'処理':22s} {'回数':>6s} {'合計(秒)':>10s} {'1回平均(ms)':>13s}")    for label, s in sorted(stats.items(), key=lambda x: -x[1]["total"]):        avg_ms = s["total"] / s["count"] * 1000        print(f"{label:22s} {s['count']:6d} {s['total']:10.3f} {avg_ms:13.2f}")

この形で出すと、「1回は速いが回数が多い」という構造がすぐ見えます。1回2ミリ秒でも、1000回呼べば2秒です。個々の速さだけを見ていると、この積み上げを見落とします。

回数が多い場合の代表的な原因が で、EP.5 で扱います。一覧を取ったあと、各行の関連データを1件ずつ問い合わせてしまう構造です。開発時のデータが少ないと気づかず、本番で顕在化するのが厄介な点です。

3. レイヤーごとの見分け方

待ち先の候補は限られています。それぞれ特徴的な症状があるので、そこから絞ります。

レイヤー別の症状と確認事項
レイヤー特徴的な症状確認すること
アプリCPUが張り付く。件数に対して非線形に遅くなる で処理単位の内訳を出す
DB特定のクエリだけ遅い。件数増加で急に悪化 を見る(EP.3)
ネットワーク1回あたり一定時間かかる。回数に比例往復回数を数える
ディスク初回だけ遅い。メモリに乗ると速い読み込み量とキャッシュの効き
排他制御同時実行を増やすと悪化するロック競合 の有無
外部サービス不定期に跳ねる。自分たちの変更と無関係呼び出し先の応答時間を分離して計測

最後の「外部サービス」は、切り分けの観点で特に重要です。自分たちのコードを一切変えていないのに遅くなったなら、外部要因を最初に疑うべきです。ここを分離して計測していないと、自分たちのコードを延々と調べることになります。

4. 件数との関係を見る

もうひとつ強力な手がかりが、件数を変えたときにどう変わるかです。処理時間の伸び方から、構造上の問題が見えます。

件数と時間の関係
件数を10倍にしたとき時間の伸び示唆
ほぼ変わらない一定件数と無関係な固定コスト(接続確立など)
約10倍比例正常。1件あたりの処理を速くするか、件数を減らす
100倍以上急激構造的な問題。総当たりや N+1問題 を疑う

3行目が見つかったら最優先です。件数が増えるほど破綻が加速するため、いま我慢できていても近い将来に停止します。1件あたりの最適化ではなく、構造を変える必要があるという判断になります。

件数を変えて、伸び方を確かめる
Python
import time

def measure_growth(func, sizes):    """件数を変えて実行し、時間の伸び方を出す。"""    base = None    for n in sizes:        data = list(range(n))        start = time.perf_counter()        func(data)        elapsed = time.perf_counter() - start
        if base is None:            base = elapsed or 1e-9            ratio = 1.0        else:            ratio = elapsed / base        print(f"  件数 {n:6d}  時間 {elapsed:8.4f}秒  初回比 {ratio:8.1f}倍")

# 総当たり(件数の2乗で増える)def quadratic(data):    return sum(1 for a in data for b in data if a == b)

measure_growth(quadratic, [100, 200, 400, 800])

件数を2倍にして時間が4倍になるなら、2乗で増えています。このまま件数が10倍になれば100倍です。実測でこの形が出たら、アルゴリズムの見直しが必要だと判断できます。

5. 切り分けの順序

以上をまとめると、次の順で進めるのが効率的です。

  1. 1全体の内訳を出す — アプリ / DB / 外部 / ネットワークの割合
  2. 2CPUが高いか低いかを見る — 計算しているのか待っているのか
  3. 3回数を数える — 1回あたりではなく合計で見る
  4. 4件数との関係を確かめる — 比例か、それ以上か
  5. 5最大の割合を占める箇所だけを深掘る — 他は後回し

5番目を守れるかが分かれ目です。調べていると細かい非効率が次々と目につきますが、全体の1%を占める箇所を半分にしても、全体は0.5%しか改善しません。目についたものを直したくなる気持ちを抑えて、割合の大きい順に処理してください。

「直せる」と「効く」は別

簡単に直せる非効率ほど目につきますが、効くかどうかは割合で決まります。直しやすさではなく、全体に占める割合で優先順位をつけてください。これは EP.1 の計測の話と一続きです。

6. 切り分けができる状態を保つ

最後に、切り分けを毎回ゼロから始めなくて済むようにする話です。障害のたびに手探りになるなら、それは切り分けの技術ではなく観測の設計の問題です。

は、外から観測できる情報だけで内部の状態を説明できる状態を指します。監視が「決めた異常を見張る」のに対し、想定していなかった問題も追えることを目指す考え方です。切り分けに毎回時間がかかるなら、ここに投資する価値があります。

具体的には、レイヤーごとの所要時間が常に記録されている状態を作ります。事後に「どこが遅かったのか」を問える形にしておけば、切り分けの前半をまるごと省略できます。

ここまでのまとめ

最初の分岐は計算しているか、待っているか。待ちなら回数を数える件数との関係を見れば構造的な問題が分かる(比例を超えていたら最優先)。深掘るのは割合が最大の箇所だけ。次回から、最も当たりやすい候補である SQL に入ります。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp