1

I am processing hundreds of thousands of call records that must be assigned to their respective telephone lines based on the phone number. I wanted to retrieve a list of Phone Line records and then create multiple batch jobs to find all related telephone call records.

    public void GetLines(){

            List<Lines__c> lines = [Select id, phone_number__c from lines__c ORDER BY Line_Status__c ASC];

            for(Lines__c l: lines){
                       ExecuteBatchUpdate(l.id, l.phone_number__c );         
            }  
        }

    public void ExecuteBatchUpdate(Id lineid, String phone){
    ..
    If(Test.isRunningTest()){
                Id batchInstanceId = Database.executeBatch(new BatchUpdateCallRecordsAssingLine(q, Lineid), 20); 
                System.abortJob(batchInstanceId);
            }else{
                    Database.executeBatch(new BatchUpdateCallRecordsAssingLine(q, Lineid));
            }
    ..
    }

 global void execute(Database.BatchableContext bc, List<Detailed_Call_Data__c> scope){

    List <Detailed_Call_Data__c> callsData = new List<Detailed_Call_Data__c>();

    for (Detailed_Call_Data__c callrec : scope) {
        Detailed_Call_Data__c rectoupdate = new Detailed_Call_Data__c();
        rectoupdate.id = callrec.id;
        rectoupdate.Line__c = lineId; 

        callsData.add(rectoupdate);
    }
    update callsData;
} 

Unfortunately, I get System.LimitException: Too many DML statements: 151.

Is it possible to call Database.executeBatch from a loop? If not, what is the right way do deal with this scenario?

9
  • have each batch finish() invoke the next batch
    – cropredy
    Oct 31 '19 at 17:27
  • 1
    What are the batches doing? Calling a batch with a single record input is not an ideal use case most of the time.
    – David Reed
    Oct 31 '19 at 17:32
  • the batch picks up thousands of Phone Call records and adds a relationship with a matching line based on the phone number. there are 12K Lines and thousands of call records.
    – wmin
    Oct 31 '19 at 17:41
  • @cropredy could you pls elaborate?
    – wmin
    Oct 31 '19 at 18:12
  • i'm with David - why not execute a single batch where the start method does the query on Lines__c?
    – cropredy
    Oct 31 '19 at 18:22
0

I think you may be shortchanging yourself on the power of Batch Apex.

My understanding is this. You've got some records in Lines__c, at high volume (12K), and many more records in Detailed_Call_Data__c (hundreds of thousands).

The purpose of your batch job is to link up (based on a phone number, which I really hope is an indexed field) the Detailed_Call_Data__c records to their corresponding Lines__c.

Running a batch job for each Lines__c is not going to be the most efficient way to do this. (For one thing, you'll hit the Apex Flex Queue limit really fast). Instead, I see a couple of viable options, which are not mutually exclusive.

Scheduled Incremental Update Batch

Run a batch on the Detailed_Call_Data__c every night.

Have it query for only records that aren't associated with a Lines__c already.

In execute(), collect the identifiers (phone numbers) for that batch of Detailed_Call_Data__c. Query for the matching Lines__c and build a Map<String, Lines__c> to collate the numbers to the lines. Then, iterate over the Detailed_Call_Data__c again, and populate the relationships to those Lines__c that were located.

Group Incoming Lines__c in Each Batch Job

Keep your current approach, except instead of passing a single Lines__c into your batch, pass a List<Lines__c>. In start(), collect the phone numbers of those Lines__c records and run a query for Detailed_Call_Data__c that matches any of them.

In execute(), build a Map<String, Lines__c> to collate the numbers to the lines. Then, iterate over your scope of Detailed_Call_Data__c records and assign each to the matching Lines__c.

Summary

Either way (or both), you'll massively reduce the number of Apex batch jobs you're running, and will likely get much better performance out of it.

1
  • David, many thanks for sharing your knowledge. Your detailed explanation is exactly what I needed. Thanks to all the contributors!
    – wmin
    Nov 1 '19 at 11:31

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.