この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

Apex の一括処理の使用

Apex の一括処理を使用するには、Salesforce が提供するインターフェース Database.Batchable を実装する Apex クラスを記述し、次にプログラムでクラスを呼び出します。

Apex の一括処理ジョブの実行を監視または停止するには、[設定] から、[クイック検索] ボックスに「Apex ジョブ」と入力し、[Apex ジョブ] を選択します。

Database.Batchable インターフェースの実装

Database.Batchable インターフェースには、実装が必要な次の 3 つのメソッドが含まれています。
  • start メソッド:

    インターフェースメソッド execute に渡すレコードまたはオブジェクトを収集するには、Apex 一括処理ジョブの冒頭で start メソッドをコールします。このメソッドは、Database.QueryLocator オブジェクト、またはジョブに渡すレコードやオブジェクトが含まれる Iterable オブジェクトを返します。

    単純なクエリ (SELECT) を使用して一括処理ジョブのオブジェクトの範囲を生成する場合は、Database.QueryLocator オブジェクトを使用します。QueryLocator オブジェクトを使用する場合、SOQL クエリによって取得されるレコード合計数に対するガバナ制限は無視されます。たとえば、Account オブジェクトに対する Apex の一括処理ジョブでは、組織内のすべての取引先レコード (最大 5000 万件のレコード) の QueryLocator を返すことができます。また、Contact オブジェクトに対して共有再適用を行うと、組織内のすべての取引先レコードの QueryLocator が返されます。

    Iterable オブジェクトは、一括処理ジョブに複雑な範囲を作成する場合に使用します。また、リスト全体を反復する独自のカスタムプロセスを作成するために Iterable オブジェクトを使用することもできます。

    Iterable オブジェクトを使用する場合、SOQL クエリによって取得されるレコード合計数に対するガバナ制限はそのまま適用されます。

    重要

  • execute メソッド

    データの処理単位ごとに必要な処理を実行するには、execute メソッドを使用します。このメソッドは、メソッドに渡すレコードのバッチごとにコールされます。

    このメソッドは次を取得します。
    • Database.BatchableContext オブジェクトへの参照。
    • List<sObject> などの sObjects のリストまたはパラメータ化された型のリスト。Database.QueryLocator を使用している場合は、返されたリストを使用します。

    レコードの一括処理は、start メソッドから受け取る順序で実行される傾向にあります。ただし、レコードの一括処理が実行される順序はさまざまな要素に応じて変わります。実行の順序は保証されません。

  • finish メソッド

    確認メールの送信や後処理操作を行う場合に、finish メソッドを使用します。このメソッドは、すべてのバッチが処理された後にコールされます。

Apex 一括処理ジョブの各実行は、個別のトランザクションとみなされます。たとえば、1,000 件のレコードを含む Apex の一括処理ジョブが、Database.executeBatch から任意の scope パラメータを指定せずに実行されると、このジョブはそれぞれ 200 件のレコードを含む 5 つのトランザ��ションとみなされます。Apex のガバナ制限は、各トランザクションでリセットされます。最初のトランザクションが成功し、2 番目が失敗した場合、最初のトランザクションで行われたデータベースの更新はロールバックされません。

Database.BatchableContext の使用

Database.Batchable インターフェースのすべてのメソッドは Database.BatchableContext オブジェクトへの参照を必要とします。このオブジェクトは、一括処理ジョブの進行状況を追跡するために使用します。

Database.BatchableContext オブジェクトのインスタンスメソッドを次に示します。
名前 引数 戻り値 説明
getJobID ID この一括処理ジョブに関連付けられている AsyncApexJob オブジェクトの ID を文字列として返します。このメソッドは、一括処理ジョブのレコードの進行状況を追跡するために使用します。System.abortJob メソッドでもこの ID を使用できます。

次の例では、Database.BatchableContext を使用して、一括処理ジョブに関連付けられている AsyncApexJob を照会します。

Database.QueryLocator を使用した範囲の定義

start メソッドは、一括処理ジョブで使用するレコードを含む Database.QueryLocator オブジェクトまたは Iterable オブジェクトを返します。

次の例では、Database.QueryLocator を使用します。

Apex の一括処理に Iterable オブジェクトを使用した範囲の定義

start メソッドは、一括処理ジョブで使用するレコードを含む Database.QueryLocator オブジェクトまたは Iterable オブジェクトを返します。Iterable オブジェクトを使用すると、より簡単に項目を返すことができます。

Database.executeBatch メソッドを使用した一括処理ジョブの送信

一括処理ジョブをプログラムで開始するには、Database.executeBatch メソッドを使用します。

Database.executeBatch をコールすると、Salesforce はプロセスをキューに追加します。実際の実行は、サービスの使用可能状態に応じて遅れる場合があります。

重要

Database.executeBatch メソッドは次の 2 つのパラメータを取ります。
  • Database.Batchable インターフェースを実装するクラスのインスタンス。
  • 省略可能なパラメータ scope。このパラメータは、execute メソッドに渡すレコードの数を指定します。このパラメータは、メソッドに渡す各レコードに対して多数の処理があり、ガバナ制限に達する場合に使用します。レコード数を制限することによって、トランザクションあたりの処理が制限されます。この値は 0 より大きくする必要があります。一括処理クラスの start メソッドが QueryLocator を返す場合、Database.executeBatch の省略可能な scope パラメータには最大値 2,000 を指定できます。これより大きい値に設定すると、Salesforce では、QueryLocator が返すレコードを、最大 2,000 レコードまでの、より小さいバッチに分割します。一括処理クラスの start メソッドが Iterable を返す場合、scope パラメータの値に上限はありません。ただし、大きな数値を使用すると他の制限が適用される場合があります。
Database.executeBatch メソッドは、ジョブの進捗状況の追跡に使用できる AsyncApexJob オブジェクトの ID を返します。次に例を示します。

System.abortJob メソッドでもこの ID を使用できます。

詳細は、『Salesforce のオブジェクトリファレンス』「AsyncApexJob」を参照してください。

Apex Flex キュー内での一括処理ジョブの保留

Apex Flex キューでは、100 件まで一括処理ジョブを送信できます。

Database.executeBatch の結果は次のようになります。
  • 一括処理ジョブは Apex Flex キューに置かれ、その状況は Holding に設定されます。
  • Apex Flex キューが最大ジョブ数の 100 に達した場合、Database.executeBatchLimitException を発生させて、ジョブをキューに追加しません。

組織で Apex Flex キューが有効ではない場合、Database.executeBatch は一括処理ジョブを Queued 状況として一括処理ジョブキューに追加します。キュー内または有効な一括処理ジョブの数が同時ジョブ数の制限に達した場合、LimitException を発生させて、ジョブをキューに追加しません。

メモ

Apex Flex キュー内のジョブの並び替え

送信したジョブの状況が Holding である間は、Salesforce ユーザインターフェースでジョブを並び替えてどの一括処理ジョブが最初に処理されるかを制御できます。これを行うには、[設定] から、[クイック検索] ボックスに「Apex Flex キュー」と入力し、[Apex Flex キュー] を選択します。

または、Apex メソッドを使用して、Flex キュー内の一括処理ジョブを並び替えることができます。新しい位置にジョブを移動するには、いずれかの System.FlexQueue メソッドをコールします。メソッドにジョブ ID と、移動するジョブの新しい位置の次にあるジョブの ID (該当する場合) を渡します。次に例を示します。

Apex Flex キュー内のジョブを並び替えてジョブの優先度を設定できます。たとえば、一括処理ジョブを保留キュー内の先頭位置に移動して、リソースが使用可能になったら最初に処理されるようにすることができます。並び替えない場合、ジョブは、送信された順序 (先入れ先出し) で処理されます。

システムリソースが使用可能になったら、システムが Apex Flex キューの先頭から次のジョブを取り出し、一括処理ジョブキューに移動します。組織ごとに、システムでは最大 5 件のキュー内のジョブまたは有効なジョブを同時に処理できます。移動したこれらのジョブの状況は、Holding から Queued に変わります。キュー内にあるジョブは、システムが新しいジョブを処理できる状態になると実行されます。[Apex ジョブ] ページで、キューに入れたジョブを監視できます。

一括処理ジョブの状況

次の表に、一括処理ジョブで発生するすべての状況と、それぞれの説明を示します。

状況 説明
保留 ジョブは送信済みで、システムリソースが使用可能になって処理用のキューにジョブを追加できるようになるまで Apex Flex キュー内に保持されています。
キュー ジョブは実行待ちです。
準備中 ジョブの start メソッドが呼び出されました。この状況は、レコードのバッチサイズに応じて数分かかることがあります。
処理中 ジョブは処理中です。
中止 ジョブはユーザによって中止されました。
完了 ジョブはエラーあり/なしで完了しました。
失敗 ジョブでシステム障害が発生しました。

System.scheduleBatch メソッドの使用

System.scheduleBatch メソッドを使用して、一括処理ジョブを将来のある時点で一度実行するようにスケジュールできます。

System.scheduleBatch メソッドに、次のパラメータを指定します。
  • Database.Batchable インターフェースを実装するクラスのインスタンス。
  • ジョブ名。
  • ジョブが実行を開始するまでの分単位の期間。
  • 範囲の値 (省略可能)。このパラメータは、execute メソッドに渡すレコードの数を指定します。このパラメータは、メソッドに渡す各レコードに対して多数の処理があり、ガバナ制限に達する場合に使用します。レコード数を制限することによって、トランザクションあたりの処理が制限されます。この値は 0 より大きくする必要があります。start メソッドが QueryLocator を返す場合、System.scheduleBatch の省略可能な scope パラメータには最大値 2,000 を指定できます。これより大きい値に設定すると、Salesforce では、QueryLocator が返すレコードを、最大 2,000 レコードまでの、より小さいバッチに分割します。start メソッドが Iterable を返す場合、scope パラメータの値に上限はありません。ただし、大きな数値を使用すると他の制限が適用される場合があります。

System.scheduleBatch メソッドは、スケジュール済みジョブ ID (CronTrigger ID) を返します。

次の例では、System.scheduleBatch をコールして、今から 1 分後に一括処理ジョブを実行するようにスケジュールします。この例では、一括処理クラスのインスタンス (reassign 変数)、ジョブ名、期間 (1 分) をこのメソッドに渡します。省略可能な scope パラメータは指定していません。メソッドからスケジュール済みジョブ ID が返されます。この ID は、CronTrigger を照会して、対応するスケジュール済みジョブの状況を取得するために使用されます。

詳細は、『Salesforce のオブジェクトリファレンス』「CronTrigger」を参照してください。

System.scheduleBatch では、次の点に留意してください。

  • System.scheduleBatch をコールすると、Salesforce により指定の時間にジョブを実行するようにスケジュールされます。実際の実行は、サービスの使用可能状態に応じて、その時間以降に行われます。
  • スケジューラは、システムとして実行されます。ユーザがそのクラスの実行権限を持っているかどうかにかかわらず、すべてのクラスが実行されます。
  • ジョブのスケジュールがトリガされると、システムは処理する一括処理ジョブをキューに入れます。組織で Apex Flex キューが有効になっている場合、Flex キューの最後に一括処理ジョブが追加されます。詳細は、「Apex Flex キュー内での一括処理ジョブの保留」を参照してください。
  • スケジュールされたすべての Apex 制限は、System.scheduleBatch を使用してスケジュールされた一括処理ジョブに適用されます。一括処理ジョブが (Holding または Queued 状況で) キューに入れられると、すべての一括処理ジョブ制限が適用され、ジョブはスケジュール済みの Apex 制限としてカウントされなくなります。
  • このメソッドをコールしてから一括処理ジョブが開始するまでは、返されたスケジュール済みジョブ ID を使用して、System.abortJob メソッドを使用したスケジュール済みジョブを中止できます。

メモ

Apex の一括処理の例

次の例では、Database.QueryLocator を使用します。
次のコードを使用して、前のクラスをコールできます。
削除されてまだごみ箱に入っている取引先や請求書を除外するには、この変更したサンプルのように、SOQL クエリの WHERE 句に isDeleted=false を付加します。
次のクラスでは、Apex の一括処理を使用して、特定のユーザが所有するすべての取引先を異なるユーザに再割り当てします。
前の例の OwnerReassignment クラスを実行するには次のコードを使用します。
次は、レコードを削除する Apex の一括処理クラスの例です。
このコードは、古いドキュメントを削除する、Apex の BatchDelete 一括処理クラスをコールします。ここに示すクエリは、指定したフォルダ内の特定の日付より古いドキュメントをすべて削除するために、それらのドキュメントを選択し、その後で、一括処理ジョブを呼び出します。

Apex の一括処理でのコールアウトの使用

Apex の一括処理でコールアウトを使用するには、クラス定義で Database.AllowsCallouts を指定します。次に例を示します。

コールアウトには、HTTP 要求および webservice キーワードで定義されたメソッドが含まれています。

Apex の一括処理での状態の使用

Apex 一括処理ジョブの各実行は、個別のトランザクションとみなされます。たとえば、1,000 件のレコードを含む Apex の一括処理ジョブが、任意の scope パラメータを指定せずに実行され���と、このジョブはそれぞれ 200 件のレコードを含む 5 つのトランザクションとみなされます。

クラス定義で Database.Stateful を指定すると、これらのトランザクション間で状態を保持できます。Database.Stateful を使用するとき、インスタンスメンバー変数のみがトランザクション間で値を保持します。静的メンバー変数は、トランザクション間で値を保持せず、リセットされます。状態を保持すると、処理されているレコードをカウントまたは集計する場合に役立ちます。たとえば、ジョブで商談レコードが処理されたとします。execute でメソッドを定義し、処理された商談数の合計を集計できます。

Database.Stateful を指定しない場合、すべての静的メンバー変数とインスタンスメンバー変数が元の値に戻されます。

次の例では、レコードが処理されるとカスタム項目 total__c が集計されます。
また、変数を指定してクラスの最初の状態にアクセスできます。この変数を使用して、Database.Batchable メソッドのすべてのインスタンスと最初の状態を共有できます。次に例を示します。

initialState はクラスの「最初の」状態でしかありません。これを使用して、一括処理ジョブの実行時にクラスのインスタンス間で情報を受け渡すことはできません。たとえば、executeinitialState の値を変更した場合、2 番目に処理されるレコード群は、新しい値にアクセスできません。アクセスできるのは最初の値のみです。

Apex の一括処理のテスト

Apex の一括処理をテストするとき、execute メソッドの 1 つの実行だけをテストできます。executeBatch メソッドの scope パラメータを使用して、execute メソッドに渡されるレコード数を制限し、ガバナ制限に達しないようにします。

executeBatch メソッドは、匿名プロセスを開始します。Apex の一括処理をテストするときには、結果に対してテストする前に非同期で処理された一括処理ジョブが完了していることを確認してください。テストメソッド startTeststopTestexecuteBatch メソッドの前後に使用して、非同期で処理された一括処理ジョブが完了してからテストを続行するようにします。startTest メソッドの後に実行されたすべての非同期コールはシステムによって収集されます。stopTest を実行する場合、すべての非同期プロセスが同期して実行されます。startTest メソッドおよび stopTest メソッド内に executeBatch メソッドを含めない場合、一括処理ジョブはテストメソッドの最後に実行されます。この実行順序は、API バージョン 25.0 以降を使用して保存された Apex には適用されますが、それより前のバージョンには適用されません。

API バージョン 22.0 以降を使用して保存した Apex の場合、テストメソッドによって呼び出された Apex の一括処理ジョブの実行中に発生する例外は、コール元のテストメソッドに渡されます。その結果として、これらの例外によりテストメソッドが失敗します。テストメソッドで例外を処理する必要がある場合は、コードを try ステートメントと catch ステートメントで囲みます。catch ブロックを stopTest メソッドの後に配置します。ただし、Apex バージョン 21.0 以前を使用して保存した Apex では、該当する例外はテストメソッドに渡されないため、テストメソッドは失敗しません。

startTest ブロックおよび stopTest ブロックでコールされた @future または executeBatch などの非同期コールは、キュー内ジョブ数の制限に対してカウントされません。

メモ

次の例では、OwnerReassignment クラスをテストします。

System.Test.enqueueBatchJobs および System.Test.getFlexQueueOrder メソッドを使用して、テストのコンテキスト内でノーオペレーションジョブをキューに追加し、並び替えます。

Apex の一括処理のガバナ制限

Apex の一括処理について、次のガバナ制限に注意してください。
  • 最大 5 件の一括処理ジョブを同時にキューに追加するか、有効にできます。
  • 最大 100 個の Holding 一括処理ジョブを Apex Flex キュー内で保留できます。
  • 実行中のテストでは、最大 5 件の一括処理ジョブを送信できます。
  • 24 時間での Apex 一括処理メソッドの最大実行数は、250,000 または組織のユーザライセンス数の 200 倍のいずれか大きい方です。メソッドの実行数には、startexecute、および finish メソッドの実行が含まれます。これは組織全体の制限で、他のすべての非同期 Apex (Apex 一括処理、キュー可能 Apex、スケジュール済み Apex、および future メソッド) と共有されます。使用可能な非同期 Apex 実行の数を確認するには、REST API limits リソースに対して要求を実行します。『REST API 開発者ガイド』「組織の制限をリストする」を参照してください。この制限のカウント対象となるライセンスは、Salesforce フルユーザライセンスまたはアプリケーションサブスクリプションのユーザライセンスです。Chatter Free、Chatter カスタマーユーザ、カスタマーポータルユーザ、およびパートナーポータルユーザライセンスは含まれません。
  • Apex 一括処理の start メソッドは、ユーザごとに同時に最大 15 個のクエリカーソルを開くことができます。Apex 一括処理の execute および finish メソッドにはそれぞれ、ユーザごとに開けるクエリカーソルは 5 個までという制限があります。
  • Database.QueryLocator オブジェクトでは最大 5,000 万件のレコードが返されます。5,000 万件以上のレコードが返された場合、一括処理ジョブは即座に終了し「失敗」とマークされます。
  • 一括処理クラスの start メソッドが QueryLocator を返す場合、Database.executeBatch の省略可能な scope パラメータには最大値 2,000 を指定できます。これより大きい値に設定すると、Salesforce では、QueryLocator が返すレコードを、最大 2,000 レコードまでの、より小さいバッチに分割します。一括処理クラスの start メソッドが Iterable を返す場合、scope パラメータの値に上限はありません。ただし、大きな数値を使用すると他の制限が適用される場合があります。
  • Database.executeBatchscope パラメータ (省略可能) でサイズが指定されない場合、Salesforce では start メソッドによって返されるレコードを 200 個ずつのバッチに分割します。次に、各バッチを execute メソッドに渡します。Apex ガバナ制限は、execute の各実行でリセットされます。
  • startexecute、および finish メソッドは、それぞれ最大 100 回のコールアウトを実装できます。
  • Apex の一括処理ジョブの start メソッドは、組織内で一度に 1 つのみ実行できます。キュー内のまだ開始されていない一括処理ジョブは、開始されるまで保持されます。なお、この制限により一括処理ジョブが失敗することはありません。また、複数のジョブが実行されている場合は、Apex の一括処理ジョブの execute メソッドが並行して実行されます。

Apex の一括処理のベストプラクティス

  • 一括処理ジョブをトリガから開始する場合は、細心の注意を払ってください。トリガで一括処理ジョブが制限を超えて追加されないようにする必要があります。特に、API の一括更新、インポートウィザード、ユーザインターフェースを使用したレコードの一括変更、および複数の���コードを一度に更新するすべての処理については十分に考慮してください。
  • Database.executeBatch をコールしたときに Salesforce が行うのは、そのジョブをキューに入れることのみです。実際の実行は、サービスの使用可能状態に応じて遅れる場合があります。
  • Apex の一括処理をテストするとき、execute メソッドの 1 つの実行だけをテストできます。executeBatch メソッドの scope パラメータを使用して、execute メソッドに渡されるレコード数を制限し、ガバナ制限に達しないようにします。
  • executeBatch メソッドは、匿名プロセスを開始します。Apex の一括処理をテストするときには、結果に対してテストする前に非同期で処理された一括処理ジョブが完了していることを確認してください。テストメソッド startTeststopTestexecuteBatch メソッドの前後に使用して、非同期で処理された一括処理ジョブが完了してからテストを続行するようにします。
  • ジョブトランザクション全体でインスタンスメンバー変数またはデータを共有する場合は、クラス定義で Database.Stateful を使用します。これを使用しない場合、各トランザクションの開始時にすべてのメンバー変数が初期状態にリセットされます。
  • future として宣言されたメソッドは、Database.Batchable インターフェースを実装するクラスでは使用できません。
  • future として宣言されたメソッドは、Apex の一括処理クラスからはコールできません。
  • Apex の一括処理ジョブが実行されると、一括処理ジョブを送信したユーザにメール通知が送信されます。管理パッケージにコードが含まれ、登録組織が一括処理ジョブを実行している場合、[Apex 例外通知受信者] 項目にリストされた受信者に通知が送信されます。
  • 各メソッドの実行では、標準のガバナ制限が、匿名ブロック、Visualforce コントローラ、または WSDL メソッド同様に適用されます。
  • Apex の一括処理が呼び出されるたびに AsyncApexJob レコードが作成されます。ジョブの状況、エラーの数、進行状況、送信者を取得する SOQL クエリを構成するには、AsyncApexJob レコードの ID を使用します。AsyncApexJob オブジェクトについての詳細は、『Salesforce のオブジェクトリファレンス』「AsyncApexJob」を参照してください。
  • 10,000 件ごとの AsyncApexJob レコードに対して、Apex では、内部で使用するための BatchApexWorker タイプの AsyncApexJob レコードを作成します。すべての AsyncApexJob レコードを照会する場合は、JobType 項目を使用して BatchApexWorker タイプのレコードを除外することをお勧めします。除外しない場合、クエリにより 10,000 件の AsyncApexJob レコードごとに複数のレコードが返されます。AsyncApexJob オブジェクトについての詳細は、『Salesforce のオブジェクトリファレンス』「AsyncApexJob」を参照してください。
  • クラス内のすべてのメソッドは global または public として定義する必要があります。
  • 共有再適用の場合、一括処理内のレコードに対する Apex による共有管理を、すべて execute メソッドで削除してから再作成することをお勧めします。このプロセスにより、共有が正確で完全になります。
  • Salesforce サービスメンテナンスダウンタイム前にキューに入れられた一括処理ジョブは、キューに入れられたままになります。サービスのダウンタイムが終了してシステムリソースが使用可能になったときに、キューにある一括処理ジョブが実行されます。ダウンタイム発生時に一括処理ジョブが実行されていた場合、その一括処理の実行はロールバックされ、サービスが再開された後に再度開始されます。
  • 可能ならば、一括処理の数は最小限に抑えてください。Salesforce では、キューベースのフレームワークを使用して、future メソッドや Apex の一括処理などの提供元からの非同期プロセスを処理します。このキューは、組織間で要求ワークロードを調整するために使用します。キュー内で 1 つの組織の未処理要求が 2,000 を上回ると、その組織からの以降の要求は遅延し、その間に他の組織からの要求が処理されます。
  • 一括処理ジョブができるだけ高速に実行されるようにします。一括処理ジョブを高速に実行するには、Web サービスコールアウト回数を最小限にし、Apex 一括処理コードで使用されるクエリを調整します。キュー内のジョブ数が多い場合、一括処理ジョブの実行時間が長くなるほど、キューにある他のジョブが遅延する可能性が高くなります。
  • Database.QueryLocator で Apex 一括処理を使用して、Salesforce Connect の OData アダプタ経由で外部オブジェクトにアクセスする場合、次の点に注意してください。
    • 外部データソースで [要求の行数] を有効にして、外部システムからの各応答に結果セットの合計行数を含める必要があります。
    • 外部データソースで [サーバ駆動のページ設定] を有効にして、大きな結果セットのページサイズとバッチの区切りを外部システムで決定することをお勧めします。通常、サーバ駆動ページングはバッチの区切りを調節して、データセットの変更にクライアント駆動ページングよりも効率的に対応できます。

      外部データソースで [サーバ駆動のページ設定] が無効になっている場合、OData アダプタでページングの動作を制御します (クライアント駆動)。ジョブの実行中に外部オブジェクトレコードが外部システムに追加されると、他のレコードが 2 回処理される可能性があります。ジョブの実行中に外部オブジェクトレコードが外部システムから削除されると、他のレコードがスキップされる可能性があります。

    • 外部データソースで [サーバ駆動のページ設定] が有効になっている場合、実行時のバッチサイズは次のサイズよりも小さくなります。
      • Database.executeBatchscope パラメータで指定したバッチサイズ。デフォルトは 200 レコードです。
      • 外部システムから返されるページサイズ。200 レコード以下のページサイズが返されるように外部システムを設定することをお勧めします。
  • start メソッドがサブクエリを介して関連レコードを含まない QueryLocator オブジェクトを返すと、Apex の一括処理ジョブは高速に実行されます。QueryLocator でのリレーションサブクエリを避けると、高速なチャンク実装を使用して一括処理ジョブを実行できます。start メソッドが Iterable、またはリレーションサブクエリを使用して QueryLocator オブジェクトを返す場合、一括処理ジョブでは、速度の遅い非チャンク実装が使用されます。たとえば、次のクエリが QueryLocator で使用される場合、リレーションサブクエリがあるために、速度の遅い実装が使用されます。
    より優れた戦略は、excute メソッド内からサブクエリを別個に実行し、高速なチャンク実装を使用して一括処理ジョブを実行できるようにすることです。

一括処理ジョブのチェーニング

API バージョン 26.0 以降、既存の一括処理ジョブから別の一括処理ジョブを開始するように、ジョブをチェーニングできます。一括処理ジョブをチェーニングすることで、大量のデータを処理する場合など、ジョブでバッチでの処理が必要な場合に、別のジョブが終了するとジョブが開始します。または、一括処理が必要ではない場合は、Queueable Apex の使用を検討してください。

一括処理ジョブをチェーニングするには、現在の一括処理クラスの finish メソッドから Database.executeBatch または System.scheduleBatch をコールします。新しい一括処理ジョブは、現在の一括処理ジョブが終了すると開始します。

以前の API バージョンでは、Apex の一括処理メソッドから Database.executeBatchSystem.scheduleBatch はコールできませんでした。使用されるバージョンは、他の一括処理ジョブを開始またはスケジュールする、実行中の一括処理クラスのバージョンです。実行中の一括処理クラスの finish メソッドで、一括処理ジョブを開始するヘルパークラスのメソッドをコールする場合は、ヘルパークラスの API バージョンは関係ありません。