
Please see below class. Which I am using to update the Contact Email Id's after TEST Refresh.
Could you please help to optimize this. Curently this takes alot of time.
Total Records : 1200000
Batch Size : 2000
global class massUpdateContactEmailsPostRefresh implements Database.Batchable<SObject>,Database.Stateful
{
//Variable Declaration
global Integer recordsUpdated = 0;
global Integer totalRecords = 0;
global Integer success = 0;
global Integer failure = 0;
public String query;
public String refreshedEnvironment='.test';
global Map<Id, String> errorMap {get; set;}
global Map<Id, SObject> IdToSObjectMap {get; set;}
global massUpdateContactEmailsPostRefresh (){
errorMap = new Map<Id, String>();
IdToSObjectMap = new Map<Id, SObject>();
}
global Database.QueryLocator start(Database.BatchableContext bc){
query = 'Select Email from Contact WHERE Email !=null';
System.debug(query);
return Database.getQueryLocator(query);
}
// Execute method is used to update all the Contact Email Id
global void execute(Database.BatchableContext bc, List<Contact> scope){
for(Contact contact : scope){
if(contact.Email!=null || contact.Email!='')
contact.Email = contact.Email+refreshedEnvironment;
recordsUpdated+=1;
}
List<Database.SaveResult> dsrs = Database.Update(scope, false);
Integer index = 0;
for(Database.SaveResult dsr : dsrs){
if(!dsr.isSuccess()){
String errMsg = dsr.getErrors()[0].getMessage();
errorMap.put(scope[index].Id, errMsg);
IdToSObjectMap.put(scope[index].Id, scope[index]);
}
index++;
}
}
global void finish(Database.BatchableContext bc){
totalRecords = recordsUpdated;
failure = errorMap.size();
success = totalRecords - failure ;
String summary = 'Summary for the Record Updation : \n1. #.Records : '+totalRecords +' \n2. #.Success : '+success +' \n3. #.Failures : '+failure;
//Send an email to the User after your batch completes
if(!errorMap.isEmpty()){
AsyncApexJob a = [SELECT id, ApexClassId,
JobItemsProcessed, TotalJobItems,
NumberOfErrors
FROM AsyncApexJob
WHERE id = :bc.getJobId()];
String body = 'Hi, \nYour batch job '
+ 'massUpdateContactEmailsPostRefresh '
+ 'has finished. \n'
+ summary
+ '\n\nPlease find the attached list of errors for your reference. \n \n This is an auto generated email. Please Do Not Reply\n.';
// Creating the CSV file
String finalstr = 'Id, Email, Error \n';
String subject = 'Contact - Apex Batch Error List : SFDC TEST';
String attName = 'Contact Errors.csv';
for(Id id : errorMap.keySet()){
string err = errorMap.get(id);
Contact cntct = (Contact) IdToSObjectMap.get(id);
string recordString = '"'+id+'","'+cntct.Email+'","'+err+'"\n';
finalstr = finalstr +recordString;
}
// Define the email
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
// Create the email attachment
Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
efa.setFileName(attName);
efa.setBody(Blob.valueOf(finalstr));
// Sets the paramaters of the email
String sendToEmailAddress='aksharma@xyz.com';
email.setSubject( subject );
email.setToAddresses(new String[] {sendToEmailAddress});
email.setPlainTextBody( body );
email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});
// Sends the email
Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
}
}
} // end of class massUpdateContactEmailsPostRefresh
2 件の回答
Try to avoid stateful batch unless and until it is extremely important.
Use [Object].field = value instead of SObject.get() / SObject.put().
Or you can use concurrent bactch approach to improve performance.
https://hub.appirio.com/tech-blog/improving-batch-performance-with-concurrent-batches-in-salesforce