今回は、Apexの「Too many query rows: 50001」の原因と回避策についてです。
これは開発時に特に悩まされるガバナ制限です。
もっと緩和してくださいよと毎度思います。。。
エラー原因
エラーの原因としては、1トランザクションで SOQL クエリによって取得されるレコード合計数が50,000を超えたからです。
これはSalesforceのガバナ制限であり、1トランザクションで SOQL クエリによって取得されるレコード合計数の上限は50,000と定められています。(非同期処理も50,000)
例えば、以下のコードを匿名実行コンソールで実行し、取得レコード合計数が50,000を超えるとエラーがでます。
//Accountに50001件以上レコードがある状態で実施
List<Account> accList = [SELECT Id FROM Account];
エラー回避策
「Too many query rows: 50001」エラーの回避策としては以下のようなものが挙げられます。
- SOQLはWhereやLimitを使用して取得対象を絞り込む
- Apexバッチの使用
1. SOQLはWhereやLimitを使用
SOQLを使用する際は可能な限り取得対象を絞り込むためにWhere句やLimitを使用するのがよいでしょう。
List<Account> accList = [SELECT Id FROM Account Where Name LIKE 'Sample%' Limit 100];
2. Apexバッチの使用
Apexバッチ(非同期処理)を実装し、Database.getQueryLocator()を使用すれば、5,000万件までレコードの取得が可能になります。
ただ、1回でまとめて取得するのではなく、指定したバッチサイズの件数ごとに取得してそれを繰り返し処理するという流れになります。
以下のソースコードはApexバッチのコードを抜粋したものです。
7行目でSOQLクエリを作成し、10行目でDatabase.getQueryLocator()を使用してレコードを取得します。
public class AccountBatch implements Database.Batchable <sobject>, Database.Stateful{
public Database.QueryLocator start(Database.BatchableContext dbc){
system.debug('startメソッド');
//処理対象の取引先取得クエリ作成
String query = 'Select Id, Industry From Account Where Name Like \'取引先%\'';
//取引先を取得し、executeメソッドに渡す
return Database.getQueryLocator(query);
}
public void execute(Database.BatchableContext dbc, List<Account> accList){
system.debug('executeメソッド');
}
public void finish(Database.BatchableContext dbc){
system.debug('finishメソッド');
}
}
Apexバッチについては以下の記事に詳しく記載していますのでよかったら参考にしてみてください。
おわりに
取得件数50,000件は正直少ないですよね。。。
うまく条件指定できる場合はよいですが、そうじゃない時もありますからね。
ガバナ制限が今後緩和されることを祈りながらいろいろと試行錯誤しながら回避していこうと思います。
今回は以上です。
コメント