はじめに
GASは手軽にコードを実行でき、Googleアプリケーションとの連携が簡単にできます。
しかし、コードの書き方によっては処理に時間がかかる場合があります。
しかもGASには実行時間制限(6分)があるため、実装方法でミスをすると、処理が完了しないという事態も起こりえます。
この記事では、処理を早くするテクニックを実例を用いて解説します。
APIの呼び出しは最小限に
Apps Script APIをGASから呼び出す際は気を付ける必要があります。
APIの呼び出しには一定の時間がかかり、これが積み重なるとどんどん処理が重くなっていきます。
特に、ループ文の中でAPIを呼び出す事はなるべく避けるようにしてください。
データの取得や作成は一括でする
スプレッドシートなどからデータを取得する際には、なるべく一度にデータを取得しましょう。データの作成時も同様です。
一行一行処理をするといった場合でも、一行ごとにデータを取得するのではなく、一括取得したデータを配列として取り扱い、処理した後に、一括でデータを作成するほうが高速に動作します。
悪い例
以下の例では、forループの中で各行に対してAPIを呼び出しており、データの取り扱いも不適切です。
function badExample() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1");
var totalRows = sheet.getLastRow();
for (var i = 1; i <= totalRows; i++) {
var range = sheet.getRange(i, 1, 1, 3); // Bad:何度もAPIを呼び出している
var values = range.getValues(); // Bad:個別にデータを取得している
// ここでvaluesを使って必要な処理を行う
range.setValues(values); // Bad:個別にデータを作成している
}
}
良い例
以下の例では、APIの呼び出しやデータの取り扱いが適切になされています。
function goodExample() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1");
var range = sheet.getDataRange(); // Good:APIの呼び出しを最小限にする
var data = range.getValues();// Good:一度に全データを取得
var setData = [] //※2次元配列にしないと反映されない
for (var i = 0; i < data.length; i++) {
// ここでdata[i]を使ってsetDataに追加する
}
range.setValues(setData); // Good:変更後のデータを一度にスプレッドシートに反映
}
処理時間計測
それぞれの例の処理時間をスプレッドシートの行データを増やして比較してみました。
行数 | badExample() | goodExample() |
---|---|---|
10 | 1,905ms | 239ms |
100 | 22,839ms | 447ms |
1,000 | 231,814ms | 592ms |
10,000 | 実行時間制限オーバー | 1,784ms |
badExample関数は、行数が10倍になるたびに、実行時間もほぼ10倍になってますね。1,000行を処理するのに、4分弱もかかりました。
それに比べてgoodExample関数は1万行を超えても2秒以内に処理が完了しています。
まとめ
意外とやってしまいがちなアンチパターンの改善点をまとめました。良きGASライフを!