您可以使用「查詢說明」功能,將 Cloud Firestore 查詢提交至後端,並換取後端查詢執行作業的詳細效能統計資料。其功能類似於許多關聯資料庫系統中的 EXPLAIN [ANALYZE]
作業。
您可以使用 Firestore 伺服器用戶端程式庫傳送查詢說明要求。
查詢說明結果有助於您瞭解查詢的執行方式,並顯示不良效率和可能的伺服器端瓶頸位置。
查詢說明:
- 提供查詢規劃階段的洞察資料,協助您調整查詢索引並提高效率。
- 使用「分析」選項,有助於您瞭解每項查詢的成本和效能,並快速重複執行不同的查詢模式,以便充分利用這些模式。
瞭解「查詢說明」選項:預設和分析
您可以使用「預設」或「分析」選項執行查詢說明作業。
使用預設選項時,查詢說明會規劃查詢,但會略過執行階段。這會傳回企劃書階段資訊。您可以使用這項功能檢查查詢是否含有必要的索引,並瞭解系統使用哪些索引。這有助於您驗證特定查詢是否使用複合式索引,而非在許多不同索引上進行交集。
使用分析選項時,查詢會同時說明計畫並執行查詢。這會傳回先前提到的所有企劃書資訊,以及查詢執行期間的統計資料。這會包含查詢的帳單資訊,以及查詢執行作業的系統層級洞察資料。您可以使用這項工具測試各種查詢和索引設定,以便將成本和延遲時間最佳化。
查詢說明的費用為何?
搭配預設選項使用「查詢說明」時,系統不會執行索引或讀取作業。無論查詢複雜度為何,系統都會收取一次讀取作業費用。
當您使用「查詢說明」搭配「分析」選項時,系統會執行索引和讀取作業,因此會照常向您收取查詢費用。分析活動不會產生額外費用,只會產生執行查詢的一般費用。
使用預設選項的查詢說明
您可以使用用戶端程式庫提交預設選項要求。
請注意,要求會透過 IAM 驗證,並使用一般查詢作業的相同權限。系統會忽略 Firebase Authentication 等其他驗證技術。如需更多資訊,請參閱用於伺服器用戶端程式庫的 IAM 指南。
Java (管理員)
Query q = db.collection("col").whereGreaterThan("a", 1);
ExplainOptions options = ExplainOptions.builder().build();
ExplainResults<QuerySnapshot> explainResults = q.explain(options).get();
ExplainMetrics metrics = explainResults.getMetrics();
PlanSummary planSummary = metrics.getPlanSummary();
節點 (管理員)
const q = db.collection('col').where('country', '=', 'USA');
const options = { analyze : 'false' };
const explainResults = await q.explain(options);
const metrics = explainResults.metrics;
const plan = metrics.planSummary;
回應的確切格式取決於執行環境。傳回的結果可轉換為 JSON。例如:
{ "indexes_used": [ {"query_scope": "Collection", "properties": "(category ASC, __name__ ASC)"}, {"query_scope": "Collection", "properties": "(country ASC, __name__ ASC)"}, ] }
詳情請參閱「查詢解釋報表參考資料」。
使用「查詢說明」與「分析」選項
您可以使用用戶端程式庫提交分析選項要求。
請注意,要求會透過 IAM 驗證,並使用一般查詢作業的相同權限。系統會忽略 Firebase Authentication 等其他驗證技術。如需更多資訊,請參閱用於伺服器用戶端程式庫的 IAM 指南。
Java (管理員)
Query q = db.collection("col").whereGreaterThan("a", 1);
ExplainOptions options = ExplainOptions.builder().setAnalyze(true).build();
ExplainResults<QuerySnapshot> explainResults = q.explain(options).get();
ExplainMetrics metrics = explainResults.getMetrics();
PlanSummary planSummary = metrics.getPlanSummary();
List<Map<String, Object>> indexesUsed = planSummary.getIndexesUsed();
ExecutionStats stats = metrics.getExecutionStats();
節點 (管理員)
const q = db.collection('col').where('country', '=', 'USA');
const options = { analyze : 'true' };
const explainResults = await q.explain(options);
const metrics = explainResults.metrics;
const plan = metrics.planSummary;
const indexesUsed = plan.indexesUsed;
const stats = metrics.executionStats;
以下範例顯示除了 planInfo
之外,還傳回 stats
物件。回應的確切格式取決於執行環境。範例回應為 JSON 格式。
{ "resultsReturned": "5", "executionDuration": "0.100718s", "readOperations": "5", "debugStats": { "index_entries_scanned": "95000", "documents_scanned": "5" "billing_details": { "documents_billable": "5", "index_entries_billable": "0", "small_ops": "0", "min_query_cost": "0", } } }
詳情請參閱「查詢解釋報表參考資料」。
解讀結果並調整
以下舉例說明,我們會根據電影類型和製作國家/地區查詢電影。
為說明這項功能,請假設您使用的是這個 SQL 查詢的對等項目。
SELECT * FROM /movies WHERE category = 'Romantic' AND country = 'USA';
如果我們使用分析選項,則傳回的指標會顯示查詢是在兩個單一欄位索引 ((category ASC, __name__ ASC)
和 (country ASC, __name__ ASC)
) 上執行。它會掃描 16500 個索引項目,但只會傳回 1200 個文件。
// Output query planning info { "indexes_used": [ {"query_scope": "Collection", "properties": "(category ASC, __name__ ASC)"}, {"query_scope": "Collection", "properties": "(country ASC, __name__ ASC)"}, ] } // Output query status { "resultsReturned": "1200", "executionDuration": "0.118882s", "readOperations": "1200", "debugStats": { "index_entries_scanned": "16500", "documents_scanned": "1200" "billing_details": { "documents_billable": "1200", "index_entries_billable": "0", "small_ops": "0", "min_query_cost": "0", } } }
如要最佳化執行查詢的效能,您可以建立完全涵蓋的複合索引 (category ASC, country ASC, __name__ ASC)
。
再次使用分析選項執行查詢時,我們可以看到系統為這項查詢選取了新建立的索引,且查詢執行速度和效率都大幅提升。
// Output query planning info { "indexes_used": [ {"query_scope": "Collection", "properties": "(category ASC, country ASC, __name__ ASC)"} ] } // Output query stats { "resultsReturned": "1200", "executionDuration": "0.026139s", "readOperations": "1200", "debugStats": { "index_entries_scanned": "1200", "documents_scanned": "1200" "billing_details": { "documents_billable": "1200", "index_entries_billable": "0", "small_ops": "0", "min_query_cost": "0", } } }