本篇參考:
https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B4%A2%E5%BC%95/8751686?fr=aladdin
https://help.salesforce.com/articleView?id=000325257&type=1&mode=1
https://help.salesforce.com/articleView?id=000334796&type=1&mode=1
我們在做專案得時候,通常會有需求是根據很多入力條件進行SOQL查詢,然後展示 List。好多程式最開始跑的是沒有問題得,當資料達到一定資料量比如百萬級別以後,可能特別慢,或者更不好的情況下,直接崩潰了。針對這種情況有很多種可能情況導致,其中最常見的一種情況是:你當前的SOQL 語句不是selective的,或者是selective的情況下沒有達到最大的優化。那什麼樣的SOQL語句是selective的,有什麼定義或者特點去區分,如何去更好的優化SOQL呢?接下來的內容就拋磚引玉,引出相關的話題。
一. selective的SOQL語句
我們想確定一個SOQL是否為selective的,當前SOQL應該具有以下的特徵:
1. where後面的filter的欄位應該最少有一個索引欄位(欄位應該是 indexed的)。索引欄位的概念我們後面會單獨作為一個部分來講;
2. 如果filter的欄位包含了索引欄位,我們將確定一下當前的SOQL返回了多少條資料。針對返回的資料的條數,我們需要看當前的索引欄位是標準的索引還是自定義索引。對於標準索引,閾值是第一個百萬目標記錄的30%,以及第一個百萬目標記錄之後所有記錄的15%。此外,標準索引的選擇性閾值最大為100萬條總目標記錄,只有在總記錄數超過560萬條時才能達到。對於自定義索引,選擇性閾值為第一個百萬目標記錄的10%,以及第一個百萬目標記錄之後所有記錄的5%。此外,自定義索引的,只有在這個表記錄數超過5,6百萬條的情況下,選擇性閾值最大為333333條目標記錄被認為是selective的。
(注:閾值我們可以理解成臨界值,即當前的SOQL語句在當前系統通過當前 filter能查詢出來的最大值)
舉個例子。我們搜尋一個自定義表,目前資料量有30萬條,因為他是100萬條以內,所以如果使用了標準的索引,閾值 = 300000 * 30% = 90000條,也就是說當查詢的SQL返回的資料如果使用標準索引只要返回的數量在90000條以內,就代表當前的SOQL是selective的。針對自定義要求是10% * 300000 = 30000條,即返回資料在這個以內代表當前的資料是selective的。
所以一言以蔽之,selective的SOQL的語句具備的特性有兩個: 1. filter包含 索引欄位;2.查詢出來的資料滿足當前要求的閾值。只有當前的SOQL是selective的情況下,我們才可以使用工具去進行優化。什麼工具呢?看下面。
二. Query Plan Tool
概念和使用暫且不提,先看一下Query Plan Tool如何啟用以及在哪裡。我們開啟 develop console,點選menu部分的help,選擇 Preferences,然後彈出的地方我們便可以看到針對 Enable Query Plan的設定,預設就是true代表已經啟用,這樣我們在下面的 Query Editor中輸入相關的SOQL以後,便可以使用 Query Plan Tool來了解官方對當前的SOQL的建議了。
使用Query Plan Tool用於SOQL執行緩慢的檢測以及優化建議,所以不是所有的場景都需要了解他,當你的資料量特別大,當前SOQL執行特別緩慢,使用它。否則瞭解這個概念和工具就好。
我們先寫一個SQL看一下效果。下圖為使用 Query Plan的效果圖。包含兩個大部分,上面的列表(Plan List)以及下面的Notes部分。
我們看到每個Plan裡面都會包括 Cardinality / Fields / Leading Operation Type / Cost / sObject Cardinality / sObject Type。這些列什麼含義,如何去理解?
- Cardinality(基數):使用 Leading Operation Type操作方式情況下,預估的返回的資料條數;
- Fields:查詢優化器(Query Optimizer)中使用的索引欄位。如果 Leading Operation Type是 索引的,則當前的列將會展示索引欄位,如果是全表掃描的模式,則當前的這個列將展示空;
- Leading Operation Type:Salesforce將用於優化查詢的主要操作型別。這裡有4個值:
- Index:當前查詢的物件使用索引進行查詢;
- Sharing:當前的查詢將會使用索引進行查詢。當前的索引基於當前執行SQL的人的共享規則來決定的。如果有 sharing rule限制了user可以訪問的記錄情況下,salesforce可以根據這些共享規則去進行優化;
- TableScan:當前的查詢方式為查詢當前表的所有資料;
- Other:salesforce將使用內部的優化方式去查詢。
- Cost:與Force.com查詢優化器的選擇性閾值相比,查詢的成本。 如果這個值大於1表示查詢不會是selective的。
- sObject Cardinality:查詢當前物件大概的記錄數;
- sObject Type:當前查詢表的 object的名字。
以上的就是關於查詢的Plan表的各個列的名詞解釋。下圖附上一張 Cost超過1的情況,因為查詢的 filter沒有索引欄位,所以查詢非 selective,cost超過了1.
我們通過Notes等資訊以及上面的表格便可以檢視到對SOQL進行優化建議。細節得 Query Plan Tool介紹我們可以檢視上方得連結中官方描述得文件。上面我們提到了 selective的SOQL必須是包含索引欄位,那麼在salesforce的世界裡面哪些是索引欄位,怎麼設定索引欄位呢???
三. Index(索引)
索引這個概念不止針對salesforce的SOQL,其他的類似SQL server以及 Oracle都有索引的概念,查詢的filter中通過索引欄位可以加快查詢的速度。具體的索引的含義也可以檢視上面的百度百科的文件。Salesforce針對索引欄位有標準和自定義兩種。我們如何知道當前哪些欄位是索引欄位呢?只需要進入field中,檢視Indexed這列資訊即可,下圖展示Account表中的一些索引欄位的截圖。
1. 標準索引欄位
salesforce針對幾乎所有的表的以下欄位維護了索引。分別是:RecordTypeId 、 Division、 CreatedDate、Systemmodstamp (LastModifiedDate)、Name、Email (for contacts and leads)、Foreign key relationships (lookups and master-detail)、Salesforce記錄得 Record Id。也就是說表中的這些的欄位,salesforce大部分已經自行維護了索引欄位用來優化查詢,無需在進行設定索引。
2. 自定義索引欄位
當然,一個專案不可能只使用標準欄位,我們還是需要建立自定義欄位去實現相關得自定義邏輯。針對自定義欄位同樣可以設定成索引欄位。當然不是所有得型別都可以設定索引欄位,以下得型別salesforce不支援設定索引欄位:multi-select picklists / text area (long) / text area (rich) / non-deterministic formula fields / encrypted text。編輯欄位以後,勾選external Id外來鍵以後,便成了被標記成索引得欄位。外來鍵僅可以Auto Number / Email / Number / Text型別中建立。當然,凡事不是那麼絕對,如果需要在其他得欄位型別中建立自定義得索引欄位,包括標準欄位,可以聯絡salesforce得support人員,他們可以進行設定。
上面有一個描述是non-deterministic formula fields不支援建立索引欄位得,並不是代表formula不支援索引,只是部分情況不支援。上方得index文件中有具體描述,感興趣自行檢視。
這裡擴充兩個對大量資料的SOQL比較災難的兩個filter,又常常是我們經常用到的。一個是使用 formula欄位進行 filter,一個是使用 null 進行filter。怎麼樣,專案上使用的是不是很常見?資料量少的時候OK,當真正資料量達到一定程度,你會發現這兩種都是災難性的。因為這兩個預設的都是不帶索引的!!!如果專案中遇到了這兩種使用在filter中,並且資料量很龐大,找salesforce提support設定索引,salesforce可以針對 null單獨設定索引。比如我們針對某個自定義欄位 XX__c設定了 index,我們的SOQL :
select Id,Name from Account where XX__c = null
即使XX__c是索引欄位也不行,需要額外的聯絡salesforce,將這個欄位設定顯示的 index用來支援null索引。
總結:當我們執行得SOQL隨著資料量增加而變緩慢或者超時等錯誤情況下,我們可以使用 Query Plan Tool去檢視是否有優化得解決方案。瞭解哪些型別可以進行索引設定,掌握哪些條件可以滿足一個SOQL是 selective。針對上面得各個點講的都很淺,感興趣得檢視上方提供得各個官方得文件以便更深入學習。篇中有錯誤歡迎指出,有不懂歡迎留言。