Cloud Firestore 的最佳做法

建構使用 Cloud Firestore 的應用程式時,您可以快速參考本文列出的最佳做法,

資料庫位置

建立資料庫執行個體時,請選取離使用者與運算資源最近的資料庫位置。遠離的網路躍點較容易出錯,且查詢延遲時間會增加。

為了盡可能提高應用程式的可用性和耐用性,請選取「多地區位置」,並將重要的運算資源至少放在兩個地區。

若應用程式容易受到延遲時間影響,或與其他 GCP 資源共置,請選取費用較低的單一地區位置

文件 ID

  • 避免使用文件 ID ...
  • 避免在文件 ID 中使用 / 正斜線。
  • 請勿使用單調遞增的文件 ID,例如:

    • Customer1Customer2Customer3...
    • Product 1Product 2Product 3...

    這種依序 ID 可能會導致熱點影響延遲時間。

欄位名稱

  • 請避免在欄位名稱中使用下列字元,因為這類字元需要額外的逸出:

    • . 段期間
    • [左括弧
    • ]右括弧
    • * 個星號
    • ` 個倒引號

索引

縮短寫入延遲時間

寫入延遲的主要貢獻者是索引擴散器。減少索引擴散的最佳做法如下:

  • 設定集合層級索引豁免。最簡單的預設設定是停用「遞減」和「陣列」索引功能。移除未使用的已建立索引值,也會降低儲存空間費用

  • 減少交易中的文件數量。如要編寫大量文件,建議您使用大量寫入器,不要使用不可分割的批次寫入器。

索引豁免情況

大多數應用程式都可以仰賴自動索引和錯誤訊息連結來管理索引。但在下列情況下,您可能會想要新增單一欄位豁免

案件 說明
大型字串欄位

如果有字串欄位經常包含不用於查詢的長字串值,則可將該欄位排除在索引範圍之外,藉此節省儲存空間費用。

集合寫入具有序列值的文件的寫入速度偏高

如果您建立索引的欄位會在集合中的文件之間依序增加或減少 (例如時間戳記),則集合的最大寫入速率為每秒 500 次。如果您不根據含有序列值的欄位執行查詢,可以將該欄位排除在索引之外,略過這項限制。

在寫入速率較高的 IoT 用途中,例如,含有時間戳記欄位的文件集合,可能達到每秒 500 次寫入的上限。

存留時間欄位

請注意,如果您使用存留時間 (存留時間) 政策,則「TTL」欄位必須為時間戳記。存留時間欄位的索引功能預設為啟用,可能會在流量費率提高的情況下影響效能。最佳做法是為存留時間欄位新增單一欄位豁免項目。

大型陣列或對應欄位

大型陣列或對應欄位可能會達到每份文件 40,000 個索引項目的上限。如果您不是根據大型陣列或對應欄位進行查詢,請讓索引不必進行索引。

讀取和寫入作業

  • 應用程式可更新單一文件的確切頻率上限,會因工作負載而異。詳情請參閱「單一文件更新」。

  • 盡可能以非同步呼叫取代同步呼叫。非同步呼叫能將延遲時間影響降到最低。舉例來說,假設應用程式需要文件查詢的結果和查詢結果才能轉譯回應。如果查詢和查詢沒有資料依附元件,就不需要同步等到查詢完成再開始查詢。

  • 不可使用位移,請改用遊標。使用偏移只能避免將略過的文件傳回應用程式,但這些文件仍會在內部擷取。略過的文件會影響查詢的延遲時間,而且您的應用程式必須支付擷取這些文件所需的讀取作業費用。

重試交易

Cloud Firestore SDK 和用戶端程式庫會自動重試失敗的交易,處理暫時性錯誤。如果您的應用程式是透過 RESTRPC 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 安全性規則