盡可能提高查詢效能

如要排解查詢速度緩慢的問題,請使用「查詢說明」取得查詢執行計畫和執行階段執行設定檔。以下各節說明如何根據執行設定檔,採取適當步驟來提升查詢效能:

限制結果數量

使用執行樹狀結構中的「傳回的記錄」欄位,判斷查詢是否傳回大量文件。建議使用 limit(...) 階段,限制傳回的文件數量。這樣一來,透過網路傳回用戶端時,結果的序列化位元組大小就會減少。如果 Limit 節點前面有 MajorSort 節點,查詢引擎可以合併 LimitMajorSort 節點,並以 TopN 排序取代完整的記憶體內具體化和排序,進而減少查詢的記憶體需求。

限制結果文件大小

建議使用 select(...) 只傳回必要欄位,或使用 remove_fields(...) 捨棄過大的欄位,藉此限制傳回的文件大小。這有助於減少處理中繼結果的運算和記憶體成本,以及透過網路傳回用戶端時,結果的序列化位元組大小。如果查詢中參照的所有欄位都涵蓋在一般索引中,查詢也可以完全涵蓋在索引掃描中,避免從主要儲存空間擷取文件。

使用索引

請按照下列操作說明設定及最佳化索引。

判斷查詢是否使用索引

如要判斷查詢是否使用索引,請檢查執行樹狀結構中的葉節點。如果執行樹狀結構的葉節點是TableScan 節點,表示查詢未使用索引,而是掃描主要儲存空間中的文件。如果使用索引,執行樹狀結構的葉節點會顯示索引的索引 ID 和索引欄位。

找出更合適的索引

如果索引可減少查詢引擎需要從主要儲存空間擷取的檔案數量,或其欄位排序可滿足查詢的排序需求,則索引對查詢很有用。

如果查詢使用索引,但查詢引擎仍會擷取並捨棄大量文件 (如 Scan 節點傳回大量記錄,接著 Filter 節點傳回少量記錄),這表示使用索引滿足的查詢述詞不具選擇性。如要建立更合適的索引,請參閱「建立索引」。

如果查詢使用索引,但查詢引擎仍在記憶體中重新排序結果集 (如查詢執行樹狀結構中的 MajorSort 節點所示),表示所用索引無法滿足查詢的排序需求。如要建立更合適的索引,請參閱下一節。

建立索引

請參閱索引管理說明文件,瞭解如何建立索引。為確保查詢可以使用索引,請依下列順序建立一般 (而非 Multikey) 索引和欄位:

  1. 所有將用於等號運算子的欄位。 如要盡量在查詢中重複使用欄位,請依據查詢中等號運算子內欄位的出現次數,以遞減順序排序欄位。
  2. 所有要排序的欄位 (順序相同)。
  3. 將用於範圍或不相等運算子的欄位,依查詢限制選擇性遞減排序。
  4. 將做為索引查詢一部分傳回的欄位:在索引中加入這類欄位,可讓索引涵蓋查詢內容,避免必須從主要儲存空間擷取文件。

強制執行索引或資料表掃描

查詢 Firestore 原生模式時,系統會自動使用可能有助提高查詢效率的任何索引。因此,您不需要為查詢指定索引。不過,如果查詢對工作負載至關重要,建議您使用 forceIndex 選項,以獲得更穩定的效能。

在少數情況下,原生模式的 Firestore 可能會選擇造成查詢延遲增加的索引。如果您按照效能迴歸問題適用的疑難排解步驟操作,並確認嘗試使用不同索引來執行查詢是合理的做法,可以使用 forceIndex 選項指定索引。

您可以在管道作業的任何輸入階段使用 forceIndex 選項,覆寫 Native Mode 中 Firestore 的預設查詢計畫,並指定要使用的索引,或強制執行資料表掃描。

強制使用特定索引

如要強制查詢使用特定索引,請將索引 ID 以字串形式提供給 forceIndex 選項。您可以從控制台或錯誤訊息中找到索引 ID。

以下範例會強制規劃工具使用 ID 為 CICAgOi36pgK 的索引:

// Force Planner to use Index ID CICAgOi36pgK
db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "CICAgOi36pgK" })
  .limit(100)

以下列舉幾項強制使用特定索引的用途:

  • 測試不同索引的成效。
  • 確保查詢使用特定已知最佳索引。
  • 如果最佳化工具的預設選擇不適合特定查詢,您可以覆寫最佳化工具。

如果找不到指定的索引,查詢就會失敗。

強制掃描資料表

資料表掃描會讀取集合或產品素材資源集合群組中的文件,但不會使用任何次要索引。如要強制執行資料表掃描,請將 forceIndex 設為 primary

以下範例會強制執行資料表掃描:

// Force Planner to only do a Full-Table Scan
db.pipeline()
  .collectionGroup({ collectionId: "customers", forceIndex: "primary" })
  .limit(100)

在下列情況下,您可能會使用資料表掃描:

  • 適用於索引負擔不合理的極小集合。
  • 查詢會存取集合中的大部分文件。
  • 用於偵錯和比較效能。

搭配「查詢說明」使用 forceIndex

您可以使用「查詢說明」,特別是搭配 analyze 選項,觀察 forceIndex 的效果:

  • 檢查執行樹狀結構的葉節點,確認 Firestore (原生模式) 在 forceIndex 中使用指定的索引 ID。
  • 確認使用 forceIndex: "primary" 時,計畫中會顯示 TableScan 節點。
  • 比較啟用和未啟用 forceIndex 時的延遲時間、掃描的文件數和掃描的索引項目數等成效指標,進一步調整查詢效能。

forceIndex最佳做法

雖然 forceIndex 可提供更多查詢執行控制權,但對於大多數用途而言,原生模式的 Firestore 查詢最佳化工具通常效率很高。使用 forceIndex 時,請考慮下列最佳做法:

  • 請謹慎使用 forceIndex。如果您發現預設查詢計畫的效能不彰,請先使用「查詢說明」診斷問題,再強制使用索引。
  • 使用 forceIndex 時,請務必以實際資料量測試查詢,瞭解查詢的效能和費用特性。
  • 請勿在正式環境中對大型集合使用 forceIndex: "primary"