Cloud Firestore 的最佳做法

在建立使用 Cloud Firestore 的應用程式時,可以使用此處列出的最佳實踐作為快速參考。

資料庫位置

建立資料庫執行個體時,選擇最接近您的使用者和運算資源的資料庫位置。影響深遠的網路躍點更容易出錯並增加查詢延遲。

為了最大限度地提高應用程式的可用性和持久性,請選擇多區域位置並將關鍵運算資源放置在至少兩個區域中。

選擇區域位置以降低成本、降低寫入延遲(如果您的應用程式對延遲敏感)或與其他 GCP 資源共置

文件 ID

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

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

    此類連續 ID 可能會導致影響延遲的熱點

欄位名稱

  • 字段名稱中避免使用以下字符,因為它們需要額外的轉義:

    • .時期
    • [左括號
    • ]右括號
    • *星號
    • `反引號

索引

減少寫入延遲

寫入延遲的主要貢獻者是索引扇出。減少索引扇出的最佳實踐是:

  • 設定集合級索引豁免。一個簡單的預設設定是停用降序和陣列索引。刪除未使用的索引值也將降低儲存成本

  • 減少交易中的文檔數量。要寫入大量文檔,請考慮使用批量寫入器而不是原子批量寫入器。

指數豁免

對於大多數應用程序,您可以依靠自動索引以及任何錯誤訊息連結來管理索引。但是,在以下情況下您可能需要新增單一欄位豁免

案件描述
大字串字段

如果您有一個經常保存不用於查詢的長字串值的字串字段,則可以透過免除該字段的索引來降低儲存成本。

包含具有順序值的文件的集合的高寫入率

如果您將集合中的文件之間依序增加或減少的欄位(例如時間戳記)建立索引,則集合的最大寫入速率為每秒 500 次寫入。如果您不根據具有順序值的欄位進行查詢,則可以將該欄位免除索引以繞過此限制。

例如,在具有高寫入速率的 IoT 使用案例中,包含帶有時間戳欄位的文件的集合可能會接近每秒 500 次寫入的限制。

TTL字段

如果您使用TTL(生存時間)策略,請注意TTL欄位必須是時間戳記。預設啟用 TTL 欄位索引,並且可能會影響較高流量速率下的效能。作為最佳實踐,請為 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 的確定性雜湊來選擇嘗試寫入新文件的隨機百分比的使用者。確保使用者 ID 雜湊的結果不會因您的函數或使用者行為而產生偏差。

同時,執行批次作業,將所有資料從舊文件複製到新集合。您的批次作業應避免寫入連續的文件 ID,以防止熱點出現。批次作業完成後,您只能從新集合中讀取。

此策略的改進是一次遷移小批量的使用者。在使用者文件中新增一個字段,用於追蹤該使用者的遷移狀態。根據使用者 ID 的雜湊值選擇一批要遷移的使用者。使用批次作業來遷移該批次使用者的文檔,並在遷移過程中為使用者使用並行讀取。

請注意,除非在遷移階段對新舊實體進行雙重寫入,否則無法輕鬆回滾。這會增加 Cloud Firestore 所產生的成本。

隱私

  • 避免在雲端項目 ID 中儲存敏感資訊。雲端項目 ID 可能會在專案生命週期結束後保留。
  • 作為資料合規性最佳實踐,我們建議不要在文件名稱和文件欄位名稱中儲存敏感資訊。

防止未經授權的訪問

使用 Cloud Firestore 安全性規則防止對資料庫進行未經授權的操作。例如,使用規則可以避免惡意使用者重複下載整個資料庫的情況。

詳細了解如何使用 Cloud Firestore 安全性法則