【Salesforce】System.LimitException: Apex CPU time limit exceeded
SalesforceのApexコードを触っていると、このようなエラーが発生しました。
System.LimitException: Apex CPU time limit exceeded
ApexのCPUタイムリミットを超えました、とのこと。
処理時間が長いと発生するエラーで、同期処理は10秒、非同期処理は60秒がリミットとなっています。
https://developer.salesforce.com/docs/atlas.ja-jp.206.0.apexcode.meta/apexcode/apex_gov_limits.htm
発生した処理を見てみると、このような状態になっていました。
List<Account> accountList;
List<Contact> contactList;
// 取引先を取得する
accountList = [select Id from Account];
// 取引先責任者を取得する
contactList = [select Id, AccountId from Contact];
// 取引先でループ
for(Account acc : accountList){
// 取引先責任者でループ
for(Contact con : contactList){
// 取引先に紐づく取引先責任者の場合、処理を行う
if(acc.Id = con.AccountId){
// 処理
}
}
}
実際に行っている処理とは異なりますが、ループの中でループを行い、紐付けを行っています。
この状態では[取引先の数] * [取引先責任者の数]だけ処理を行うことになります。
レコード数が少なければ問題ないのですが、レコード数が増えるほど膨大な数の処理を行うことになります。
結果、今回のようなエラーが発生するわけですね。
取引先と取引先責任者のように参照や主従の紐付けがある場合は、SOQLの時点で振り分ける方が処理が少なくなります。
List<Account> accountList;
// 取引先と取引先責任者を取得する
accountList = [select Id, (select Id, AccountId from Contacts) from Account];
// 取引先でループ
for(Account acc : accountList){
// 取引先責任者でループ
for(Contact con : acc.Contacts__r){
// 処理
}
}
このようにすれば、処理回数は[取引先の数] + [取引先責任者の数]となり、レコードが多い場合は上の例より処理回数が少なくなります。
項目により紐付けが無い場合はMapを使うのが便利です。
分かりやすいように取引先のIdをキーとしています。
List<Account> accountList;
List<Contact> contactList;
Map<String, List<Conrtact>> keyContactMap;
// 取引先を取得する
accountList = [select Id from Account];
// 取引先責任者を取得する
contactList = [select Id, AccountId from Contact];
// keyから取引先責任者を取得するMapを作成する
keyContactMap = new Map<String, List<Contact>>();
for(Contact con : contactList){
List<Contact> tmpList;
// キーに対応するリストが無い場合は作成する
if(!keyContactMap.containsKey(con.AccountId)){
// 取引先のIdをキーとする
keyContactMap.put(con.AccountId, new List<Contact>());
}
// Mapからリストを取得する
tmpList = keyContactMap.get(con.AccountId);
// リストに取引先責任者を追加する
tmpList.add(con);
}
// 取引先でループ
for(Account acc : accountList){
// キーに紐づく取引先責任者でループ
for(Contact con : keyContactMap.get(acc.Id)){
// 処理
}
}
この状態であれば、[取引先の数] +( [取引先責任者の数] * 2)となるでしょうか。
最初の状態よりは処理が少なくなると思います。
レコードが多い場合は処理に時間がかかることが多いため、注意が必要ですね。
ちなみに、このように直すのが100%良いというわけではないので悪しからず。
One Response to "【Salesforce】System.LimitException: Apex CPU time limit exceeded"