2

I call to a batch class on 204 records:

PaymentAgreementMonitor myBatchObject = new PaymentAgreementMonitor();
Id batchId = Database.executeBatch(myBatchObject, 66);

When it runs, it is running on 66 records, 34 records, 66 records, 34 records, 4 records.

Why does it not run 66 records, 66 records, 66 records, and 6 records? What could be causing this behavior?

5

When a batch Apex job is executed with a set batch size, it is not guaranteed that the number of records processed in one batch iteration will be the same as the set batch size (scopeSize). As a result the number of batch iterations is not the smallest integer that is greater than the number of records returned by the query locator divided by the set scope size.

Records from the query locator are retrieved in chunks of a given chunk size, called retrieveChunkSize.

There are three available values for retrieveChunkSize: 100, 400, and 2000, and the smallest value that is greater than or equal to the scope size (scopeSize) will be chosen.

  • If 1 <= scopeSize <= 100, then retrieveChunkSize = 100
  • If 101 <= scopeSize <= 400, then retrieveChunkSize = 400
  • If 401 <= scopeSize <= 2000, then retrieveChunkSize = 2000

However, each execute chunk (that is the records passed to the execute() method) will have a size that will depend on the chosen retrieveChunkSize, the scopeSize, and the available records in the current retrieve chunk.

So, say that you have 290 records, scope size is 75, and hence retrieveChunkSize is 100. In this case we would have 3 retrieve chunks and 6 execute chunks:

  1. Retrieve chunk 1: retrieve first 100 records
    • Execute chunk 1: pass first 75 records to execute() method
    • Execute chunk 2: pass remaining 25 records from this retrieve chunk to execute() method
  2. Retrieve chunk 2: retrieve next 100 records
    • Execute chunk 1: pass first 75 records of this retrieve chunk to execute() method
    • Execute chunk 2: pass remaining 25 records from this retrieve chunk to execute() method
  3. Retrieve chunk 3: retrieve remaining 90 records
    • Execute chunk 1: pass first 75 records of this retrieve chunk to execute() method
    • Execute chunk 2: pass remaining 15 records from this retrieve chunk to execute() method

In this case, total amount of batches = 6, not ceiling(290/75) = 4.

In essence, in this case if we have full chunks of 100 records, these will get processed in two child batch executions of 75 and 25 records, respectively.

In your case 66 records, 34 records, 66 records, 34 records, 4 records. Your scope is <100 so the first chunk is the 66 and 34 is remaining chunk of 100 and another set of 66 and 34 and finally the remaining 4 records.

NOTE: The contents of this answer apply to batch Apex jobs where the start method returns a query locator for a SOQL query that doesn't contain inner or subqueries in it.

| improve this answer | |
  • 4
    +1 That's really cool to know! – sfdcfox Dec 7 '18 at 22:15
  • @Olivia You're welcome. Glad to help! – codeyinthecloud Dec 10 '18 at 21:58

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.