建構使用 Cloud Firestore 的應用程式時,您可以快速參考本文列出的最佳做法,
資料庫位置
建立資料庫執行個體時,請選取離使用者與運算資源最近的資料庫位置。遠離的網路躍點較容易出錯,且查詢延遲時間會增加。
為了盡可能提高應用程式的可用性和耐用性,請選取「多地區位置」,並將重要的運算資源至少放在兩個地區。
若應用程式容易受到延遲時間影響,或與其他 GCP 資源共置,請選取費用較低的單一地區位置。
文件 ID
- 避免使用文件 ID
.
和..
。 - 避免在文件 ID 中使用
/
正斜線。 請勿使用單調遞增的文件 ID,例如:
Customer1
、Customer2
、Customer3
...Product 1
、Product 2
、Product 3
...
這種依序 ID 可能會導致熱點影響延遲時間。
欄位名稱
請避免在欄位名稱中使用下列字元,因為這類字元需要額外的逸出:
.
段期間[
左括弧]
右括弧*
個星號`
個倒引號
索引
縮短寫入延遲時間
寫入延遲的主要貢獻者是索引擴散器。減少索引擴散的最佳做法如下:
設定集合層級索引豁免。最簡單的預設設定是停用「遞減」和「陣列」索引功能。移除未使用的已建立索引值,也會降低儲存空間費用。
減少交易中的文件數量。如要編寫大量文件,建議您使用大量寫入器,不要使用不可分割的批次寫入器。
索引豁免情況
大多數應用程式都可以仰賴自動索引和錯誤訊息連結來管理索引。但在下列情況下,您可能會想要新增單一欄位豁免:
案件 | 說明 |
---|---|
大型字串欄位 | 如果有字串欄位經常包含不用於查詢的長字串值,則可將該欄位排除在索引範圍之外,藉此節省儲存空間費用。 |
集合寫入具有序列值的文件的寫入速度偏高 | 如果您建立索引的欄位會在集合中的文件之間依序增加或減少 (例如時間戳記),則集合的最大寫入速率為每秒 500 次。如果您不根據含有序列值的欄位執行查詢,可以將該欄位排除在索引之外,略過這項限制。 在寫入速率較高的 IoT 用途中,例如,含有時間戳記欄位的文件集合,可能達到每秒 500 次寫入的上限。 |
存留時間欄位 |
請注意,如果您使用存留時間 (存留時間) 政策,則「TTL」欄位必須為時間戳記。存留時間欄位的索引功能預設為啟用,可能會在流量費率提高的情況下影響效能。最佳做法是為存留時間欄位新增單一欄位豁免項目。 |
大型陣列或對應欄位 | 大型陣列或對應欄位可能會達到每份文件 40,000 個索引項目的上限。如果您不是根據大型陣列或對應欄位進行查詢,請讓索引不必進行索引。 |
讀取和寫入作業
應用程式可更新單一文件的確切頻率上限,會因工作負載而異。詳情請參閱「單一文件更新」。
盡可能以非同步呼叫取代同步呼叫。非同步呼叫能將延遲時間影響降到最低。舉例來說,假設應用程式需要文件查詢的結果和查詢結果才能轉譯回應。如果查詢和查詢沒有資料依附元件,就不需要同步等到查詢完成再開始查詢。
不可使用位移,請改用遊標。使用偏移只能避免將略過的文件傳回應用程式,但這些文件仍會在內部擷取。略過的文件會影響查詢的延遲時間,而且您的應用程式必須支付擷取這些文件所需的讀取作業費用。
重試交易
Cloud Firestore SDK 和用戶端程式庫會自動重試失敗的交易,處理暫時性錯誤。如果您的應用程式是透過 REST 或 RPC API (而非透過 SDK) 存取 Cloud Firestore,應用程式應實作交易重試功能以提高可靠性。
即時更新
如要瞭解與即時更新相關的最佳做法,請參閱「大規模瞭解即時查詢」。
資源調度設計
下列最佳做法說明如何避免產生爭用問題的情況。
更新單一文件
設計應用程式時,請考慮應用程式更新單一文件的速度。評估工作負載效能的最佳方式是執行負載測試。應用程式可更新單一文件的確切頻率上限,會因工作負載而有很大的差異。因素包括寫入率、要求之間的爭用情況,以及受影響的索引數量。
文件寫入作業會更新文件和任何相關聯的索引,而 Cloud Firestore 會同步套用多個備用資源的寫入作業。如果寫入速率夠高,資料庫就會開始發生爭用情況、延遲時間過長或其他錯誤。
讀取、寫入和刪除頻率小,文件範圍有限
請避免高速讀取或寫入字母順序接近的文件,否則應用程式會發生爭用錯誤。此問題稱為資源使用率不均,如果您的應用程式執行以下任一操作,就可能會發生此問題:
以高速率建立新文件,並自行分配單調增加的 ID。
Cloud Firestore 使用散佈演算法分配文件 ID。如果您使用自動文件 ID 建立新文件,則應該不會在寫入時遇到資源使用率不均的問題。
以少量文件集大量建立新文件。
以極高的速度,建立具有單調遞增欄位 (如時間戳記) 的新文件。
以高速刪除集合中的文件。
能以極高的速度寫入資料庫 但不會逐漸增加流量
避免略過已刪除的資料
避免使用略過最近刪除資料的查詢。如果近期查詢結果近期遭到刪除,查詢就可能需要略過大量索引項目。
其中一個工作負載可能會需要略過大量刪除的資料,例如嘗試找出最舊佇列中的工作項目。查詢看起來可能會像這樣:
docs = db.collection('WorkItems').order_by('created').limit(100)
delete_batch = db.batch()
for doc in docs.stream():
finish_work(doc)
delete_batch.delete(doc.reference)
delete_batch.commit()
每次執行這項查詢時,系統都會掃描任何最近刪除文件中的 created
欄位索引項目。這會減緩查詢的速度。
為提升效能,請使用 start_at
方法找出最佳的起點。例如:
completed_items = db.collection('CompletionStats').document('all stats').get()
docs = db.collection('WorkItems').start_at(
{'created': completed_items.get('last_completed')}).order_by(
'created').limit(100)
delete_batch = db.batch()
last_completed = None
for doc in docs.stream():
finish_work(doc)
delete_batch.delete(doc.reference)
last_completed = doc.get('created')
if last_completed:
delete_batch.update(completed_items.reference,
{'last_completed': last_completed})
delete_batch.commit()
注意:上述範例使用單調增加的欄位,是高寫入速率的反模式。
增加流量
您應逐漸增加新集合或字母順序離散文件的流量,讓 Cloud Firestore 有足夠時間準備文件,以因應增加的流量。建議您從每秒最多 500 個作業開始到新的集合,接著每 5 分鐘增加 50% 的流量。您可以同樣提高寫入流量,但請注意 Cloud Firestore 標準限制。請確保作業在整個索引鍵範圍內均勻分佈。這就是「500/50/5」規則。
將流量遷移至新的集合
如果將應用程式流量從一個集合遷移至另一個集合,逐步提高效能就特別重要。處理這項遷移作業的簡易方法是讀取舊集合,如果文件不存在,再從新的集合讀取資料。不過,這可能會導致流量突然增加,並導致新集合中的字典關閉文件。Cloud Firestore 可能無法有效率地為流量增加的新集合做好準備,尤其是當流量不足時。
如果您對同一個集合中的多份文件變更文件 ID,也可能會發生類似問題。
將流量遷移至新集合的最佳策略取決於您的資料模型。下列策略範例稱為「平行讀取」。您必須判斷這項策略是否適用於您的資料,而在遷移期間,平行作業對成本的影響至關重要。
平行讀取
如要在將流量遷移至新集合時實作平行讀取,請先從舊集合讀取資料。如果文件遺失,請從新的集合讀取資料。大量讀取不存在的文件可能會導致資源使用率不均,因此請務必逐步增加新集合的負載。更好的策略是將舊文件複製到新集合,然後刪除舊文件。逐步調高平行讀取,以確保 Cloud Firestore 能夠處理傳送至新集合的流量。
如要逐漸增加新集合的讀取或寫入量,可使用確定性的使用者 ID 雜湊,隨機選取嘗試寫入新文件的使用者百分比。請確保 User ID 雜湊的結果不會遭到函式或使用者行為扭曲。
同時,請執行批次工作,將舊文件的所有資料複製到新集合。批次工作應避免寫入連續的文件 ID,以免資源使用率不均。批次工作完成後,您只能從新的集合讀取資料。
這個策略的變革是一次只遷移一批使用者。 在使用者文件中新增欄位,用於追蹤該使用者的遷移狀態。 根據使用者 ID 的雜湊值選取一批要遷移的使用者。請使用批次工作來遷移該批次使用者的文件,並在遷移期間對使用者使用平行讀取功能。
請注意,除非您在遷移階段同時寫入新舊實體,否則無法輕鬆復原。這會增加 Cloud Firestore 產生的費用。
隱私權
- 避免將機密資訊儲存在 Cloud 專案 ID 中。Cloud 專案 ID 可能會在專案的生命週期結束後保留下來。
- 為遵循資料法規遵循的最佳做法,建議您不要將機密資訊儲存在文件名稱和文件欄位名稱中。
防範未經授權的存取行為
運用 Cloud Firestore 安全性規則,避免資料庫發生未經授權的作業。例如,使用規則可避免惡意使用者重複下載整個資料庫。
進一步瞭解如何使用 Cloud Firestore 安全性規則。