毎朝7時に動いていた集計スクリプトが、先月あたりから途中で止まるようになった。ログを見ると「最大実行時間を超過しました(Exceeded maximum execution time)」。コードは1行も変えていません。変わったのは扱うデータの量だけです。
この時点で相談されると、たいてい2つの誤解がセットで出てきます。「Workspace の有料プランなら上限が延びるはず」と、「処理を速くすれば直る」です。どちらも今は成り立ちません。
6分は延ばせない
まず前提を固めておきます。スクリプト1回あたりの実行時間の上限は6分で、無料の個人アカウントでも Google Workspace でも同じです。かつて Workspace 系アカウントに30分の枠があった時期がありますが、これは廃止されています。プランを上げても、管理コンソールを探しても、この6分は動きません。
関連する上限もあわせて把握しておくと、後の判断が速くなります。
| 項目 | 個人アカウント | Google Workspace |
|---|---|---|
| スクリプト1回の実行時間 | 6分 | 6分 |
| トリガー実行時間の1日合計 | 90分 | 6時間 |
| 同時実行数 | 30 | 30 |
| UrlFetch の1日あたり呼び出し | 20,000 | 100,000 |
| スクリプトあたりの時間主導トリガー数 | 20 | 20 |
見落とされやすいのは2行目です。1回6分に収まっていても、トリガーで動かす処理の合計が1日の枠を食い切ると、その日の残りは動きません。「途中まで動いて止まる」のではなく「そもそも起動しない」形で出るため、実行時間超過とは症状が違います。ログに何も残らないときは、まずこちらを疑ってください。
詰まっているのは計算ではないことが多い
「処理を速くすれば直る」が外れるのは、6分を食っているのが計算ではないからです。
Apps Script が遅くなる原因は、圧倒的にスプレッドシートとの往復です。ループの中で getValue() や setValue() を1セルずつ呼んでいると、1回ごとにサービス境界をまたぐ通信が発生します。行数が1,000から10,000に増えれば、往復も10倍になる。ロジックそのものは一瞬で終わっているのに、待ち時間だけが積み上がっていきます。
// 往復が行数ぶん発生する
for (let i = 2; i <= lastRow; i++) {
const v = sheet.getRange(i, 3).getValue();
sheet.getRange(i, 4).setValue(v * 1.1);
}
// 往復は2回で済む
const values = sheet.getRange(2, 3, lastRow - 1, 1).getValues();
const result = values.map(([v]) => [v * 1.1]);
sheet.getRange(2, 4, result.length, 1).setValues(result);
外部 API を呼んでいる場合も同じ構造です。1件ずつ UrlFetchApp.fetch() を呼んでいるなら、fetchAll() でまとめられないかを先に見ます。
ここを直すだけで6分に収まるケースは珍しくありません。分割実行の仕組みを作るのは、まとめ読み・まとめ書きに直したあとの話です。順番を逆にすると、遅いままの処理を分割しただけの、複雑で遅い仕組みが残ります。

分割で粘るときの型
まとめ読み・まとめ書きに直してもなお6分に収まらないなら、分割実行に進みます。考え方は単純で、「どこまで終わったか」を外に記録して、次の実行が続きから始める構造にします。
- 処理開始時刻を記録し、経過が4分30秒程度を超えたらループを抜ける(6分ぎりぎりまで粘らない)
- 中断した位置を
PropertiesServiceに保存する - 未処理が残っていれば、
ScriptApp.newTrigger()で数分後の単発トリガーを仕込んで自分を終了する - 次の実行は保存した位置から再開する
- 全件終わったら記録を消し、後片付けとして自分が作ったトリガーを削除する
5番目を忘れると、スクリプトあたり20個というトリガー上限に静かにぶつかります。しばらく動いていたのに突然トリガーが作れなくなる、という形で表面化するため、原因にたどり着くまで時間がかかる部類の不具合です。
この型が向いているのは、処理が行単位に独立していて、途中で止まっても中途半端な状態が残らない場合です。1行ずつ独立した転記や集計はここに当てはまります。
粘っても意味がないとき
一方で、分割実行を入れても解決にならないパターンがあります。判断の材料は処理時間ではなく、次の3点です。
中断が業務的に許されない処理。在庫の引き当てや請求データの確定のように、途中まで反映された状態が実害になるものは、分割してはいけません。Apps Script には複数の処理をまとめて取り消す仕組みがないため、失敗したときに手で戻すことになります。
データ量が増え続ける前提の処理。いま6分を分割で凌いでも、半年後には分割数が倍になります。分割は時間を買っているだけで、増加そのものは止まりません。1年後の件数を見積もって、そこでも成立するかを確認してください。成立しないなら、置き場所をスプレッドシートの外に移す設計に切り替える時期です。
作った人以外が直せない処理。分割実行を入れると、コードは目に見えて複雑になります。もともと引き継ぎが難しかったスクリプトは、ここでさらに触れないものになります。この状態のまま放置されたスクリプトがどう問題化するかはApps Script が保守されなくなるときで扱っています。
3つのどれかに当てはまるなら、粘る先を変えたほうが早い。スプレッドシートを表計算として使い続けるべきか、データの置き場所ごと見直すべきかの判断軸はExcel 運用をいつシステム化に切り替えるかにまとめています。外部 API を呼ぶスクリプトを増やす前の点検はApps Script の外部通信を棚卸しするを参照してください。
次にやること
止まっているスクリプトがあるなら、**まず getValue() と setValue() がループの中にあるかどうかだけ見てください。**あれば、そこが原因である可能性が高く、分割実行を検討する前にやることが残っています。
ループの外に出しても収まらない場合は、そのスクリプトが上の3条件に当てはまるかを確認します。当てはまらなければ分割実行で数年は持ちます。当てはまるなら、粘るための工数を作り直しに振り替えたほうが、結果的に安く済みます。
既存スクリプトの棚卸しや、どこまでを Apps Script で維持しどこから別の作りに移すかの切り分けは、グリームハブの IT・Google Workspace 無料相談で承っています。データ量の伸び方や業務の依存関係によって結論は変わるため、個別にご相談ください。お問い合わせからどうぞ。