August 18, 2026·Engineering·4 min read

遅かったのはデータベースではなく、往復の回数だった

業務用ダッシュボードの初回表示が10.4秒。データ量のせいだと思って測ったら、データベース側は合計1.3秒しかかかっていなかった。残り9秒を食っていたものと、直す順番の話。

遅かったのはデータベースではなく、往復の回数だった

現場で毎日使う画面を作っていて、「読み込み中……が長い」とフィードバックをいただいた。 測ると、最初の表示までに 10.4秒かかっていた。

扱っている数字は10万行に届く。なのでデータが多いせいだと思った。 集計を軽くするか、事前に計算しておくか。直す場所はもう決めたつもりでいた。

測ったら違った。

疑う前に、分解して測る

表示までの処理を段ごとに切って、それぞれ何秒かかっているかを取った。

データベース側は全部足して1.3秒だった。 残りの9秒はデータを取りに行く往復で消えていた。

1回の往復には、中身の重さと関係なく固定の費用がかかる。名乗って、確認されて、通されて、帰ってくる。 画面に必要な数字は何種類かに分かれていて、それぞれ別に取りに行っていた。 1本ずつは速い。ただ本数が多いので、合計は本数のほうで決まっていた。

夜のオフィスビルのロビーに、同じ形の入退館ゲートが奥まで一列に並んでいる
1本ずつは速い。合計を決めていたのは本数のほうだった。

速い問い合わせを何本も投げる構成は、遅い1本より遅くなることがある。 ここは自分でも意外だった。

やったことは2つ

ひとつは、中継を通る回数を減らしたこと。 最初に1回だけ通行証にあたるものを受け取り、以降しばらくは直接取りに行く形にした。

もうひとつは、2回目以降の見せ方を変えたこと。 前回の結果を手元に残しておいて、まずそれで画面を描く。新しいものは裏で取ってきて差し替える。 人が待つのは描画までで、更新は待たせない。

結果はこうなった。

  • 初回の表示: 10.4秒 → 2.8秒
  • ページ間の移動: 0.83秒
  • 同じ条件をもう一度開いたとき: 即時

集計の中身には一行も手を入れていない。

本当にクエリが悪い場所もあった

同じ画面の中に、どこに余っていてどこで足りないかを突き合わせる集計がある。 これは1ヶ月ぶんで 72秒かかっていて、画面から呼べる状態ではなかった。

中身を見ると、品目ごとに「直近の記録を1件だけ取る」を対象の数だけ繰り返していた。 考え方は素直だが、繰り返しの回数がそのまま時間になる。

これをデータベース側で「まとめて並べ替えて、各グループの先頭だけ取る」1回の処理に置き換えたら 2.3秒になった。 あとから月ごとの表に切り出して索引も張った。

つまり同じ画面に両方あったことになる。往復の回数が効いている場所と、問い合わせ自体が悪い場所。 どちらも症状は「遅い」で、測るまで区別がつかなかった。

直す順番は初回から決める

改善幅がいちばん大きいのは、2回目以降を即時にしたところ。 ただ実際に効いたのは初回の10.4秒を縮めたほうだと思う。

人はそこで「このツールは重い」と判断する。一度そう思われると、あとで速くしても評価は戻らない。 逆に最初さえ我慢できる速さなら、残りは多少雑でも「速い」と言われる。

コンクリートの上に置かれたストップウォッチ。針は0から動き出したばかりのところにある
評価が決まるのは、この数秒のあいだ。

なので最適化の順番は、平均でも合計でもなく初回から決めることにした。

まとめ

  • 遅いと指摘をもらったら、直す前に分解して測る。今回はデータベース側が1.3秒しかなかった
  • 効いていたのは往復の回数。速い問い合わせを何本も投げる構成は、遅い1本より遅くなる
  • ただし本当にクエリが悪い場所もある(72秒 → 2.3秒)。測らないと区別できない
  • 直す順番は平均ではなく初回から

直したあとの数字より、直す前に「たぶんデータ量のせいだ」と決めていた自分のほうが問題だったと思う。 測る前の見立ては外れる。しかも外れたことに気づかないまま、関係ない場所を速くしてしまう。