【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"