我們在處理大規模數據時,經常會發生各種限制。但是使用Apex Batch會將需要處理的數據,分割開來執行。
也就是進行異步處理數據,而不會超出平臺的限制。
同步和異步的概念:
生活中,同步就是表示兩件事請同時做,比如一邊聽歌一邊學習寫作業。這兩件事是同時進行。
生活中,異步就是表示兩件事請有先後順序,只能是先聽歌,聽完歌之後再學習寫作業。這兩件事是有順序的進行。
軟體程序中,完全是相反的,也就是同步是有順序經進行,異步是同時進行。
同步:每個程序處理都是有順序的,不能跨越執行,比如用戶必須先註冊,然後才可以登錄,這個流程不能變。
異步:程序只是發送調用的指令,不用等待被調用的方法完全執行完,而是會繼續執行下一個程序。就像打開一個頁面,是邊加載邊顯示在頁面上。
同步是需要等待,異步不需要等待。
看一下英文表示,同步:Synchronize,異步:Asynchronous
批處理Apex語法
實現 :Database.Batchable 接口
和三個方法:
start()
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}
Apex Batch開始,在Apex批處理作業的開始處被調用一次,收集並返回處理的對象或記錄。
使用QueryLocator對象時,將忽略SOQL查詢檢索到的記錄總數的限制條件限制,並且最多可以查詢5000萬條記錄。
使用Iterable對象時,SOQL查詢檢索的記錄總數的限制條件限制仍然適用。
execute()
global void execute(Database.BatchableContext BC, list<P>){}
接收start()傳過來的對象或記錄,默認批處理大小為200條記錄。200條執行一次。
批處理記錄開始它們傾向於按照從方法中接收到的順序執行。但是,執行記錄批處理的順序取決於各種因素。無法保證執行順序。
finish ()
global void finish(Database.BatchableContext BC){}
用於執行後處理操作(例如發送郵件,日誌登錄,調用其他Batch等),並且在處理完所有批次後調用一次。
批處理Apex類的框架如下:
global class MyBatchClass implements Database.Batchable<sObject> {
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {
// collect the batches of records or objects to be passed to execute
}
global void execute(Database.BatchableContext bc, List<P> records){
// process each batch of records
}
global void finish(Database.BatchableContext bc){
// execute any post-processing operations
}
}
調用批處理類
MyBatchClass myBatchObject = new MyBatchClass();
Id batchId = Database.executeBatch(myBatchObject,200);
每次調用Batch Apex時,都會創建一個AsyncApexJob記錄,以便跟蹤工作進度。可以通過SOQL查看進度並管理Apex作業隊列中的作業。
AsyncApexJob job = [SELECT Id, Status, JobItemsProcessed, TotalJobItems, NumberOfErrors FROM AsyncApexJob WHERE ID = :batchId ];
下面看一個具體的例子,
當環境中有許多操作在一個對象上時,例如PB,Flow,Trigger等,我們對這個對象進行數據移行,需要更新等操作時,需要更加小心,
因為有可能會觸發【Apex CPU time limit exceeded】,導致比如用dataloader更新,需要設置batch size為50,20,甚至為1,這樣執行時間會大大加大。
Code more efficiently to avoid 『Apex CPU time limit exceeded』https://help.salesforce.com/articleView?id=000339361&language=ja&type=1&mode=1
Salesforce Developer Limits and Allocations Quick Referencehttps://developer.salesforce.com/docs/atlas.ja-jp.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm
Maximum CPU time on the Salesforce servers510,000 milliseconds60,000 millisecondsMaximum execution time for each Apex transaction10 minutes
數據移行時,有些Object需要直接更新,什麼操作都不用,只是更新,為了讓其他的PB等生效,設置上其相應的值。
也就是所謂的空更新,用dataloader做一個欄位更新也可以實現,這裡用Apex Batch來完成。
首先在Account對象上創建一個【空更新Flag】CheckBox欄位。
global class AccountUpdateBatch implements Database.batchable<sObject> {
global AccountUpdateBatch() {
}
global Database.QueryLocator start(Database.BatchableContext BC) {
String query = 'select Id, Name, karakousin_Flag__c from Account';
//return Database.getQueryLocator([select Id, Name, karakousin_Flag__c from Account]);
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<sObject> scope) {
List<Account> accountList = new List<Account>();
Account acc = new Account();
for (sObject s : scope) {
acc = new Account();
acc = (Account)s;
acc.karakousin_Flag__c = true;
accountList.add(acc);
}
if (accountList.size() > 0) update accountList;
}
global void finish(Database.BatchableContext BC) {
// Get the ID of the AsyncApexJob representing this batch job
// from Database.BatchableContext.
// Query the AsyncApexJob object to retrieve the current job's information.
AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed,
TotalJobItems, CreatedBy.Email
FROM AsyncApexJob WHERE Id =
:BC.getJobId()];
// Send an email to the Apex job's submitter notifying of job completion.
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
String[] toAddresses = new String[] {a.CreatedBy.Email};
mail.setToAddresses(toAddresses);
mail.setSubject('Apex Sharing Recalculation ' + a.Status);
mail.setPlainTextBody
('The batch Apex job processed ' + a.TotalJobItems +
' batches with '+ a.NumberOfErrors + ' failures.');
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}
}
確認一下空更新Flag 欄位。
通過匿名窗口執行,Apex Batch
回到頁面 在確認空更新Flag 欄位。
如果Batch類同時實現Database.Stateful,
可以指定保留這些事務之間的狀態。Database.Stateful使用時,僅實例成員變量在事務之間保存值。
靜態成員變量不會在事務之間保留其值,而是會重置。當您要計數或匯總正在處理的記錄時,保持狀態很有用。
例如,工作處理機會記錄。執行 可以定義一個方法來匯總已處理的交易總數。
Database.Stateful 如果未指定,則所有靜態成員變量和實例成員變量都將還原為其原始值。
第一種情況:Database.Stateful 未指定
上面加上
private Integer AUB_Count = 0;
global void execute(Database.BatchableContext BC, List<sObject> scope) {
AUB_Count += scope.size();
system.debug(『AUB_Count = 『 + AUB_Count);
}
打開 Debug logs,新建 User Trace Flags,
然後在執行Apex Batch,
先看一下 環境中有多少個 Account記錄,
執行Batch後,
AccountUpdateBatch batch = new AccountUpdateBatch();
database.executeBatch(batch,40);
看 AUB_Count 處理記錄數量
總共100條,第一次 40,第二次 40,第三次 20,不會加上之前的。
第二種情況:Database.Stateful 指定
global class AccountUpdateBatch implements Database.batchable<sObject>, Database.stateful{}
其他一樣,
執行Batch後,一樣的Batch Size=40,
總共100條,第一次 40,第二次 80,第三次 100,會加上之前的。
Apex Scheduler
上面是手動執行批處理,現在用Apex Scheduler可以在特定的時間執行Apex Batch。
實現Schedulable接口
Apex Scheduler語法
global class scheduledBatchable implements Schedulable {
global void execute(SchedulableContext sc) {
batchable b = new batchable();
database.executebatch(b);
}
}
scheduledBatchable reminder = new scheduledBatchable ();
// Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
String sch = 』17 30 00 1 9 ? 2020′;
String jobID = System.schedule(『Owners』, sch, reminder);
對上面的Batch操作。
global class AccountScheduled implements Schedulable {
global void execute(SchedulableContext sc) {
AccountUpdateBatch aub = new AccountUpdateBatch();
database.executebatch(aub);
}
}
AccountScheduled accsch = new AccountScheduled();
String sch = '00 31 16 1 9 ? 2020'; //表示 2020年9月1日,16:31:00
String jobID = system.schedule('Account Job1', sch, accsch);
1,通過匿名窗口執行
Apex Jobs
Scheduled Jobs
2,通過Schedule Apex執行。
設置為每周二的下午五點執行。
為了測試我設置為下午四點看效果。
Apex Jobs
Scheduled Jobs
這次只是簡單的空更新Batch,更複雜的業務邏輯,都可以根據需要更改。
正常執行了,有問題或者建議可以評論區留言。
參考下面的連結。
Use Batch Apex Thrilhead
https://trailhead.salesforce.com/en/content/learn/modules/asynchronous_apex/async_apex_batch
Using Batch Apex
https://developer.salesforce.com/docs/atlas.en-us.226.0.apexcode.meta/apexcode/apex_batch_interface.htm
Schedule Jobs Using the Apex Scheduler
https://trailhead.salesforce.com/en/content/learn/modules/asynchronous_apex/async_apex_scheduled
Apex Scheduler
https://developer.salesforce.com/docs/atlas.en-us.224.0.apexcode.meta/apexcode/apex_scheduler.htm
我在故我思,我思故我在。