Abfrageleistung mithilfe von „Abfrageerläuterung“ analysieren

Mit der Abfrageerläuterung können Sie Cloud Firestore-Abfragen an das Backend senden und detaillierte Leistungsstatistiken zur Ausführung von Backendabfragen erhalten. Sie funktioniert in vielen relationalen Datenbanksystemen wie der Vorgang EXPLAIN [ANALYZE].

Anfragen zur Abfrageerläuterung können mit den Firestore-Server-Clientbibliotheken gesendet werden.

Die Ergebnisse der Abfrageerläuterung helfen Ihnen zu verstehen, wie Ihre Abfragen ausgeführt werden. Sie sehen Ineffizienzen und die Standorte wahrscheinlicher serverseitiger Engpässe.

Abfrageerläuterung:

  • Bietet Statistiken zur Phase der Abfrageplanung, damit Sie Ihre Abfrageindexe anpassen und die Effizienz steigern können.
  • Mit der Analyseoption können Sie die Kosten und die Leistung pro Abfrage nachvollziehen und schnell verschiedene Abfragemuster durchgehen, um die Nutzung zu optimieren.

Optionen für die Abfrageerläuterung: Standard und analysieren

Abfrageerläuterungen können mit der Option standard oder analysieren ausgeführt werden.

Bei der Standardoption wird die Abfrage mit Query Explain geplant, die Ausführungsphase wird jedoch übersprungen. Dadurch werden Informationen zur Planungsphase zurückgegeben. So können Sie prüfen, ob eine Abfrage die erforderlichen Indexe enthält, und nachvollziehen, welche Indexe verwendet werden. So können Sie beispielsweise prüfen, ob für eine bestimmte Abfrage ein zusammengesetzter Index verwendet wird, anstatt viele verschiedene Indexe überschneiden zu müssen.

Mit der Analyseoption erstellt Query Explain beide Pläne und führt die Abfrage aus. Dadurch werden alle zuvor genannten Informationen zum Planer sowie Statistiken zur Ausführungszeit der Abfrage zurückgegeben. Dazu gehören die Abrechnungsinformationen der Abfrage sowie Statistiken zur Abfrageausführung auf Systemebene. Mit diesen Tools können Sie verschiedene Abfrage- und Indexkonfigurationen testen, um Kosten und Latenz zu optimieren.

Wie viel kostet die Funktion „Abfrage erklären lassen“?

Wenn Sie „Abfrageerläuterung“ 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 „Abfrageerläuterung“ mit der Option „Analysieren“ verwenden, werden Index- und Lesevorgänge ausgeführt. Die Abfrage wird Ihnen daher wie gewohnt in Rechnung gestellt. Für die Analyseaktivität fallen keine zusätzlichen Kosten an, nur die üblichen Kosten für die ausgeführte Abfrage.

„Abfrage erläutern“ mit der Standardoption verwenden

Sie können die Clientbibliotheken verwenden, um eine Anfrage für die Standardoption zu senden.

Anfragen werden mit IAM authentifiziert und dabei dieselben Berechtigungen wie für reguläre Abfragevorgänge verwendet. Andere Authentifizierungsmethoden wie Firebase Authentication werden ignoriert. Weitere Informationen finden Sie im Leitfaden 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. Die zurückgegebenen 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 „Erläuterung von Abfragen“.

Abfrageerläuterung mit der Option „Analysieren“ verwenden

Sie können die Clientbibliotheken verwenden, um eine Anfrage für die Analyseoption zu senden.

Anfragen werden mit IAM authentifiziert und dabei dieselben Berechtigungen wie für reguläre Abfragevorgänge verwendet. Andere Authentifizierungsmethoden wie Firebase Authentication werden ignoriert. Weitere Informationen finden Sie im Leitfaden 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;

    

Im folgenden Beispiel wird das stats-Objekt zusätzlich zu planInfo zurückgegeben. Das genaue Format der Antwort hängt von der Ausführungsumgebung ab. Die Beispielantwort ist im 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 „Erläuterung von Abfragen“.

Ergebnisse interpretieren und Anpassungen vornehmen

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

Angenommen, Sie haben die folgende SQL-Abfrage.

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

Wenn wir die Analyseoption verwenden, zeigen die zurückgegebenen Messwerte, dass die Abfrage auf zwei Einzelfeldindexen ausgeführt wird: (category ASC, __name__ ASC) und (country ASC, __name__ ASC). Es 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 der Abfrageausführung zu optimieren, können Sie einen vollständig abgedeckten zusammengesetzten Index (category ASC, country ASC, __name__ ASC) erstellen.

Wenn wir die Abfrage noch einmal mit der Analyseoption ausführen, sehen wir, dass der neu erstellte Index für diese Abfrage ausgewählt ist. Die Abfrage wird viel schneller und effizienter ausgeführt.

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