+ Start a Discussion
adreameradreamer 

Batch Apex vs Asynchronous Processing

Hi All,

 

I would be most grateful for your views on what is the best approach here.

 

The scenario is as follows. I have a trigger that when fires it should update a large number of records of an object related to the one associated with the trigger.

The delicate bit here is that the number of related records is large, of the order of hundreds of thousands.

 

I am considering two approaches. One based on Batch Apex and the other based on @future call.

 

In the case of Batch Apex I would in the trigger kick a Batch Apex job using a query locator that fetches all the related records that need to be updated. In the Batch Apex implementation (execute method) I would then process the related records and update them.

 

In the approach using @future I would in the trigger collect the records of the object associated with the trigger,and pass them to an @future call. Within the @future call implementation I would fetch the related records with an SOQL for loop (so it does it in batches), loop over the related objects, process them and when done with the batch, update them.

 

In neither case I see running into issues with governor limits but I might be wrong.

 

Any views on what would be the best approach ?

 

Thank you very much in advance,

Fernando

 

Michael_JohnsonMichael_Johnson

I would use batch if the records you are inserting have triggers on them that may run you into governor limit issues. Otherwise @future would be best.

adreameradreamer

Thanks for your input Michael.

 

I take your point. May I ask why @future would be best ?

 

Regards,

Fernando

BritishBoyinDCBritishBoyinDC

@future doesn't get you round governor limits - it just gives you a separate context. So if you plan to process more than 50k records from one update, @future won't help you...

 

I also would be wary of calling a batch from a trigger - SF doesn't recommend it as I think you can only have 5 batches running at any one time...

 

You are probably better off marking a flag on the updated record, and then scheduling a single batch to run every few minutes that looks for all records that need updating...

adreameradreamer

Thank you for your response BritishBoyInDC !

 

Regarding your point that @future doesn't get me round governor limits, great point. I think that what does the trick here is to use the SOQL for loop that allows one to process in chunks. So take for example a trigger on the Account object and you want to process/update the Contacts under each account. I also assume that the number of accounts in the trigger doesn't blow things up in terms of memory, etc. Say 1,000 accounts with 100 contacts each. I would need to process 100,000 contact records. I believe the SOQL for loop lets me get chunks of 200 (by default) that I can process, and then over to the next chunk, and so on. I update the contacts in each iteration so at any time I only deal with an array of 200 elements. In that case you are right and the @future is unnecessary because I can use the SOQL for loop within the trigger. Have I got it right ?

 

Thanks again !

 

Cheers,

Fernando

BritishBoyinDCBritishBoyinDC

I don't think SOQL for loops will help you much here - a trigger acts on the whole context of the update action, so if you update 1000 accounts in one process , it will process 200 hundred accounts at one time, and therefore try and update 20,000 contacts in that single context. Although you can now return 50,000 query rows in one context, I am pretty sure that will still break the DML limits...

 

Batches get round this because each execution of the batch gets it own set of limits, so you could set the batch to process one account at a time, and then the update would stay within the limits... 

adreameradreamer

Yes, it makes sense.

 

I probaly wasn't  clear but my idea was to loop over the contacts, which is what I need to update after the accounts update, so the for loop is over contacts rather than accounts. I was thinking of collecting the batches of contacts of each iteration in an array of say 1,000 and once I fill the array (after 5 iterations of 200) I update them, clear the array, and start over again. But I thibk you are right in that I will reach the maximum number of DML executions at some point if I do it in the context of the trigger. So Batch Apex will be the way to go.

 

Thanks !

Fernando