How to optimize this code ,I am continuously getting "Apex CPU Limit Error" Can anyone help me out with optimize solution Here is the code :- Batch Size :50 passing here are some number of records we have opportunities: 1 million records. opportunity history: 1 million records.

global class LastStateUpdatedBatch implements Database.Batchable<sObject> {

    String query;

    global LastStateUpdatedBatch() {
        query = 'Select Last_Stage_Update__c, (Select CreatedDate, StageName From OpportunityHistories order by CreatedDate desc) From Opportunity where Last_Stage_Update__c = null AND IsClosed = false ';

    global Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator(query);

    global void execute(Database.BatchableContext BC, List<sObject> scope) {
    List<Opportunity> listOfOldOpp = (List<Opportunity>)scope;
    for( Opportunity opp : listOfOldOpp){
        String lastOppStage = opp.OpportunityHistories[0].StageName;
        DateTime lastUpdate = opp.OpportunityHistories[opp.OpportunityHistories.size()-1].CreatedDate;
        DateTime previousStageChangeDate = opp.OpportunityHistories[0].CreatedDate;
        List<OpportunityHistory> ListOfOpportunityHistories = opp.OpportunityHistories;
        for(OpportunityHistory opphis :ListOfOpportunityHistories){ 
            if(lastOppStage != opphis.StageName && opp.Last_Stage_Update__c == null){
                lastUpdate = previousStageChangeDate;
            previousStageChangeDate = opphis.CreatedDate; 
        opp.Last_Stage_Update__c = lastUpdate.Date();

    update listOfOldOpp;

    global void finish(Database.BatchableContext BC) {

  • 1
    When are you hitting the limit? In the start() method? – rael_kid Sep 9 '15 at 10:02
  • i am not sure is it in start() method because we are not getting any particular line no. error but it can be on execute while processing Opportunity History .because we have opportunity history: 1 million records. we only got Failed to process batch for class System.LimitException: Apex CPU time limit exceeded – Amit Sep 9 '15 at 10:10

Perhaps the quick fix is to add a break statement to drop out of the OpportunityHistory loop as soon as the required value is found (right after opp.Last_Stage_Update__c = opphis.CreatedDate.Date();) rather than to keep looping and so keep consuming CPU seconds.

But assuming the problem is that it is a large number of OpportunityHistory objects being iterated over, cutting down the number of those down in the original query would also make sense. I'm not exactly sure which date you are trying to set on the Opportunity so this is only an example of the sort of change you could make:

Select Last_Stage_Update__c, (
        Select CreatedDate, StageName
        From OpportunityHistories
        where StageName  != ''
        order by CreatedDate desc
        limit 1
From Opportunity
where Last_Stage_Update__c = null
and IsClosed = false
  • Thanks @Keith for your reply we have tried something like this global UpdateLastStateUpdatedBatch() { query = 'Select Last_Stage_Update__c, (Select CreatedDate, StageName From OpportunityHistories order by CreatedDate desc) From Opportunity where Last_Stage_Update__c = null AND IsClosed = false '; } – Amit Sep 9 '15 at 10:48
  • @Amit The query you have included in your comment is missing the where and limit that reduce the number of OpportunityHistory objects returned. – Keith C Sep 9 '15 at 10:55
  • we are trying to grab the date from opportunity history where opportunity stage changed and last_stage_update field was blank.So we put a solution to process opportunity history in desc order of date and we put break also there but still got the exceptions we can't limit the OpportunityHistories but definitely try where StageName != '' – Amit Sep 9 '15 at 10:57
  • one more thing where StageName != '' .this condition never be happened because on opportunity StageName is required field – Amit Sep 9 '15 at 11:03

It could be an issue with the query in start method which is fetching child records with their parent records. As both are in million it could be possible that it is taking time in preparation phase itself and hitting the CPU time limit. So separating the query on child records and doing this in the execute() could be helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.