[SalesForce] Apex CPU time limit exceeded in Apex batch class

I have below apex batch class where I am getting below error. Can someone please let me know where I am wrong to get such an error.
Moreover, I get the parent record for Business_Plan_Approval_Process_abv__c successfully created but fails to create it's child record for Business_Plan_Approval_Process_Data_abv__c using Database.Saveresult.

Error

Apex CPU time limit exceeded

Apex Batch Class

global class batchInsertbp implements Database.Batchable<sObject>, Database.Stateful {

    Public String strParameter;
     Public String strParameter1;
    public Set<String> terr = new Set<String>();
    Public Map<String, List<Business_Plan_abv__c>> accMap = new Map<String, List<Business_Plan_abv__c>>(); 
   //     Public Map<Id, String> IdMap = new Map<Id,String>(); 
    public Business_Plan_Approval_Process_Data_abv__c bpdata = new Business_Plan_Approval_Process_Data_abv__c();
    public batchInsertbp(String strParam , String strParam1) {
        strParameter = strParam;
        strParameter1 = strParam1;
    }

    global Database.QueryLocator start(Database.BatchableContext BC) {
         List<Business_Plan_Approval_Process_abv__c> BPApprovalProcessExist = [select Id, Franchise_abv__c, territory_Name__c from Business_Plan_Approval_Process_abv__c where Franchise_abv__c=:strParameter and Quarter_Time_Period__c=:strParameter1 ];

        for(Business_Plan_Approval_Process_abv__c bp : BPApprovalProcessExist )
        {             
        terr.add(bp.Territory_Name__c);
        }
       // String query = 'Select Name,Id,Salesforce_abv__c,Franchise_abv__c from Territory where Franchise_abv__c =\''+strParameter+'\' and Name NOT in:'+terr;
        System.debug('strParameter@'+strParameter);
        return Database.getQueryLocator([Select Name,Id,Salesforce_abv__c,Franchise_abv__c from Territory where Franchise_abv__c =: strParameter and Name NOT in :terr]);
    }

    global void execute(Database.BatchableContext BC, List<Territory> scope) {
        system.debug('Franchise@@'+strParameter);    
         List<Business_Plan_Approval_Process_abv__c  > BpToInsert = new List<Business_Plan_Approval_Process_abv__c>{};
           List<Business_Plan_Approval_Process_Data_abv__c  > insbpdata = new List<Business_Plan_Approval_Process_Data_abv__c>{};
    List<String> scopenames = new List<String>();
    for (Territory t : scope)
    { system.debug('Territory Name@'+t.Name);
      scopenames.add(t.Name);
    }
    system.debug('scopenames@@'+scopenames);
     List<Business_Plan_abv__c> bp = [select Id,Ambassador_Enrolments_abv__c,Biologic_TRx_Growth_last_3_months_abv__c,Biologic_TRx_Growth_last_6_months_abv__c,Biologic_Index_last_3_months_abv__c,Biologic_Index_last_6_months_abv__c,Business_Planner_Flag_abv__c,Call_Activity_Avg_of_last_3_quarters_abv__c,Call_Priority_Decile_abv__c,City_abv__c,Comments_abv__c,Core_Target_abv__c,Creon_Decile_abv__c,Creon_TRx_growth_change_abv__c,Creon_TRx_Normalized_abv__c,Creon_TRx_Raw_abv__c,DMARD_TRx_Growth_last_3_months_abv__c,DMARD_TRx_Growth_last_6_months_abv__c,DMARD_Index_last_3_months_abv__c,DMARD_Index_last_6_months_abv__c,Dosing_Opportunity_Ranking_abv__c,EPI_Risk_Decile_abv__c,External_Id_abv__c,First_Name_abv__c,Account_abv__c,Growth_opportunity_Decile_abv__c,HCP_Accessibility_Rating_abv__c,HQ_Call_Plan_Flag_abv__c,HQ_Recommended_Frequency_abv__c,Humira_TRx_Growth_last_3_months_abv__c,Humira_TRx_Growth_last_6_months_abv__c,Humira_Decile_abv__c,Humira_Market_Share_last_3_months_abv__c,Humira_Market_Share_last_6_months_abv__c,Humira_Market_Share_Growth_lst_3_mon_abv__c,Humira_Market_Share_Growth_lst_6_mon_abv__c,Humira_TRx_last_3_months_abv__c,Humira_TRx_last_6_months_abv__c,IMS_Number_abv__c,Last_Name_abv__c,Last_Quarter_Calls_By_Rep_abv__c,Last_Quarter_Calls_Rheum_abv__c,Lipase_unit_per_Rx_Strength__c,Market_Decile_BIO_abv__c,Market_Share_abv__c,Market_Share_Growth_abv__c,Market_Share_opportunity_Ranking_abv__c,Market_TRx_Normalized_abv__c,Motivational_Profile_abv__c,My_Action_abv__c,My_Frequency_abv__c,
PDRP_Flag_abv__c,PERT_Decile_abv__c,Priority_1_abv__c,Priority_3_abv__c,Priority_4_abv__c,Priority_5_abv__c,Reason_for_Add_Drop_abv__c,Specialty_abv__c,State_abv__c,Street_Address_abv__c,Suggested_Priority_abv__c,Target_Inclusion_Reason_abv__c,Target_Plan_Flag_abv__c,Territory_abv__c,Total_Planned_calls_to_HCP_abv__c,Zip_abv__c from Business_Plan_abv__c where Territory_abv__c in :scopenames];
     system.debug('terr@@'+terr); 

      for(Business_Plan_abv__c obj : bp) 
     {
     system.debug('BusinessPlan@'+obj);
     if(!accMap.containsKey(obj.Territory_abv__c)){
         accMap.put(obj.Territory_abv__c, new List<Business_Plan_abv__c>{obj});
        system.debug('accmap new@'+accmap.get(obj.Territory_abv__c));
    }else{
         List<Business_Plan_abv__c> tempList = accMap.get(obj.Territory_abv__c);
         tempList.add(obj);
         accMap.put(obj.Territory_abv__c, tempList);
         system.debug('accmap old@'+accmap.get(obj.Territory_abv__c));
    }


     }
     system.debug('scope@@@'+scope);
     system.debug('accmap@@@'+accMap); 
        for(Territory a :scope)
        {
        system.debug('accMap.get(a.Name)@'+accMap.get(a.Name));
        system.debug('check exist@'+accMap.keyset().contains(a.Name));
        If(accMap.keyset().contains(a.Name) == true && accMap.get(a.Name) != null) 
         { for(Business_Plan_abv__c j: accMap.get(a.Name))
             { 
        Business_Plan_Approval_Process_abv__c  newbp = new Business_Plan_Approval_Process_abv__c ();

        newbp.Franchise_abv__c =a.Franchise_abv__c;
        newbp.Territory_Name__c=a.Name; 

        newbp.Status_abv__c = 'Saved';
        newbp.Quarter_Time_Period__c= strParameter1 ;

        BpToInsert.add(newbp);
            }

         }
       }
       system.debug('BpToInsert@Check'+BpToInsert);
        if(!BpToInsert.isEmpty()){
    system.debug('BpToInsert@Check'+BpToInsert);
    Database.SaveResult[] srList = Database.insert(BpToInsert, false);


    for (Integer i = 0; i < srList.size(); i++ ) {
     Database.SaveResult sr = srList[i];
        if (sr.isSuccess()) {

           system.debug('accmap@'+accMap.get(BpToInsert[i].Territory_Name__c)); 
           system.debug('TerrName@'+BpToInsert[i].Territory_Name__c);
             //Alstitem.External_ID_vod__c = actID+'-'+key;


           if(accMap.get(BpToInsert[i].Territory_Name__c) != null && accMap.get(BpToInsert[i].Territory_Name__c).size() > 0)
         {   for(Business_Plan_abv__c j: accMap.get(BpToInsert[i].Territory_Name__c))
             { 
             Business_Plan_Approval_Process_Data_abv__c bpdata = new Business_Plan_Approval_Process_Data_abv__c();
             bpdata.Business_Plan_Approval_Process_abv__c= sr.getId();  
             bpdata.Territory_abv__c= BpToInsert[i].Territory_Name__c;
             bpdata.External_Id_abv__c = j.Account_abv__c+'_'+sr.getId();
           /* Schema.FieldSet fieldSetToCopy = Schema.SObjectType.Business_Plan_abv__c.FieldSets.Approval_Process_Data_Fields;
            for (Schema.FieldSetMember dataField : fieldSetToCopy.getFields()) {
              bpdata.put(dataField.getFieldPath(), j.get(dataField.getFieldPath()));
            } */

             bpdata.Business_Planner_Flag_abv__c = j.Business_Planner_Flag_abv__c;
            bpdata.Call_Activity_Avg_of_last_3_quarters_abv__c = j.Call_Activity_Avg_of_last_3_quarters_abv__c;
            bpdata.Call_Priority_Decile_abv__c = j.Call_Priority_Decile_abv__c;
            bpdata.City_abv__c = j.City_abv__c;
            bpdata.Comments_abv__c = j.Comments_abv__c;
            bpdata.Core_Target_abv__c = j.Core_Target_abv__c;
            bpdata.Creon_Decile_abv__c = j.Creon_Decile_abv__c;
            bpdata.Creon_TRx_growth_change_abv__c = j.Creon_TRx_growth_change_abv__c;
            bpdata.Creon_TRx_Normalized_abv__c = j.Creon_TRx_Normalized_abv__c;
            bpdata.Creon_TRx_Raw_abv__c = j.Creon_TRx_Raw_abv__c;
            bpdata.DMARD_TRx_Growth_last_3_months_abv__c = j.DMARD_TRx_Growth_last_3_months_abv__c;
            bpdata.DMARD_TRx_Growth_last_6_months_abv__c = j.DMARD_TRx_Growth_last_6_months_abv__c;
            bpdata.DMARD_Index_last_3_months_abv__c = j.DMARD_Index_last_3_months_abv__c;
            bpdata.DMARD_Index_last_6_months_abv__c = j.DMARD_Index_last_6_months_abv__c;
            bpdata.Dosing_Opportunity_Ranking_abv__c = j.Dosing_Opportunity_Ranking_abv__c;
            bpdata.EPI_Risk_Decile_abv__c = j.EPI_Risk_Decile_abv__c;
           //
            bpdata.First_Name_abv__c = j.First_Name_abv__c;
            bpdata.Account_abv__c = j.Account_abv__c;
            bpdata.Growth_opportunity_Decile_abv__c = j.Growth_opportunity_Decile_abv__c;
            bpdata.HCP_Accessibility_Rating_abv__c = j.HCP_Accessibility_Rating_abv__c;
            bpdata.HQ_Call_Plan_Flag_abv__c = j.HQ_Call_Plan_Flag_abv__c;
            bpdata.HQ_Recommended_Frequency_abv__c = j.HQ_Recommended_Frequency_abv__c;
            bpdata.Humira_TRx_Growth_last_3_months_abv__c = j.Humira_TRx_Growth_last_3_months_abv__c;
            bpdata.Humira_TRx_Growth_last_6_months_abv__c = j.Humira_TRx_Growth_last_6_months_abv__c;
            bpdata.Humira_Decile_abv__c = j.Humira_Decile_abv__c;
            bpdata.Humira_Market_Share_last_3_months_abv__c = j.Humira_Market_Share_last_3_months_abv__c;
            bpdata.Humira_Market_Share_last_6_months_abv__c = j.Humira_Market_Share_last_6_months_abv__c;
            bpdata.Humira_Market_Share_Growth_lst_3_mon_abv__c = j.Humira_Market_Share_Growth_lst_3_mon_abv__c;
            bpdata.Humira_Market_Share_Growth_lst_6_mon_abv__c = j.Humira_Market_Share_Growth_lst_6_mon_abv__c;
            bpdata.Humira_TRx_last_3_months_abv__c = j.Humira_TRx_last_3_months_abv__c;
            bpdata.Humira_TRx_last_6_months_abv__c = j.Humira_TRx_last_6_months_abv__c;
            bpdata.IMS_Number_abv__c = j.IMS_Number_abv__c;
       //  Not Writable     bpdata.Indicator_abv__c = j.Indicator_abv__c;
            bpdata.Last_Name_abv__c = j.Last_Name_abv__c;
            bpdata.Last_Quarter_Calls_By_Rep_abv__c = j.Last_Quarter_Calls_By_Rep_abv__c;
            bpdata.Last_Quarter_Calls_Rheum_abv__c = j.Last_Quarter_Calls_Rheum_abv__c;
            bpdata.Lipase_unit_per_Rx_Strength__c = j.Lipase_unit_per_Rx_Strength__c;
            bpdata.Market_Decile_BIO_abv__c = j.Market_Decile_BIO_abv__c;
            bpdata.Market_Share_abv__c = j.Market_Share_abv__c;
            bpdata.Market_Share_Growth_abv__c = j.Market_Share_Growth_abv__c;
            bpdata.Market_Share_opportunity_Ranking_abv__c = j.Market_Share_opportunity_Ranking_abv__c;
            bpdata.Market_TRx_Normalized_abv__c = j.Market_TRx_Normalized_abv__c;
            bpdata.Motivational_Profile_abv__c = j.Motivational_Profile_abv__c;
            bpdata.My_Action_abv__c = j.My_Action_abv__c;
            bpdata.My_Frequency_abv__c = j.My_Frequency_abv__c;
            bpdata.PDRP_Flag_abv__c = j.PDRP_Flag_abv__c;
            bpdata.PERT_Decile_abv__c = j.PERT_Decile_abv__c;
            bpdata.Priority_1_abv__c = j.Priority_1_abv__c;
            bpdata.Priority_3_abv__c = j.Priority_3_abv__c;
            bpdata.Priority_4_abv__c = j.Priority_4_abv__c;
            bpdata.Priority_5_abv__c = j.Priority_5_abv__c;
            bpdata.Reason_for_Add_Drop_abv__c = j.Reason_for_Add_Drop_abv__c;
            bpdata.Specialty_abv__c = j.Specialty_abv__c;
            bpdata.State_abv__c = j.State_abv__c;
            bpdata.Street_Address_abv__c = j.Street_Address_abv__c;
            bpdata.Suggested_Priority_abv__c = j.Suggested_Priority_abv__c;
            bpdata.Target_Inclusion_Reason_abv__c = j.Target_Inclusion_Reason_abv__c;
            bpdata.Target_Plan_Flag_abv__c = j.Target_Plan_Flag_abv__c;

            bpdata.Total_Planned_calls_to_HCP_abv__c = j.Total_Planned_calls_to_HCP_abv__c;
            bpdata.Zip_abv__c = j.Zip_abv__c;  


             }

         }
             system.debug('insbpdata@@'+insbpdata);
             insbpdata.add(bpdata);
        }
    }
    try {
        INSERT insbpdata;
    } 
    catch(Exception e) {
        system.debug(e.getMessage());
    }
}

        //insert BpToInsert;   
    }   

    global void finish(Database.BatchableContext BC) {
    }
}

Best Answer

Governor limits are harder to diagnose in many cases, because there is not always an obvious "smoking gun." Strictly speaking, there's nothing in this code that jumps out and screams "Here I am! I'm the bug!" Instead, it's most likely a cumulative effect because of all the extra code you've written. If you interested in figuring out the primary culprit, you'd want to turn Profiling up to the max, run the batch, and check the logs to see where the most time is being used.

That said, I would bet that you're spending an inordinate amount of time using your debug statements. They take up time, and a lot of it. You also have a lot of waste by not using the SObject constructor, excess checks against null values, missing keys, etc.

Here's my suggestions, based on the above information:

Remove Debug Statements

Remove all your debug statements. You should learn how to read debug logs and use checkpoints for debugging purposes. Do not leave debug statements in production code.

Use SObject Constructors

Every line of execution uses extra CPU time. It's more efficient to populate all the fields at once:

    for(Business_Plan_abv__c j: accMap.get(a.Name)) {
        BpToInsert.add(
            new Business_Plan_Approval_Process_abv__c(
                Franchise_abv__c =a.Franchise_abv__c,
                Territory_Name__c=a.Name,
                Status_abv__c = 'Saved',
                Quarter_Time_Period__c= strParameter1
            )
        );
    }

Avoid Excessive Checks

You rarely need to use more than one check to verify that you can go down a particular code path. All of your code runs in paranoia mode, and that costs you CPU time. For example, the following code:

    If(accMap.keyset().contains(a.Name) == true && accMap.get(a.Name) != null) 

Could instead be written as:

    If(accMap.get(a.Name) != null) 

The first check is not necessary, because we're really just worried about seeing if the map has a record at the given key.

Similarly:

    if(!BpToInsert.isEmpty()){

Is not necessary, because the platform automatically ignores empty lists, meaning that there's no bad side effects of inserting an empty list.

Also:

       if(accMap.get(BpToInsert[i].Territory_Name__c) != null && accMap.get(BpToInsert[i].Territory_Name__c).size() > 0)

It's okay to iterate over an empty list, so again, we just need to worry about null values, so:

       if(accMap.get(BpToInsert[i].Territory_Name__c) != null)

Unnecessary Fields in Query

Your query is getting extra data you don't need, such as Biologic_TRx_Growth_last_3_months_abv__c (according to my find/replace dialog). Combine that with debug statements, and you're looking at wasted CPU time.

Overall, I suspect that your execute method would probably run okay with these modifications, but unfortunately, we won't know until you try it.

Related Topic