I have written a batch apex which will update few fields in contacts and account objects of about 1.5 million records. I initiated it yesterday and in 10 hours it updated just 300k records. I wanted to check if this is quite usual, or if there is a way to make this batch update faster?
This is the code I am using to update mass records:
global class UpdateFields implements Database.Batchable<SObject>{
global String query;
global String Entity;
global String Email;
global Database.QueryLocator start(Database.BatchableContext BC){
query = 'SELECT End_Date_180_Prior__c, Pardot_End_Date_180_Prior__c, Pardot_Related_C_Account__c, AccountId, Id FROM contact';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Contact> scope){
List<Contact> contcts = (List<Contact>)scope;
Map<Id, Account> accts = new Map<Id, Account>([SELECT Related_C_Account_Text__c,
Membership_Status__c
FROM Account WHERE Id IN (SELECT AccountId FROM Contact WHERE Id = :scope)]);
for(Contact c : contcts){
Account a = accts.get(c.AccountId);
c.Pardot_End_Date_180_Prior__c = c.End_Date_180_Prior__c;
//updating 10 more fields here
if(a != null) {
c.Pardot_Related_C_Account__c = a.Related_C_Account_Text__c;
a.Pardot_Membership_Status__c = a.Membership_Status__c;
}
}
update contcts;
update accts.values(); // save changes to the accounts
}
global void finish(Database.BatchableContext BC) {
/*Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] {email});
mail.setReplyTo('[email protected]');
mail.setSenderDisplayName('Account and Contacts Batch Processing');
mail.setSubject('Batch Process Completed');
mail.setPlainTextBody('Batch Process has completed');
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });*/
}
}
After the optimizations suggested by @sfdcfox, execute function of my batch now looks like this:
global void execute(Database.BatchableContext BC, List<Contact> scope){
List<Contact> contcts = new List<Contact>();
Map<Id, Account> accts = new Map<Id, Account>([SELECT Related_C_Account_Text__c,
Membership_Status__c
FROM Account WHERE Id IN (SELECT AccountId FROM Contact WHERE Id = :scope)]);
for(Contact c : scope){
Account a = accts.get(c.AccountId);
contcts.add(new Contact(
Id = c.Id,
Pardot_End_Date_180_Prior__c = c.End_Date_180_Prior__c;
Pardot_Related_C_Account__c = a.Related_C_Account_Text__c;
//updating 10 more fields here
));
if(a != null) {
a.Pardot_Membership_Status__c = a.Membership_Status__c;
//updating 1 more field here
}
}
update contcts;
update accts.values(); // save changes to the accounts
}
It now gives two errors to me: 1. Attempt to de-reference a null object - I am assuming this is because of the cross object mapping in the contacts 2. Apex CPU time limit exceeded - If I execute the batch with 200 records as the scope, I do not get this error.
Any ideas of what could resolve these issues in my case?