1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Salesforce にてレコードの取得や更新に関する開発をしていると、ときどきガバナ制限に遭遇します。

ガバナ制限とは何か、どのような場合にどう回避するかを解説します。

ガバナ制限とは

Salesforce はマルチテナント環境で動作しており、複数の組織が同一のサーバーリソースを共有しています。ガバナ制限とは、ある組織のコードや処理が共有リソースを占有しないよう Salesforce ランタイムが強制する上限値のことです。

制限を超えると、System.LimitException がスローされ、処理が強制終了します。

Apex ガバナ制限

開発中によく遭遇する主要な制限です。同期処理と非同期処理(Batch Apex など)で上限が異なります。

DML(Data Manipulation Language)とは、レコードの挿入・更新・削除・アップサート操作のことを指します。

説明 同期の制限 非同期の制限
SOQL クエリの発行数 100 200
SOQL で取得できる総レコード数 50,000 50,000
DML ステートメント数 150 150
DML で処理される総レコード数 10,000 10,000
CPU 時間 10,000 ミリ秒 60,000 ミリ秒
ヒープサイズ 6 MB 12 MB

参考: Apex ガバナ制限 | Salesforce Developer の制限および割り当てクイックリファレンス

SOQL の制限

SOQL クエリの結果件数は実行する文脈によって上限が異なります。

文脈 上限
API 経由(REST/SOAP) 1 リクエストあたり 2,000 件
Apex 内(トランザクション合計) 50,000 件

参考: SOQL および SOSL の検索クエリの制限 | Salesforce Developers

フロー(Flow)のガバナ制限

公式ドキュメントには次のように記載されています。

Apex で適用されるトランザクション単位の制限により、フローが制限されます。

フローも Apex と同じトランザクション単位の制限が適用されます。

説明 制限値
発行された SOQL クエリの総数 100
DML ステートメントの合計数 150
DML で処理されるレコードの合計数 10,000
Salesforce サーバーの最大 CPU 時間 10,000 ミリ秒
ヒープサイズ 6 MB

参考: トランザクション単位のフローの制限 | Salesforce Help

Apex での対応案

SOQL for ループで大量レコードを逐次処理する

通常のコレクション代入では、すべてのレコードをヒープに読み込みます。大量データを扱う場合、ヒープサイズ制限を超えることがあります。

Database.QueryLocator を用いた SOQL for ループでは、レコードをチャンク単位で逐次処理するため、ヒープの消費を抑えられます。

for (Account acc : [SELECT Id, Name FROM Account]) {
    // レコードをまとめてヒープに持たずに逐次処理できる
}

たとえば、Lightning Web Components から呼び出す Apex メソッド内でこのパターンを活用できます。

参考: コンポーネントへの Apex メソッドの公開 | Salesforce Developers

ただし、1 トランザクションあたり 50,000 件の上限は変わりません。50,000 件を超えるデータを扱う場合は、Batch Apex または Data Loader を検討してください。

Apex Batch を使う

一度に大量のレコードを処理する必要がある場合は Batch Apex を使います。

Batch Apex は Database.Batchable インターフェースを実装することで利用できます。execute の 1 チャンクあたりのデフォルトは 200 件で、最大 2,000 件まで指定可能です。

public class MyBatchJob implements Database.Batchable<SObject> {

    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id, Name FROM Account');
    }

    public void execute(Database.BatchableContext bc, List<SObject> scope) {
        List<Account> accounts = (List<Account>) scope;
        for (Account acc : accounts) {
            acc.Name = acc.Name + '_updated';
        }
        update accounts;
    }

    public void finish(Database.BatchableContext bc) {
        // 全チャンク完了後の後処理(メール通知・後続ジョブの起動など)
    }
}

start メソッドで使用する Database.getQueryLocator は、通常の SOQL が持つ 50,000 件制限の対象外で、最大 5,000 万件まで取得できます。大量レコードの一括処理に適しています。

Batch Apex は非同期処理のため、ガバナ制限が緩和されます。具体的には、SOQL 発行数が 100 から 200 に、CPU 時間が 10,000 ms から 60,000 ms に拡大されます。

MyBatchJob job = new MyBatchJob();
Database.executeBatch(job, 200); // 第2引数でチャンクサイズを指定

参考: 非同期 Apex | Trailhead

大量データ操作への対応案

Data Loader を使う

Apex トランザクションの 50,000 件上限を超える大量データを操作する場合は Data Loader の利用を検討してください。

Data Loader は Salesforce が提供する公式クライアントツールで、CSV ファイルをもとにレコードの一括挿入・更新・削除・エクスポートができます。Apex トランザクションを経由しないため、Data Loader はトランザクション単位のガバナ制限の対象外です。

参考: Data Loader | Salesforce Developers

主なユースケース

  • 初期データ投入(数十万〜数百万件規模の一括 insert)
  • 定期的な外部システムとのデータ同期
  • 大量レコードの一括削除

1 回の操作で処理できる上限は 5,000,000 件です。5,000,000 件を超える場合はファイルを分割して複数回実行します。

API 経由で自動化したい場合は Bulk API 2.0 も有効です。バックグラウンドで非同期処理されるため、大量レコードのインポート・エクスポートに適しています。

参考: Bulk API および Bulk API 2.0 の制限および割り当て | Salesforce Developers

フローでの対応案

DML をループ外に出す(一括処理)

レコードトリガーフローなどでは、ループ内の「レコードを作成/更新」要素をループ外に移動することで、DML の消費を大幅に削減できます。

スケジュールトリガーフローでは、条件に合致したレコードに対する処理を記述するだけでよい場合が多いため、ループ等の複雑な処理を書く必要がないかもしれません。

参考: トランザクションでのフローの一括処理 | Salesforce Help

参考: スケジュールトリガーフローに関する考慮事項 | Salesforce Help

おわりに

ガバナ制限はマルチテナント環境を健全に保つための仕組みです。制限に達したときは設計を見直すと、より堅牢な実装に近づけられます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?