salesforce零基礎學習(一百零二)Limitation篇之 CPU Limit


本篇參考:

https://help.salesforce.com/articleView?id=000339361&type=1&mode=1

https://developer.salesforce.com/wiki/apex_code_best_practices

https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_limits.htm

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_transaction.htm

背景

還記得前幾年剛開始接觸sf的時候,對標准的功能一點都不懂,因為從java轉過來,側重點大部分在開發上面。所以連Account那些基本表都不清楚,sales cloud等更沒有概念。好在那時候經常看apex開發文檔,所以開發入手特別快。
轉眼都已經做sf 5年多了,回首一下以前的博客,大部分都是某個特定case的實現方式,一些新知識的探索,但是一直沒有涉足過apex government limitation的,這些在最開始的開發時很多概念很模糊,很不懂,所以未來幾篇側重點在limitation的介紹上,以便新人可以更好的理解這些,老人也重(同樣)溫(惡補)一下。最開始做sf classic的開發時,工作多年的大拿很少沒有不處理過 cpu limit / heap size limit等等各種各樣的問題,本篇先以CPU limitation開始,后續其他的主要的爭取都簡單介紹,溫故而知新,保證開發動手以前可以先多多的思考。
話不多說,今天主要講兩個內容。 Transcation & CPU Limitation

一. Transcation

我們經常會聽到前輩們給新人講salesforce相關的 limitation。一個transcation中SOQL查詢回來的數量最多50000條啊,DML最多10000條啊等等。新人肯定很努力的記住相關的關鍵字, SOQL 搜索50000,DML 10000。 且慢,還有一個關鍵點,transcation是什么?作為新人真的理解嗎?

我們嚴格的說 transcation的時候,前面都會加 apex transcation,即用apex寫代碼的時候,才涉及到transcation的概念。比如某些公司前后端分離,你做純粹的 aura / lwc前端,不需要考慮后端的小伙伴,肯定會想, transcation?excuse me?

是的,transcation的概念只有在apex上下文的情況下才會有這個概念,下文中出現的【transcation】和【事務】是同一個東西,在這里進行說明一下。transcation是什么先賣個關子,先說一下他具有什么特性呢?
transcation有一個主要的特性:transcation中的所有DML操作要么成功完成,要么在一個操作中發生錯誤,整個事務被回滾,沒有數據提交到數據庫,當然這種處理我們通常使用 Database.savePoint以及rollback去處理代碼邏輯。
既然大前提是apex上下文,所以我們思考一下,我們平時寫apex的代碼都會有哪些場景?
trigger / apex class / 匿名塊 / vf page調用 / web service,如果不全歡迎補充,所有上述的這些可以理解成 transcation的邊界,即事務的邊界,我們在事務邊界內發生的所有操作都表示單個操作單元。
這個時候引出一下官方對transcation的定義:表示作為單個單元執行的一組操作。即上述事務邊界執行的所有的操作。

所以我們思考一個場景,我們一個匿名塊里面調用了一個類的靜態方法,這個靜態方法做了一個表的DML操作,這個表同時還有 validation rule / trigger 巴拉巴拉很多操作。當調用了這個方法,執行了DML操作,這個數據最終 commit並且這個靜態方法完全執行完,然后最終這個匿名塊的所有的邏輯全執行完才算做當前的一個事務結束,這樣是否會好點理解呢?

二. CPU Limitation

一個transcation情況下,同步場景10s,異步場景60s。限制是死的不用太糾結,我們只需要知道,哪些會被計入CPU limitation,哪些不會被計入即可。

會被記入的有以下情況:

  • 所有的apex代碼
  • apex公開的所有的資源庫里面的函數
  • workflow的執行

不會被計入的有以下的情況:

  • 數據庫操作。比如花費在DML/SOQL/SOSL的時間就不會被計入進去
  • apex callout等待時間也不會被算進去

所以既然我們知道了哪些場景會被記入,哪些不會被記入,如果真涉及到CPU 調優的場景,盡可能的往以下的場景去優化。官方給了幾個場景的sample:

1. Using Map based query:這種場景用於當我們搜索 list出來以后,還需要獲取相關的ID作為列表去進行后續操作,官方建議我們別對list for循環繼續操作了,通過map去接收,然后使用 keySet以及values去同時獲取到id和數據集合。等會還要對它進行引申,先看一下官方的代碼。

List<Account> lstacc=[Select Id,Name from Account limit 50000];
Set<Id> setIds=new Set<Id>();
for(Account a:lstacc){ //More CPU time for sure due to looping
setIds.add(a.id);
}

//Using Map query saves CPU time

//Fetching all account in map
Map<id,account> aMap = new Map<id,account>([Select Id,Name from Account limit 50000]);

//Creating list of accounts
List<account> accList = aMap.values() ;

//Creating set of ids

Set<id> accIds = aMap.keySet() ;

2. 如果業務允許的情況下去異步處理,因為異步的CPU limit是60s,時間更充裕。比如部分代碼放在 @future里面。但是放在異步的沒法保證實時性以及回滾等操作,需要具體業務具體分析,別盲目選擇。

3. 業務允許探索一下SOQL聚合的用法,這個很好理解,因為SOQL查詢時間不計算在CPU limitation里面。salesforce提供了一些聚合函數等,比如我們場景需要這些,我們可以直接通過SOQL進行聚合,而不是搜索出來以后列表進行處理。

4. 盡量減少不必要的loop操作,如果不可避免,保證數據最少原則,只對需要的數據列表進行操作,從而減少迭代的量,減少CPU使用時間。

看完以后誠惶誠恐的感覺有沒有,恨不得想知道我們現有的代碼CPU時間用了多少,還有多少時間限制??? apex提供了 Limits這個類來捕捉大部分的government limitation的限制數。比如我們可以通過Limits.getCpuTime()去獲取當前時段已經用了多少CPU時間,以ms來計算。
當然,官方推薦的肯定優秀,不代表我們就一定適合當前的場景去進行優化。下面舉個例子,希望小伙伴看完擁有自己的思考。我們針對第一個的demo做一下debug,分別打印出來代碼執行的CPU limit 以及 heap size limit

第一個代碼塊

List<Account> lstacc=[Select Id,Name from Account limit 50000];
Set<Id> setIds=new Set<Id>();
for(Account a:lstacc){ //More CPU time for sure due to looping
setIds.add(a.id);
}
system.debug('cpu limit' + Limits.getCpuTime());
system.debug('heap size:' + Limits.getHeapSize());

第二個代碼塊

//Fetching all account in map
Map<id,account> aMap = new Map<id,account>([Select Id,Name from Account limit 50000]);

//Creating list of accounts
List<account> accList = aMap.values() ;

//Creating set of ids

Set<id> accIds = aMap.keySet() ;
system.debug('cpu limit' + Limits.getCpuTime());
system.debug('heap size:' + Limits.getHeapSize());

執行以后發現了什么???

第一個代碼塊的CPU時間確實比第二個高,但是相對應的heap size卻小一點。

 第二個代碼塊盡管CPU時間節省了下來,但是因為聲明了 map變量, heap size相應的變多了。

 當你在CPU慢慢降下來偷偷竊喜時,也要關注其他的點,因為他們可能在你不注意的時候慢慢的長高了。

salesforce針對apex有好幾個government limitation,我們在寫代碼的時候要從多個角度考慮,好多的點可能是互斥的,我們需要權衡好我們現在要在意什么,可以舍棄什么。空間換時間?時間換空間?沒有最好的統一的解決方案,只有最適合你的當前業務場景的某個transcation代碼。

總結:篇中根據最上面提供的官方文檔進行一下簡單的CPU limitation的描述。篇中有錯誤歡迎指出,有不懂歡迎留言。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM