In this post, I would share my recent experience in fixing “CPU time limit” error in Batch apex and reason. When I encountered this error, initially thought that it would be easy to fix by following some of basic rules like :
- Remove unnecessary code and loops
- Efficient use of collections (Set, Hashmap or List)
- Avoid using loop within loop
- SOQL query should be indexable
- Avoid unnecessary re-initialization of variables
- Use Aggregated SOQL (as Database operations not counted in this limit, avoid arithmetic operations in Apex)
- Check how much time Workflow rules and process builders are taking
- Is there any manage package performing heavy operations in transaction
This piece of code was handed over to me from previous team, so I was not fully aware about full functionality and thought to check debug logs. To my surprise, how many times I tried to get a log, every attempt failed. I was thinking that problem could be in execute method however Batch Apex was failing with no debug logs. I tried all my tricks to get debug log with no success. Batch Apex was using Query locator and it could fetch up to 50 millions of record and therefore overlooked start method.
Below pseudo code will give you some idea about Batch Apex structure and data volume.
global class SampleBatchApex_CPUError implements Database.Batchable<sObject> { String query = ' SELECT Field1, Field2, (SELECT Name, Identifier__c FROM childObject__r Where type=\'some value\') FROM Contact'; global Database.QueryLocator start(Database.BatchableContext BC) { return Database.getQueryLocator(query); } global void execute(Database.BatchableContext BC, List<Contact> contacts) { //Some code about 100 lines } global void finish(Database.BatchableContext BC) { //Perform cleaning and start another Batch job } }
Data volume in full copy sandbox were like
- Contact – 270k+
- ChildObject__c – 270k+
Reason for CPU time out (in my case) – SubQuery
I tried SOQL Query Plan and run same query in Developer console and workbench, but it was not timing out. Still, gave one shot to idea that I had and tried to remove subquery from start method and queried again in execute method. And voilla…. it worked. So, subquery in SOQL was causing CPU time limit error and it was not even able to enter in execute method. I got lost because there were no debug logs. Instead of spending time on actual issue, I spent lot of time to figure out why debug log is not showing up.
Lessons learned
- If we are getting CPU time limit error (in my experience I have seen many), then avoid using sub-query, its costly and time consuming. Damn !!! I need to tell my colleagues of previous projects to check code for subquery, where they are getting CPU error.
- If batch apex error says “First error – some error” , that means error is in start method and don’t even try to hunt for execute method debug logs.
Leave a Reply