Questa pagina fornisce esempi di strategia di indicizzazione che puoi utilizzare per le query con filtri di intervallo e disuguaglianza su più campi per creare un'esperienza di query efficiente.
Prima di ottimizzare le query, leggi informazioni sui concetti correlati.
Ottimizzare le query con Query Explain
Per determinare se la query e gli indici sono ottimali, puoi utilizzare Query Explain per ottenere il riepilogo del piano di query e le statistiche di esecuzione della query:
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);
L'esempio seguente mostra come l'utilizzo dell'ordinamento corretto degli indici riduce il numero di voci di indice scansionate da Cloud Firestore.
Query semplici
Con l'esempio precedente di una raccolta di dipendenti, la semplice query
che viene eseguita con l'indice (experience ASC, salary ASC)
è la seguente:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("experience")
.orderBy("salary");
La query esegue la scansione di 95.000 voci di indice solo per restituire cinque documenti. Poiché il predicato della query non è soddisfatto, viene letto un numero elevato di voci di indice, ma vengono filtrate.
// 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" } } }
Puoi dedurre dall'esperienza nel settore che la maggior parte dei dipendenti avrà almeno un po' di esperienza, ma pochi avranno uno stipendio superiore a 100.000. Da questa
informazione, puoi notare che il vincolo salary
è più selettivo del
vincolo experience
. Per influenzare l'indice utilizzato da Cloud Firestore per
eseguire la query, specifica una clausola orderBy
che ordina il vincolo salary
prima del vincolo experience
.
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("salary")
.orderBy("experience");
Quando utilizzi esplicitamente la clausola orderBy()
per aggiungere i predicati,
Cloud Firestore utilizza l'indice (salary ASC, experience ASC)
per eseguire la query.
Poiché la selettività del primo filtro intervallo è maggiore in questa query
rispetto alla query precedente, la query viene eseguita più velocemente ed è più conveniente.
// 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" } } }
Passaggi successivi
- Scopri di più su Query Explain.
- Scopri di più sulle best practice di indicizzazione.