早朝のオフィスで、まだ終わらないバッチの進み具合を画面で見守りながら、どこで時間がかかっているのか考えている保守運用担当者

遅いバッチは直す前に測る|ボトルネックを見つける5つの手順

朝8時、チャットに一言届きます。「今日の売上集計、まだ見られないんですけど」 確認すると、夜中の集計バッチがまだ動いている。数年前は2時に始まって3時前には終わっていたのに、最近は少しずつ遅くなって、とうとう始業に間に合わなくなった——。

「どこが遅いの?」と聞かれても、すぐには答えられない。とりあえずサーバーを増強するか、それとも怪しそうなSQLを直してみるか。気持ちは焦りますよね。

でも、ここでひと呼吸おいてください。答えに詰まるのは、あなたの力不足ではありません。まだ誰も測っていないから、わからないだけです。遅いバッチは、直す前に測る。それだけで、打つ手はぐっと絞れます。

この記事では、遅いバッチのボトルネックを見つけるための計測の順番を整理します。特別な監視ツールは使いません。Linux に標準で入っている(または入れやすい)コマンドと、ログへの一行の追記だけで進めます。

結論:遅いバッチは、①全体の時間と「いつから遅いか」を記録する → ②区間ごとに時刻を打って、どこが長いかを見る → ③その区間が「計算」で遅いのか「待ち」で遅いのかを見分ける → ④件数と時間の関係を見る → ⑤直す前の数字を「基準値」として残す の順で測ります。ボトルネックはたいてい1か所です。全体を速くしようとせず、いちばん長い区間を1つ見つけられれば十分です。

なお、以下のコマンドは一般的な Linux 環境を前提にしています。ディストリビューションやバージョンで、入っているコマンドや出力の形が変わります。本番で使う前に、お使いの環境のマニュアル(man コマンド)で確認してください。

何が起きているか:バッチは「ある日突然」ではなく「少しずつ」遅くなる

障害と違って、遅くなるバッチにはアラートが鳴りません。毎晩ちゃんと終わっているうちは、誰も時間を気にしないからです。

だから、直す前に測ります。ここは現場でも、つい飛ばしてしまいやすいところです。順番を決めておきましょう。

遅いバッチのボトルネックを見つける5つの手順

バッチの処理を左から順に4つの区間に分けた横長の帯で、3つ目の「集計」の区間だけが極端に長く、虫眼鏡で注目されている図
区間ごとに時刻を打つと、時間の大半を使っている「1か所」が見えてきます

① 全体の時間と「いつから遅いか」を記録する

まずは、バッチ全体が何分かかっているかを、数字でつかみます。「最近遅い気がする」を「先月は45分、今月は2時間40分」に変えるだけで、相談も判断もしやすくなります。

ここで「いつから遅くなったか」も確かめておきます。ある日を境に急に遅くなったなら、その日の変更(リリース、設定変更、データ移行、他のバッチの時刻変更)がまず疑わしい候補です。少しずつ遅くなっているなら、データ量の増加を疑います。

② 区間ごとに時刻を打って、どこが長いかを見る

いちばん効くのがこの手順です。バッチを「抽出 → 変換 → 集計 → 送信」のような区間に分けて、それぞれの開始と終了の時刻をログに出します。

シェルスクリプトなら、区間の境目に1行ずつ足すだけです。

echo "$(date '+%F %T') 集計 開始"
# ……集計の処理……
echo "$(date '+%F %T') 集計 終了"

PHP や Python のバッチでも、区間の前後で時刻と処理件数をログに出すだけで十分です。並べてみると、たいていこうなります。

区間所要時間全体に占める割合
抽出2分約1%
変換5分約3%
集計150分約94%
送信3分約2%
合計160分100%

この場合、抽出や送信をどれだけ速くしても、全体はほとんど縮みません。直すべきは「集計」の区間だけだとわかります。

ログの追記も、小さいとはいえ改修です。いきなり本番のファイルを書き換えず、検証環境で動きを確かめてから、いつもの手順で反映します。ログの入れ方のコツは改修時にログを仕込む|あとから原因を追えるログの残し方で整理しています。

③ その区間が「計算」で遅いのか「待ち」で遅いのかを見分ける

長い区間が見つかったら、次はなぜ長いのかを見分けます。ざっくり分けると、遅さには2種類あります。

見分けるいちばん簡単な手がかりは、手順①でメモした time の数字です。

たとえば real 160分 に対して user 6分・sys 1分 なら、CPUを使っていたのは全体の5%足らず(7 ÷ 160 ≒ 4.4%)。残りは何かを待っていた計算です。

待ちの相手を絞るには、バッチが動いている時間帯に、次のコマンドで様子を見ます。

CPUもディスクも落ち着いているのに時間がかかっているなら、外部API・ファイル転送・ロック待ちのように、サーバーの外や別の処理を待っている可能性が高まります。CPUの見方はCPU使用率が高いときの原因プロセス特定手順、数字の読み方はロードアベレージの正しい読み方も参考になります。

④ 件数と時間の関係を見る

区間のログに処理件数も出しておくと、もう一歩踏み込めます。過去の数か月分を、件数と所要時間で並べてみてください。

この見分けがつくと、「サーバーを増強すれば済むのか、書き方を直すべきなのか」を落ち着いて説明できるようになります。

⑤ 直す前の数字を「基準値」として残す

最後に、いま測った数字をそのまま残しておきます。完璧な資料でなくてかまいません。

項目書く内容
全体の時間例:160分(real)、user 6分・sys 1分
区間ごとの時間例:抽出2分/変換5分/集計150分/送信3分
処理件数例:20万件(前年同月は10万件)
測った日・条件日付、同じ時間帯に動いていた処理
いちばん長い区間例:集計(ほぼ待ち。DBの応答待ち)
次に試すこと例:集計のSQLを EXPLAIN で確認

この基準値があると、直したあとに同じ条件で測り直して比べることができます。「たぶん速くなった」ではなく「160分が18分になった」と言えるのは、直す前の数字があるからです。効果の確かめ方は直したつもりが直っていない|改修の効果を確かめる4つの手順で整理しています。

具体例:月次の売上集計バッチが始業に間に合わない

冒頭のバッチを、この順番で測ってみます。

  1. 全体の時間:ログを並べると、1年前は45分前後。それが毎月少しずつ伸びて、今月は160分。ある日を境に急に、ではなく、少しずつ遅くなっていた。
  2. 区間ごとの時刻:検証環境で動作を確かめてから、区間の境目に時刻を出す行を追加。翌月の実行で、集計の区間だけで150分(全体の約94%)かかっているとわかった。
  3. 計算か待ちか:time の結果は real 160分 に対して user + sys が7分ほど。ほとんど待っている。実行中の top でもCPUは低く、DBのスロークエリログに、同じ形の SELECT が大量に記録されていた。
  4. 件数と時間:処理件数は1年前の10万件から20万件へ約2倍。一方、集計の時間は約4倍。ループの中で1件ごとに、インデックスの効いていない条件でテーブルを検索している書き方が見つかった。
  5. 基準値:ここまでの数字を1枚にまとめ、「集計区間のループ内検索が原因。サーバー増強ではなく、検索条件へのインデックス追加を検証する」と記録した。

検証環境でインデックスを追加して同じ件数で測ると、全体は160分から18分に。本番への反映は、いつもの変更手順に沿って別の日に行いました。サーバーを増強していたら、費用をかけたうえで、ほとんど速くならなかったかもしれません。

影響:測っておくと、何が変わるか

明日やること:いちばん気になるバッチの「全体の時間」を並べる

一度に全部やらなくて大丈夫です。今日はここだけ確認できれば十分です。

  1. 遅くなって困っているバッチを1本だけ選ぶ。
  2. 過去のログや出力ファイルの更新日時から、ここ数か月の所要時間を並べる。
  3. 「ある日を境に急に遅くなった」のか「少しずつ遅くなった」のかを見る。
  4. 次の実行で time を付けて、real・user・sys をメモする段取りをする。

ここまでで30分ほど。区間ごとのログ追加は、検証環境で確かめてから、別の日に進めればかまいません。

遅いバッチ 計測チェックリスト

全部に○が付かなくても大丈夫です。わかったところから埋めていきましょう。

全体をつかむ

区間を見る

理由を見分ける

記録する

よければ、こちらも

遅いバッチの計測は、バッチの正体の解読や、改修の効果確認とひと続きの作業です。あわせて読むと、測った数字が次の判断に生きてきます。

朝の明るいオフィスで、予定より早く終わったバッチを確認し、出社してきた同僚と笑顔で言葉を交わす保守運用担当者

毎晩のバッチが少しずつ遅くなっていくのに気づいて、なんとか朝に間に合わせようとしてきたこと自体が、もう立派な保守の仕事です。 まずは1本だけ、ここ数か月の所要時間を並べてみてください。数字がひとつ見えるたびに、「なんとなく遅い」は「ここを直せばいい」に変わっていきます。

ほかの実務ヒントは記事一覧からどうぞ。保守運用の小さな備えを、メールでも少しずつお届けしています。