本頁面提供索引策略範例,您可以針對多個欄位的查詢使用範圍和不相等篩選器,打造高效率的查詢體驗。
在最佳化查詢之前,請先閱讀相關概念。
使用查詢說明來最佳化查詢
如要判斷查詢和索引是否最佳化,您可以使用 Query Explain 取得查詢的查詢計畫摘要和執行統計資料:
Java
Query q = db.collection("employees").whereGreaterThan("salary",
100000).whereGreaterThan("experience", 0);
ExplainResults<QuerySnapshot> explainResults = q.explain(ExplainOptions.builder().analyze(true).build()).get();
ExplainMetrics metrics = explainResults.getMetrics();
PlanSummary planSummary = metrics.getPlanSummary();
ExecutionStats executionStats = metrics.getExecutionStats();
System.out.println(planSummary.getIndexesUsed());
System.out.println(stats.getResultsReturned());
System.out.println(stats.getExecutionDuration());
System.out.println(stats.getReadOperations());
System.out.println(stats.getDebugStats());
Node.js
let q = db.collection("employees")
.where("salary", ">", 100000)
.where("experience", ">",0);
let options = { analyze : 'true' };
let explainResults = await q.explain(options);
let planSummary = explainResults.metrics.planSummary;
let stats = explainResults.metrics.executionStats;
console.log(planSummary);
console.log(stats);
以下範例說明如何使用正確的索引排序,減少 Cloud Firestore 掃描的索引項目數量。
簡易查詢
以先前的員工集合範例為例,以下是使用 (experience ASC, salary ASC)
索引執行的簡易查詢:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("experience")
.orderBy("salary");
查詢會掃描 95,000 個索引項目,但只會傳回五份文件。由於查詢述元不符合條件,因此系統會讀取大量索引項目,但會篩除這些項目。
// Output query planning info { "indexesUsed": [ { "properties": "(experience ASC, salary ASC, __name__ ASC)", "query_scope": "Collection" } ], // Output Query Execution Stats "resultsReturned": "5", "executionDuration": "2.5s", "readOperations": "100", "debugStats": { "index_entries_scanned": "95000", "documents_scanned": "5", "billing_details": { "documents_billable": "5", "index_entries_billable": "95000", "small_ops": "0", "min_query_cost": "0" } } }
您可以從專業領域推斷,大多數員工至少都會有一些經驗,但薪水超過 100000 的員工很少。有了這項洞察資料,您就能瞭解 salary
限制條件比 experience
限制條件更具選擇性。如要影響 Cloud Firestore 用來執行查詢的索引,請指定 orderBy
子句,將 salary
限制排在 experience
限制之前。
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("salary")
.orderBy("experience");
當您明確使用 orderBy()
子句新增謂詞時,Cloud Firestore 會使用 (salary ASC, experience ASC)
索引來執行查詢。由於這個查詢中的第一個範圍篩選器的選擇性高於先前的查詢,因此查詢執行速度更快,且成本效益更高。
// Output query planning info { "indexesUsed": [ { "properties": "(salary ASC, experience ASC, __name__ ASC)", "query_scope": "Collection" } ], // Output Query Execution Stats "resultsReturned": "5", "executionDuration": "0.2s", "readOperations": "6", "debugStats": { "index_entries_scanned": "1000", "documents_scanned": "5", "billing_details": { "documents_billable": "5", "index_entries_billable": "1000", "small_ops": "0", "min_query_cost": "0" } } }