Abfrageleistung mit Query Explain verstehen

Mit Query Explain können Sie Firestore-Abfragen an das Back-End senden und im Gegenzug detaillierte Leistungsstatistiken zur Ausführung von Back-End-Abfragen erhalten. Sie funktioniert in vielen relationalen Datenbanksystemen wie die EXPLAIN [ANALYZE]-Operation.

Query Explain-Anfragen können mithilfe der Firestore-Server-Clientbibliotheken gesendet werden.

Die Ergebnisse von Query Explain helfen Ihnen zu verstehen, wie Ihre Abfragen ausgeführt werden, und zeigen Ihnen Ineffizienzen und den Ort wahrscheinlicher serverseitiger Engpässe auf.

Erklärende Abfrage:

  • Bietet Einblicke in die Abfrageplanungsphase, damit Sie Ihre Abfrageindexe anpassen und die Effizienz steigern können.
  • Mit der Option „Analysieren“ können Sie Kosten und Leistung pro Abfrage nachvollziehen und verschiedene Abfragemuster schnell durchlaufen, um deren Nutzung zu optimieren.

Optionen von Query Explain verstehen: Standard und Analyse

Query Explain-Vorgänge können mit der Standardoption oder der Analyseoption ausgeführt werden.

Bei der Standardoption plant Query Explain die Abfrage, überspringt aber die Ausführungsphase. Dadurch werden Informationen zur Planerphase zurückgegeben. Damit können Sie prüfen, ob eine Abfrage die erforderlichen Indexe hat und ermitteln, welche Indexe verwendet werden. So können Sie beispielsweise überprüfen, ob eine bestimmte Abfrage einen zusammengesetzten Index verwendet, anstatt sich mit vielen verschiedenen Indexen überschneiden zu müssen.

Mit der Option "Analysieren" plant und führt Query Explain sowohl die Abfrage als auch die Abfrage aus. Dadurch werden alle zuvor genannten Planerinformationen zusammen mit Statistiken zur Laufzeit der Abfrageausführung zurückgegeben. Dazu gehören die Abrechnungsinformationen der Abfrage und Informationen auf Systemebene zur Ausführung der Abfrage. Sie können dieses Tool verwenden, um verschiedene Abfrage- und Indexkonfigurationen zu testen, um ihre Kosten und Latenz zu optimieren.

Was kostet Query Explain?

Wenn Sie Query Explain mit der Standardoption verwenden, werden keine Index- oder Lesevorgänge ausgeführt. Unabhängig von der Komplexität der Abfrage wird ein Lesevorgang berechnet.

Wenn Sie Query Explain mit der Analyseoption verwenden, werden Index- und Lesevorgänge ausgeführt, sodass Ihnen die Abfrage wie gewohnt in Rechnung gestellt wird. Für die Analyseaktivität fallen keine zusätzlichen Kosten an, sondern nur die übliche Gebühr für die ausgeführte Abfrage.

Query Explain mit der Standardoption verwenden

Sie können die Clientbibliotheken verwenden, um eine Standardoptionsanfrage zu senden.

Anfragen werden mit IAM authentifiziert, wobei dieselben Berechtigungen für reguläre Abfragevorgänge verwendet werden. Andere Authentifizierungstechniken wie Firebase Authentication werden ignoriert. Weitere Informationen finden Sie in der Anleitung zu IAM für Server-Clientbibliotheken.

Java (Administrator)

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

    
Knoten (Administrator)

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;

    

Das genaue Format der Antwort hängt von der Ausführungsumgebung ab. Zurückgegebene Ergebnisse können in JSON konvertiert werden. Beispiel:

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

Weitere Informationen finden Sie in der Referenz zum Bericht „Query Explain“.

Query Explain mit der Analyseoption verwenden

Sie können die Clientbibliotheken verwenden, um eine Anfrage zur Analyseoption zu senden.

Anfragen werden mit IAM authentifiziert, wobei dieselben Berechtigungen für reguläre Abfragevorgänge verwendet werden. Andere Authentifizierungstechniken wie Firebase Authentication werden ignoriert. Weitere Informationen finden Sie in der Anleitung zu IAM für Server-Clientbibliotheken.

Java (Administrator)

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

    
Knoten (Administrator)

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;

    

Das folgende Beispiel zeigt das stats-Objekt, das zusätzlich zu planInfo zurückgegeben wird. Das genaue Format der Antwort hängt von der Ausführungsumgebung ab. Die Beispielantwort hat das JSON-Format.

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

}

Weitere Informationen finden Sie in der Referenz zum Bericht „Query Explain“.

Ergebnisse interpretieren und Anpassungen vornehmen

Sehen wir uns ein Beispielszenario an, in dem wir Filme nach Genre und Produktionsland abfragen.

Nehmen wir zur Veranschaulichung an, dass das Äquivalent zu dieser SQL-Abfrage verwendet wird.

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

Wenn wir die Option „Analysieren“ verwenden, zeigen die zurückgegebenen Messwerte, dass die Abfrage auf zwei Einzelfeldindexen ausgeführt wird: (category ASC, __name__ ASC) und (country ASC, __name__ ASC). Dabei werden 16.500 Indexeinträge gescannt, aber nur 1.200 Dokumente zurückgegeben.

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

Um die Leistung beim Ausführen der Abfrage zu optimieren, können Sie einen vollständig abgedeckten zusammengesetzten Index (category ASC, country ASC, __name__ ASC) erstellen.

Wenn Sie die Abfrage noch einmal mit der Option „Analysieren“ ausführen, sehen Sie, dass der neu erstellte Index für diese Abfrage ausgewählt ist und die Abfrage viel schneller und effizienter ausgeführt wird.

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