Informazioni sulle prestazioni delle query utilizzando la spiegazione delle query

Query Explain ti consente di inviare query Firestore al backend e ricevere statistiche dettagliate sulle prestazioni relative all'esecuzione delle query di backend in cambio. Funziona come l'operazione EXPLAIN [ANALYZE] in molti sistemi di database relazionali.

Le richieste Query Explain possono essere inviate utilizzando le librerie client dei server Firestore.

I risultati di Query Explain ti aiutano a capire come vengono eseguite le query, mostrando inefficienze e posizione di probabili colli di bottiglia sul lato server.

Spiegazione della query:

  • Fornisce insight sulla fase di pianificazione delle query per consentirti di regolare gli indici delle query e aumentare l'efficienza.
  • L'opzione di analisi ti consente di comprendere costi e prestazioni per singola query e di eseguire rapidamente l'iterazione attraverso diversi pattern di query per ottimizzare il loro utilizzo.

Informazioni sulle opzioni di Query Explain: impostazione predefinita e analisi

Le operazioni Query Explain possono essere eseguite utilizzando l'opzione default o analyze.

Con l'opzione predefinita, Query Explain pianifica la query, ma salta la fase di esecuzione. Verranno restituite le informazioni sulla fase dello strumento di pianificazione. Puoi utilizzarlo per verificare che una query abbia gli indici necessari e capire quali indici vengono utilizzati. In questo modo puoi verificare, ad esempio, che una determinata query utilizzi un indice composto invece di intersecarsi con molti indici diversi.

Con l'opzione di analisi, Query Explain pianifica ed esegue la query. Questa operazione restituisce tutte le informazioni dello strumento di pianificazione menzionate in precedenza insieme alle statistiche relative al runtime di esecuzione della query. Ciò includerà le informazioni di fatturazione della query e insight a livello di sistema nell'esecuzione della query. Puoi utilizzare questi strumenti per testare varie configurazioni di query e indici al fine di ottimizzarne costi e latenza.

Quanto costa la query Explain?

Quando utilizzi Query Explain con l'opzione predefinita, non vengono eseguite operazioni di indice o lettura. Indipendentemente dalla complessità della query, viene addebitata un'operazione di lettura.

Quando utilizzi Query Explain con l'opzione di analisi, vengono eseguite operazioni di indicizzazione e lettura, quindi la query ti viene addebitata come di consueto. Non sono previsti costi aggiuntivi per l'attività di analisi, ma solo il normale addebito per l'esecuzione della query.

Utilizza Spiegazione query con l'opzione predefinita

Puoi utilizzare le librerie client per inviare una richiesta di opzione predefinita.

Tieni presente che le richieste vengono autenticate con IAM e utilizzano le stesse autorizzazioni per le normali operazioni di query. Altre tecniche di autenticazione, come Firebase Authentication, vengono ignorate. Per maggiori informazioni, consulta la guida IAM per le librerie client dei server.

Java (amministratore)

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();

    
Nodo (amministratore)

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;

    

Il formato esatto della risposta dipende dall'ambiente di esecuzione. I risultati restituiti possono essere convertiti in formato JSON. Ad esempio:

{
    "indexes_used": [
        {"query_scope": "Collection", "properties": "(category ASC, __name__ ASC)"},
        {"query_scope": "Collection", "properties": "(country ASC, __name__ ASC)"},
    ]
}

Per ulteriori informazioni, consulta la sezione Riferimento al report Query Explain.

Utilizzare la spiegazione delle query con l'opzione di analisi

Puoi utilizzare le librerie client per inviare una richiesta di opzione di analisi.

Tieni presente che le richieste vengono autenticate con IAM e utilizzano le stesse autorizzazioni per le normali operazioni di query. Altre tecniche di autenticazione, come Firebase Authentication, vengono ignorate. Per maggiori informazioni, consulta la guida IAM per le librerie client dei server.

Java (amministratore)

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();

    
Nodo (amministratore)

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;

    

Nell'esempio seguente viene mostrato l'oggetto stats restituito in aggiunta a planInfo. Il formato esatto della risposta dipende dall'ambiente di esecuzione. La risposta di esempio è in formato 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",
               }
    }

}

Per ulteriori informazioni, consulta la sezione Riferimento al report Query Explain.

Interpretare i risultati e apportare modifiche

Esaminiamo uno scenario di esempio in cui eseguiamo query sui film per genere e paese di produzione.

Ad esempio, supponiamo l'equivalente di questa query SQL.

SELECT *
FROM /movies
WHERE category = 'Romantic' AND country = 'USA';

Se utilizziamo l'opzione di analisi, le metriche restituite mostrano che la query viene eseguita su due indici a campo singolo, (category ASC, __name__ ASC) e (country ASC, __name__ ASC). Analizza 16.500 voci di indice, ma restituisce solo 1200 documenti.

// 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",
               }
    }
}

Per ottimizzare le prestazioni dell'esecuzione della query, puoi creare un indice composto completamente coperto (category ASC, country ASC, __name__ ASC).

Eseguendo di nuovo la query con l'opzione di analisi, possiamo vedere che l'indice appena creato è selezionato per questa query e che la query viene eseguita in modo molto più rapido ed efficiente.

// 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",
               }
    }
}