CPU 制限を回避するための一括レコード処理の例
Apex_CPU_TIME_LIMIT_EXCEEDED エラーを回避する一括処理パターンを使用するようにフローをリファクタリングする方法について説明します。この例は、非効率的なフロー設計と最適化されたフロー設計の違いを示しています。
必要なエディション
| サポートされているエディションを表示する。 |
| 必要なユーザー権限 | |
|---|---|
| Einstein for Flow や Agentforce for Flow など、Flow Builder で使用できるすべてのフロー タイプ、要素、機能を使用してフローを開く、編集、作成、有効化、または無効化する | 「フローの管理」 |
次の例は、ループ内でデータ操作言語 (DML) を実行するフローを、レコードを効率的に処理する一括処理フローに変換する方法を示しています。前後の比較を表示し、フローの一括処理の原則を確認します。
シナリオ
商談が完了したときに実行されるレコードトリガーフローを作成します。成立した商談ごとに、フローは商談チームの各メンバーのフォローアップ ToDo を作成します。フロー:
- すべての商談チームメンバーを取得します。
- 各チームメンバーに割り当てられた ToDo を作成します。
- ユーザーが一度に複数の商談を更新する場合でも効率的に機能します。
- 一括操作中の APEX_CPU_TIME_LIMIT_EXCEEDED エラーを回避します。
Salesforce では、同期トランザクションごとに 10,000 ミリ秒 (10 秒) の 1 つの CPU 時間制限が適用されます。そのトランザクションのすべての自動化要素 (Apex トリガー、フロー、ワークフロールール、プロセス) は同じ予算から利用されます。非効率的なフロー設計によって問題が複雑になります。トランザクションの他の自動化では最初に共有予算が削減され、非効率的なフローでは残りの予算が必要以上に消費されます。
フローの実行順序は、フロー種別によって異なります。この例では、保存前フローよりも後の順序で実行される保存後レコードトリガーフローを使用します。実行順序についての詳細は、「Triggers and Order of Execution」を参照してください。
非効率的なアプローチ: ループ内の DML 操作
この方法では、複数の商談を処理するときに CPU 制限エラーが発生します。
フロー構造: フローは、フェーズが「商談成立」の場合にレコード更新後に実行される商談オブジェクトのレコードトリガーフローで開始します。このフローでは、[レコードを取得] を使用してトリガーレコードの商談チームメンバーを取得し、コレクションをループします。ループ内では、[レコードを作成] 要素でチームメンバーごとに 1 つの ToDo が作成されます。
このアプローチが失敗する理由:
- ループの反復ごとに個別の DML 操作が実行されます。
- チームメンバーが 5 人の商談では、5 つの DML 操作になります。
- ユーザーが一度に 20 件の商談を更新すると、フローは 1 つのトランザクションですべての商談を処理します。
- 20 件の商談 × 5 人のチームメンバー = 1 つのトランザクションで 100 件の DML 操作。
- 100 DML 操作からの累積 CPU 時間がガバナ制限を超えています。
- 結果: Apex_CPU_TIME_LIMIT_EXCEEDED エラー。
効率的なアプローチ: コレクションベースの一括処理
この方法では、量に関係なくレコードを効率的に処理します。
フロー構造: フローは、商談オブジェクトのレコードトリガーフローで開始し、レコードの取得を使用して商談チームメンバーを取得します。フローで ToDo レコード変数と ToDo レコードコレクション変数が作成されます。レコード変数にはフローで現在処理中の ToDo が保持され、レコードコレクションには作成する ToDo が保持されます。フローはチームメンバーをループします。ループ内では、割り当て要素が ToDo レコード変数の値を設定して各 ToDo レコードを作成し、ループ内の現在のチームメンバーに ToDo を関連付けます。別の割り当て要素では、ToDo レコード変数値が ToDo レコードコレクションに追加されます。ループが完了すると、1 つの [レコードを作成] 要素でコレクションのすべての ToDo が作成されます。
なぜこれが機能するのか:
- このループでは、DML 操作を実行せずに ToDo レコードのコレクションが作成されます。
- ループの完了後は 1 つの DML 操作のみが行われます。
- チームメンバーが 5 人の商談では、1 つの DML 操作 (一度に 5 つの ToDo を作成) のみになります。
- ユーザーが一度に 20 件の商談を更新すると、フローで合計 20 件の DML 操作が実行されます (商談ごとに 1 件)。
- CPU 時間消費の大幅な削減。
- 結果: ガバナ制限に達することなくフローが正常に完了しました。
パフォーマンスの比較
| シナリオ | 非効率 (ループ内の DML) | 効率的 (一括処理) |
|---|---|---|
| チームメンバーが 5 人の商談 1 件 | 5 DML 操作 | 1 DML 操作 |
| 20 件の商談 (一括更新) (各チームメンバーは 5 人) | 100 DML 操作 (CPU 制限エラーで失敗する可能性が高い) |
20 DML 操作 (正常に完了) |
| それぞれ 3 人のチームメンバーが含まれる 100 件の商談 (データ読み込み) | 300 DML 操作 (間違いなく失敗する) |
100 DML 操作 (正常に完了) |
一括処理の主要な原則
- ループ内で DML 操作を実行しないでください。ループ中には常にコレクション変数でレコードを収集し、ループの完了後に DML を実行します。
- 最初から一括操作用に設計します。レコードトリガーフローで複数のレコードを同時に処理するとします。
- レコードコレクション変数を使用します。コレクションベースの DML 操作は、個々の操作よりも大幅に効率的です。
- 現実的な量でテストします。1 つのレコードが含まれるデバッグモードでは、一括操作の問題は表示されません。データインポートウィザード、データローダー、または一括更新を使用してテストします。
- パフォーマンスを監視します。デバッグログを確認して、本番で失敗する前にガバナ制限に近づいているフローを特定します。
手順の概要
この例の手順を確認します。順序どおりに操作するか、より具体的な手順を参照するセクションに移動します。
- フローの作成
商談が完了したときに実行されるレコードトリガーフローを設定します。 - リソースの作成
一括処理に必要な変数を作成します。 - チームメンバーの取得
[レコードを取得] 要素を使用して、処理する商談チームメンバーレコードを取得します。 - チームメンバーを確認する決定の追加
決定要素を追加して、チームメンバーがいないときの処理を回避します。 - ループ要素の追加
チームメンバーを反復処理するループ要素を追加します。 - ループ内での ToDo レコードの作成
ループ内の各チームメンバーの TaskRecord レコード変数の項目値を入力します。 - コレクションへの ToDo の追加
一括作成用に各 ToDo レコードを TasksToCreate コレクション変数に追加します。 - ループ後のすべての ToDo の作成
1 つのレコード作成要素を使用して、1 つの操作ですべての ToDo を作成します。 - エラー処理の追加
エラーを取得して報告するように障害管理を設定します。 - 一括データを使用したテスト
一括処理フローをテストするには、一括処理をシミュレーションする必要があります。 - その他の最適化手法
これらの手法を使用して、一括処理フローをさらに最適化します。 - 既存のフローの変換
ループ内のデータ操作言語 (DML) 操作でフローを一括処理パターンに変換します。
フローの作成
商談が完了したときに実行されるレコードトリガーフローを設定します。
-
[フロー] リストビューを開きます。
- [設定] の [クイック検索] ボックスに「フロー」と入力し、[フロー] を選択します。
- Automation アプリケーションから、[フロー] タブを選択します。
- 任意の Lightning アプリケーションの [フロー] タブで、アクション メニューをクリックし、[フローを開く] を選択します。
-
レコードトリガーフローを作成します。
- オートメーション Lightning アプリケーションから、[新規] をクリックします。[レコードトリガーフロー] を検索して選択します。
- [設定] から、[新規フロー] をクリックし、[レコードトリガーフロー] を検索して選択します。
[開始を設定] パネルが開きます。 -
開始要素を設定します。
- [オブジェクト] で、[Opportunity] を選択します。
- [Trigger the Flow When (フローをトリガーするタイミング)] で、[A record is updated (レコードが更新されたとき)] を選択します。
- [エントリ条件の設定] セクションの [条件の要件] で、[すべての条件に一致 (AND)] を選択します。
- [項目] で、[フェーズ] を選択します。
- [演算子] で [次の文字列と一致する] を選択します。
- [値] で、[商談成立] を選択します。
- [フローを最適化] で、[アクションと関連レコード] を選択します。
リソースの作成
一括処理に必要な変数を作成します。
-
各 ToDo を作成するには、ToDo レコードを作成するためのレコード変数を作成します。
-
ツールボックスを開くには、[
] をクリックします。
- [新規リソース] をクリックし、[変数] を選択します。
- [API 参照名] に「TaskRecord」と入力します。
- [データ型] で、[レコード] を選択します。
- [オブジェクト] で、[ToDo] を選択します。
- [完了] をクリックします。
-
ツールボックスを開くには、[
-
すべての ToDo を保存するには、すべての ToDo のレコードコレクション変数を作成します。
- [新規リソース] をクリックし、[変数] を選択します。
- [API 参照名] に「TasksToCreate」と入力します。
- [データ型] で、[レコード] を選択します。
- [オブジェクト] で、[ToDo] を選択します。
- [Allow multiple values (collection) (複数の値を許可 (コレクション))] を選択します。
- [完了] をクリックします。
チームメンバーの取得
[レコードを取得] 要素を使用して、処理する商談チームメンバーレコードを取得します。
-
[
] をクリックし、[レコードを取得] を検索して選択します。
-
要素を設定します。
- [表示ラベル] に「Get Opportunity Team Members」と入力します。
-
[オブジェクト] で、[Opportunity Contact Role] を選択します。
この例では、フローはチームメンバーを商談取引先責任者の役割オブジェクトに保存します。商談を取引先責任者にリンクするオブジェクト。
- [Filter Opportunity Contact Role Records (商談取引先責任者の役割レコードの絞り込み)] セクションの [項目] で、[商談 ID] を選択します。
- [演算子] で [次の文字列と一致する] を選択します。
- [値] で、[Triggering Opportunity]、[Opportunity ID] の順に選択します。
- [保存するレコード数] で [すべてのレコード] を選択します。
- [レコードデータの保存方法] で、[すべてのフィールドを自動的に保存] を選択します。
チームメンバーを確認する決定の追加
決定要素を追加して、チームメンバーがいないときの処理を回避します。
-
[
] をクリックし、[決定] を検索して選択します。
-
決定を設定します。
- [表示ラベル] に「Found Team Members?」と入力します。
- API 参照名が自動入力されます。
- [結果の表示ラベル] に「Yes」と入力します。
- API 参照名が自動入力されます。
- [リソース] で、[Get Opportunity Team Members (商談チームメンバーを取得)] の [Opportunity Contact Roles (商談取引先責任者の役割)] を選択します。
- [演算子] で [null] を選択します。
- [値] で、[False] を選択します。
- [デフォルトの結果(Default Outcome)] をクリックします。
- [表示ラベル] に「いいえ」と入力します。
ループ要素の追加
チームメンバーを反復処理するループ要素を追加します。
-
[はい] パスで [
] をクリックし、[ループ] を検索して選択します。
-
ループを設定します。
- [表示ラベル] に「Iterate Through Team Members」と入力します。
- API 参照名が自動入力されます。
-
[コレクション変数] で、[Get Opportunity Team Members] から [Opportunity Contact Role] を選択します。
このリソースは、複数のレコードが含まれている場合でも、単一として表示されます。
- [方向] で、[最初の項目から最後の項目] を選択します。
ループ内での ToDo レコードの作成
ループ内の各チームメンバーの TaskRecord レコード変数の項目値を入力します。
-
[それぞれ] の後で、[
] をクリックし、[割り当て] を検索して選択します。
-
割り当てを設定します。
- [表示ラベル] に「Build Task Record」と入力します。
- API 参照名が自動入力されます。
- [変数] で [TaskRecord] を選択し、[件名] を選択します。
- [演算子] で [次の文字列と一致する] を選択します。
- 値に「Follow up on closed opportunity」と入力します
- [+ Add Assignment (+ 割り当ての追加)] をクリックします。
-
割り当ての追加と値の設定を続行します。
リソース 演算子 値 TaskRecord>状況 次の文字列と一致する 未開始 TaskRecord>優先度 次の文字列と一致する High (高) TaskRecord>割り当て先 ID 次の文字列と一致する ループの現在の項目>取引先責任者 ID TaskRecord>関連先 ID 次の文字列と一致する Triggering Opportunity>Opportunity ID (トリガー商談>商談 ID)
コレクションへの ToDo の追加
一括作成用に各 ToDo レコードを TasksToCreate コレクション変数に追加します。
-
[割り当て] 要素の後、ループ内でまだ [
] をクリックし、[割り当て] を検索して選択します。
-
割り当てを設定します。
- [表示ラベル] に「Add Task to Collection」と入力します。
- [変数] で、[TasksToCreate] を選択します。
- [演算子] で [追加] を選択します。
- [値] で、[TaskRecord]、[リソース全体] の順に選択します。
ループ後のすべての ToDo の作成
1 つのレコード作成要素を使用して、1 つの操作ですべての ToDo を作成します。
-
ループが終了したら、[
] をクリックし、[レコードを作成] を検索して選択します。
-
要素を設定します。
- [表示ラベル] に「Create All Tasks」と入力します。
- [レコード項目値の設定方法] で、[レコード変数から] を選択します。
- [作成するレコード数] で、[複数] を選択します。
- [レコードコレクション] で、[TasksToCreate] を選択します。
- フローを保存します。
- [表示ラベル] に「Create Tasks for Opportunity Team Members」と入力します。
- API 参照名が自動入力されます。
エラー処理の追加
エラーを取得して報告するように障害管理を設定します。
-
エラーを管理するには、[レコードを作成] 要素に障害パスを追加します。
- [Create All Tasks (すべての ToDo を作成)] 要素の 3 つの点をクリックし、[Add Fault Path (障害パスを追加)] を選択します。
-
Salesforce システム管理者に障害パスの失敗を通知するには、[メールを送信] アクションを追加します。
-
障害パスで、[
] をクリックし、[メールを送信] を検索して選択します。
- [表示ラベル] に「Notify Admin About Error」と入力します。
- API 参照名が自動入力されます。
- [受信者アドレス] に、通知を受信するユーザーのメールアドレスを入力します。
- [件名] に「A flow needs your attention」と入力します。
- [本文] に「[Create Tasks for Opportunity Team Members (商談チームメンバーの ToDo の作成)] フローでエラーが発生しました。」と入力します。 というエラーがあります。
- [リソースを挿入] をクリックします。
- [実行中のフロー] を選択し、[障害メッセージ] を選択します。
-
障害パスで、[
- 作業内容を保存します。
一括データを使用したテスト
一括処理フローをテストするには、一括処理をシミュレーションする必要があります。
- 個々のレコードをテストするには、デバッグモードを使用して 1 つの商談を更新し、フローで ToDo が正しく作成されることを確認します。
- フローを有効化します。
-
Sandbox で一括操作をテストするには、データインポートウィザード、データローダー、またはリストビューを使用して複数の商談を一度に更新します。
- 10 ~ 20 のテスト商談を作成します。
- チームメンバーを各商談に追加します。
- データローダーまたは一括更新を使用して、すべての商談で同時にフェーズを「商談成立」に変更します。
- フローですべての ToDo がエラーなしで作成されることを確認します。
- パフォーマンスを検証するには、Apex デバッグ ログで CPU 時間の消費量が許容範囲内であることを確認します。
その他の最適化手法
これらの手法を使用して、一括処理フローをさらに最適化します。
エントリ条件を使用した実行の制限
フローの開始要素に条件を追加して、必要な場合にのみ実行されるようにします。たとえば、特定の金額を超える商談や特定のレコードタイプの商談のみを処理します。
重要でない操作の保存後を考慮
保存後レコードトリガーフローでは、商談の保存後にフォローアップ ToDo を作成できます。非同期で実行され、ガバナ制限が高くなります。
大量の一括処理
商談に数十人のチームメンバーが頻繁にいる場合、完了した商談をリアルタイムではなくバッチで処理するスケジュール済みフローを使用します。
既存のフローの変換
ループ内のデータ操作言語 (DML) 操作でフローを一括処理パターンに変換します。
ループ内に DML 操作を含む既存のフローがある場合、次の手順に従って変換します。
- ループ内の DML 操作を見つけるには、ループ内のすべての [レコードを作成]、[レコードを更新]、[レコードを削除] 要素を特定します。
-
DML 要素ごとに変換を実行します。
- レコードを作成するには、そのオブジェクト種別のレコード変数を作成します。
- 処理するレコードを保存するには、そのオブジェクト種別のレコードコレクション変数を作成します。
- レコードの項目値を保存するには、割り当て要素を使用して値をレコード変数に割り当てます。
- 処理するレコードを収集するには、割り当てを使用してレコード変数をレコードコレクションに追加します。
- レコードを効率的に作成するには、ループの後に、レコードコレクション全体を処理する 1 つの DML 要素を追加します。
- 変換を検証するには、一括データを使用して徹底的にテストし、リファクタリングが正常に機能したことを確認します。

