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 i 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 query semplice
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" } } }
Dall'esperienza nel dominio puoi dedurre che la maggior parte dei dipendenti avrà almeno una certa esperienza, ma pochi avranno uno stipendio superiore a 100.000. Tenendo conto di 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 salary
vincolo 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 di intervallo è maggiore in questa query rispetto alla query precedente, la query viene eseguita più rapidamente ed è più efficiente in termini di costi.
// 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.