Na tej stronie znajdziesz przykłady strategii indeksowania, których możesz używać w zapytaniach z filtrami zakresu i nierówności w różnych polach, aby zwiększyć efektywność zapytań.
Przed zoptymalizowaniem zapytań zapoznaj się z powiązanymi pojęciami.
Optymalizowanie zapytań za pomocą Query Explain
Aby określić, czy Twoje zapytanie i indeksy są optymalne, możesz użyć polecenia Query Explain, aby uzyskać podsumowanie planu zapytania i statystyki wykonania zapytania:
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);
Poniższy przykład pokazuje, jak zastosowanie prawidłowej kolejności indeksu zmniejsza liczbę wpisów indeksu skanowanych przez Cloud Firestore.
proste zapytania,
W wcześniejszym przykładzie zbioru pracowników proste zapytanie uruchamiane z indeksem (experience ASC, salary ASC)
wygląda tak:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("experience")
.orderBy("salary");
Zapytanie skanuje tylko 95 000 wpisów indeksu, aby zwrócić 5 dokumentów. Ponieważ predykat zapytania nie jest spełniony, odczytywana jest duża liczba wpisów w indeksie, ale są one odfiltrowywane.
// 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" } } }
Na podstawie specjalistycznej wiedzy w danej dziedzinie możesz wywnioskować, że większość pracowników ma co najmniej pewne doświadczenie, ale niewiele osób zaoferuje wynagrodzenie powyżej 1 000 000 000. Biorąc pod uwagę te dane, możesz zauważyć, że ograniczenie salary
jest bardziej selektywne niż ograniczenie experience
. Aby wpływać na indeks, którego Cloud Firestore używa do wykonywania zapytania, określ klauzulę orderBy
, która porządkuje ograniczenie salary
przed ograniczeniem experience
.
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("salary")
.orderBy("experience");
Gdy dodajesz predykaty, używając wyraźnie klauzuli orderBy()
, funkcja Cloud Firestore używa indeksu (salary ASC, experience ASC)
do wykonywania zapytań.
Selektywność pierwszego filtra zakresu jest w tym zapytaniu większa w porównaniu z poprzednim zapytaniem, dlatego zapytanie działa szybciej i jest tańsze.
// 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" } } }
Co dalej?
- Dowiedz się więcej o wyjaśnieniach zapytań.
- Dowiedz się więcej o sprawdzonych metodach indeksowania.