function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Guru sfdcGuru sfdc 

Apex CPU Time Limited

Hi All,

Facing the issues like getting a System.LimitException: Apex CPU time limit exceeded when trying to update my opportunities. Via data loader can someone please help me on this code, so we don't run into this error anymore and how to avoid it again with future Triggers.
 
Thanks
 
Guru sfdcGuru sfdc
Trigger is :

Trigger AccountPartnerType on Account (after update){   
       if(AccountPartnerTypecls.isfutureupdate!=true){
        AccountPartnerTypecls acpt = new AccountPartnerTypecls();
        if(AccountPartnerTypecls.Aptcalc)
        acpt.AccountPartnerTypecalc(Trigger.new,trigger.newmap,trigger.oldmap);     
        AccountPartnerTypecls.isfutureupdate=true; 
     }
}

Apex class :

public class AccountPartnerTypecls{
    public static Boolean Aptcalc = true; 
    public static Boolean Aptcalc1 = false;  
    public static Boolean Aptcalc2 = false;   
    public static Boolean isfutureupdate=false;
    public void AccountPartnerTypecalc(List<Account> aclist,map<id,Account> newmap,map<id,Account> oldmap)
    {
        set<id> accidset = new set<id>();  
        set<string> ulprntidset = new set<string>();    
        string dulprnt; 
        map<string,List<Account>>  accmap = new  map<string,List<Account>>();
        system.debug('*********'+aclist.size());            
        for(Account acc: aclist)
        {
            accidset.add(acc.id); 
            // if(acc.GE_Global_Ultimate_Reporting_Account__c!=Null)  //GE_Digital_Ultimate_Parent_ID__c 
            // Ultimate_Parent_ID__c
            ulprntidset.add(acc.GE_Digital_Ultimate_Parent_ID__c);
            dulprnt= acc.GE_Digital_Ultimate_Parent_ID__c;
            system.debug('*********'+dulprnt);
        }
        
        system.debug('*********'+dulprnt);  
        
        List<Account> hiracclist = new List<Account>();
        List<Account> aclist1 = [select id, name,Partner_Status__c,Is_Partner__c,Account_Type__c,Parentid,GE_Digital_Ultimate_Parent_ID__c from Account where  GE_Digital_Ultimate_Parent_ID__c  =:dulprnt  AND Parentid!=null AND id NOT IN:accidset ]; 
        
        system.debug('*********'+aclist1.size());  
        
        for(Account a : aclist1)
        { 
            if(accmap.containskey(a.GE_Digital_Ultimate_Parent_ID__c))
            accmap.get(a.GE_Digital_Ultimate_Parent_ID__c).add(a);
            else
            {
                List<Account> alist = new List<Account>();
                alist.add(a); 
                accmap.put(a.GE_Digital_Ultimate_Parent_ID__c,alist);
            }
        }
        for(Account acc: [select id, name,Partner_Status__c,Is_Partner__c,Account_Type__c,Parentid,GE_Digital_Ultimate_Parent_ID__c from Account where ID IN :accidset ])
        {
            string acctype='';
            if(accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c)!=null)
            {
                /* if(accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c).contains(acc)){
                accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c).set(0, acc);
                accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c).remove(0);
                }*/
                for(Account acchr : accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c))
                {
                    //acchr.Is_Partner__c= acc.Is_Partner__c;
                    if(acc.Is_Partner__c)
                    acchr.Account_Type__c = 'Partner';
                    else
                    acchr.Account_Type__c= '';
                    hiracclist.add(acchr); 
                }
                if(acc.Is_Partner__c)
                {
                    if(acc.parentid!=null)
                    Aptcalc1 =true;
                    acc.Account_Type__c= 'Partner';
                    hiracclist.add(acc);
                }
                else{
                    if(acc.parentid!=null)
                    Aptcalc2 =true;
                    acc.Account_Type__c= '';
                    hiracclist.add(acc);
                }
            }
            else{
                if(acc.Is_Partner__c)
                {
                    acc.Account_Type__c= 'Partner'; 
                    hiracclist.add(acc);
                }
                else{
                    acc.Account_Type__c= ' ';
                    hiracclist.add(acc);
                }
            }
        }       
        Account a=  [select id, name,Partner_Status__c,Is_Partner__c,Account_Type__c,Parentid,GE_Digital_Ultimate_Parent_ID__c from Account where ID  =:dulprnt];
        if(Aptcalc1)
        {
            a.Account_Type__c= 'Partner';
            hiracclist.add(a);
        }
        else if(Aptcalc2)
        {
            a.Account_Type__c= '';
            hiracclist.add(a);
        }
        Aptcalc = false; 
        isfutureupdate=True;         
        update  hiracclist;
    }
}

Thanks

 
LBKLBK
How many record are you trying to update?
Can you reduce the batch size in Data Loader and try?

I would suggest reduce the batch size to half of what it is now and try it.
If it doesn't work again, reduce it further.
Guru sfdcGuru sfdc
Hi LBK,

Thanks for your quick reply.one account having more than 500 child records.Eventhough if i have try to update one field manually getting same error. Can you please help me on this?
 
Thanks
 
JLA.ovhJLA.ovh
Your first SELECT is querying child accounts with same ultimate parent (N records, N can be huge for global big accounts). Your second query is retrieving all your updated accounts (M records). For each of them (in the second query) you will loop on the map defined form the first query. This will do NxM operations . This can be huge. To reduce the cost of the inner loop, instead of doing
 
for(Account acchr : accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c)){
    if(acc.Is_Partner__c)
        acchr.Account_Type__c = 'Partner';
    else acchr.Account_Type__c= '';
    hiracclist.add(acchr);
}
You could put invariant outside of the loop, this will remove N-1 tests :
    String val=acc.Is_Partner__c?'Partner':''
    for(Account acchr : accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c)){
        acchr.Account_Type__c = val;
        hiracclist.add(acchr); 
    }
You can still optimize this big loop (removing unused fields, organizing tests, removing useless code...) and all the class as this :
public class AccountPartnerTypecls{
    public static Boolean Aptcalc = true; 
    public static Boolean Aptcalc1 = false;  
    public static Boolean Aptcalc2 = false;   
    public static Boolean isfutureupdate=false;
    public void AccountPartnerTypecalc(List<Account> aclist,map<id,Account> newmap,map<id,Account> oldmap)    {
        set<id> accidset = new set<id>();  
        string dulprnt; 
        List<Account> hiracclist = new List<Account>();
        map<string,List<Account>>  accmap = new  map<string,List<Account>>();
        system.debug('*********'+aclist.size());
	for(Account acc: aclist) {
		accidset.add(acc.id); 
		dulprnt= acc.GE_Digital_Ultimate_Parent_ID__c;
		//system.debug('*********'+dulprnt);
	}
        system.debug('*********'+dulprnt);  
        
	for(Account a : [select id, GE_Digital_Ultimate_Parent_ID__c from Account where  GE_Digital_Ultimate_Parent_ID__c  =:dulprnt  AND Parentid!=null AND id NOT IN:accidset ]) { 
		if(accmap.containskey(a.GE_Digital_Ultimate_Parent_ID__c))
			accmap.get(a.GE_Digital_Ultimate_Parent_ID__c).add(a);
		else accmap.put(a.GE_Digital_Ultimate_Parent_ID__c,new Account[]{a});
	}
	for(Account acc: [select id, Is_Partner__c,Parentid,GE_Digital_Ultimate_Parent_ID__c from Account where ID IN :accidset ]) {
		String val=acc.Is_Partner__c?'Partner':''
		if(accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c)!=null) {
			for(Account acchr : accmap.get(acc.GE_Digital_Ultimate_Parent_ID__c)){
				acchr.Account_Type__c = val;
				hiracclist.add(acchr); 
			}
			if(acc.parentid!=null){
				if(acc.Is_Partner__c)Aptcalc1 =true;
				else Aptcalc2 =true;
			}
		}
		acc.Account_Type__c=val;
		hiracclist.add(acc);
	}
        Account a=  new Account();
	a.Id=dulprnt;
        if(Aptcalc1) a.Account_Type__c= 'Partner';
        else if(Aptcalc2) a.Account_Type__c= '';
        hiracclist.add(a);
        Aptcalc = false; 
        isfutureupdate=True;         
        update  hiracclist;
    }
}
It is shorter, quicker to run, consuming less CPU

Side note - we can identify an issue (not related to the cpu) in your code : the trigger can update multiple accounts with different ultimate parents and you manage only 1 ultimate parent with the variable dulprnt.

We can see that you will go multiple times in your for() inner loop if your trigger is updating multiple records with the same ultimate parent. It is not efficient. You should build a list of ultimate parents that you have already managed to avoid this. This will have the benefit to reduce the size of the list "hiracclist", avoiding duplicates in that list.
Guru sfdcGuru sfdc
Hi AdminBooster,

Thanks for your valid explanation. I have compressed my logic. When am trying to enable as partner getting error like "System.ListException: Duplicate id in list: ".Can you please help me on this.

​Thanks