請快速參考本文列出的最佳做法 以建構使用 Cloud Firestore 的應用程式
資料庫位置
建立資料庫執行個體時,請選取最靠近使用者和運算資源的資料庫位置。網路跳躍範圍越廣,發生錯誤的機率就越高,查詢延遲時間也會增加。
為了讓 並選取多區域位置 請將重要的運算資源置於至少兩個區域
選取區域位置可降低成本,如果應用程式對延遲時間較為敏感,則可縮短寫入延遲時間,或是與其他 GCP 資源共置。
文件 ID
- 請避免使用文件 ID
.
和..
。 - 請勿在文件 ID 中使用
/
斜線。 請勿使用單調遞增的文件 ID,例如:
Customer1
、Customer2
、Customer3
...Product 1
、Product 2
、Product 3
、...
這種依序 ID 可能會導致熱點影響延遲時間。
欄位名稱
請避免在欄位名稱中使用以下字元,因為這些字元需要額外逸出:
.
期[
左括號]
右方括號*
個星號`
個倒引號
索引
減少寫入延遲時間
造成寫入延遲的主要原因是索引分支。減少索引分支的最佳做法如下:
組合 集合層級索引豁免設定。最簡單的預設設定是停用「遞減」與陣列索引。移除未使用的索引值也會降低儲存空間費用。
減少交易中的文件數量。寫大量時適用 不妨考慮使用大量撰寫工具,不要使用整體化的批次 。
索引豁免情況
對於大多數應用程式,您可以使用自動建立索引功能,以及任何錯誤訊息連結來管理索引。不過,我們建議您 單一欄位豁免項目 下列情況:
案件 | 說明 |
---|---|
大型字串欄位 | 如果您有一個字串欄位,經常儲存您不會用於查詢的長字串值,您可以將該欄位排除在索引之外,藉此節省儲存空間成本。 |
寫入含有序列值的集合速度過快 | 如果您為集合中的文件建立索引,以便在這些文件之間依序增加或減少某個欄位 (例如時間戳記),則集合的寫入頻率上限為每秒 500 次。如果您不根據含有序列值的欄位執行查詢,可以將該欄位豁免 藉此略過這項限制 舉例來說,在寫入頻率高的 IoT 用途中,包含有時間戳記欄位的文件集合可能會接近每秒 500 次寫入的限制。 |
存留時間欄位 |
如果使用存留時間 (存留時間) 政策,請留意存留時間 欄位必須為時間戳記。存留時間欄位的索引功能預設為啟用,且 可以在流量率提高的情況下對效能造成影響最佳做法是 保留存留時間欄位的單一欄位豁免情況。 |
大型陣列或對應欄位 | 大型陣列或對應欄位可能會接近每個文件 40,000 個索引項目的上限。如果您不是根據大型陣列或對應欄位進行查詢,請將該欄位排除在索引之外。 |
讀取和寫入作業
應用程式更新單一文件的確切最大速率,取決於工作負載。如需更多資訊 請參閱單一文件更新。
盡可能以非同步呼叫取代同步呼叫。 非同步呼叫可以盡可能降低延遲造成的衝擊。以需要文件查詢結果和查詢結果才能顯示回應的應用程式為例。若查詢和查詢沒有資料依附性, 不需要同步等待查詢完成 起始查詢。
不可使用位移,而是改用 遊標。僅使用偏移量可避免 將略過的文件傳回應用程式 仍會擷取到內部 IP 位址系統略過的文件會影響 而且應用程式就要收取讀取作業的費用 擷取。
交易重試
Cloud Firestore SDK 和用戶端 程式庫自動重試失敗 處理暫時性錯誤如果應用程式是透過 REST 或 RPC API 直接存取 Cloud Firestore,而非透過 SDK,則應實作交易重試功能,以提高可靠性。
即時更新
如需即時更新的最佳做法,請參閱 大規模瞭解即時查詢。
資源調度設計
以下最佳做法說明如何避免產生競爭問題的情況。
更新單一文件
設計應用程式時,請考慮應用程式更新單一文件的速度。 評估工作負載效能的最佳方式是執行負載 進行測試。應用程式可更新單一文件的確切頻率上限 會完全視工作負載而定這些因素包括寫入率、請求之間的爭用情形,以及受影響的索引數量。
文件寫入作業會更新文件和任何相關聯的索引, 和 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 費用。
隱私權
- 避免將機密資訊儲存在 Cloud 專案 ID 中。專案結束後,專案 ID 仍有可能保留下來。
- 為遵守資料法規,我們建議您不要在文件名稱和文件欄位名稱中儲存機密資訊。
防止未經授權的存取
使用 Cloud Firestore Security Rules 防止未經授權的資料庫作業。舉例來說,使用規則即可避免 惡意使用者重複下載整個資料庫。
進一步瞭解如何使用 Cloud Firestore Security Rules。