Abfragestatistiken

Spanner bietet integrierte Tabellen mit vielen Statistiken für die am meisten CPU genutzten Abfragen und DML-Anweisungen. Außerdem werden alle Abfragen insgesamt zusammengefasst (einschließlich Änderungsstreamabfragen).

Verfügbarkeit

SPANNER_SYS-Daten sind nur über SQL-Schnittstellen verfügbar. Beispiel:

Andere von Spanner bereitgestellte Methoden für einzelne Leseaufrufe unterstützen SPANNER_SYS nicht.

Nach Abfrage gruppierte CPU-Nutzung

In den folgenden Tabellen werden die Abfragen mit der höchsten CPU-Auslastung während eines bestimmten Zeitraums nachverfolgt:

  • SPANNER_SYS.QUERY_STATS_TOP_MINUTE: Abfragen in Intervallen von 1 Minute
  • SPANNER_SYS.QUERY_STATS_TOP_10MINUTE: Abfragen in Intervallen von 10 Minuten
  • SPANNER_SYS.QUERY_STATS_TOP_HOUR: Abfragen in Intervallen von 1 Stunde

Diese Tabellen haben folgende Attribute:

  • Jede Tabelle enthält Daten für nicht überlappende Zeitintervalle in der Länge, die der Tabellenname festlegt.

  • Die Intervalle basieren auf der Uhrzeit. 1-Minuten-Intervalle enden jeweils zur vollen Minute, 10-Minuten-Intervalle enden alle 10 Minuten ab der vollen Stunde und 1-Stunden-Intervalle enden zur vollen Stunde.

    Beispielsweise sind die neuesten, für SQL-Abfragen verfügbaren Intervalle um 11:59:30 Uhr:

    • 1 Minute: 11:58:00–11:58:59 Uhr
    • 10 Minuten: 11:40:00–11:49:59 Uhr
    • 1 Stunde: 10:00:00–10:59:59 Uhr
  • Spanner gruppiert die Statistiken nach dem Text der SQL-Abfrage. Wenn eine Abfrage Abfrageparameter verwendet, gruppiert Spanner alle Ausführungen der Abfrage in einer Zeile. Wenn die Abfrage Stringliterale verwendet, gruppiert Spanner die Statistiken nur, wenn der vollständige Abfragetext identisch ist. Wenn sich der Text unterscheidet, wird jede Abfrage als separate Zeile angezeigt. Bei Batch-DML normalisiert Spanner den Batch, indem aufeinanderfolgende identische Anweisungen vor dem Generieren des Fingerabdrucks dedupliziert werden.

  • Wenn ein Anfrage-Tag vorhanden ist, ist F der Hash des Anfrage-Tags. Andernfalls ist es der Hash des Werts TEXT.

  • Jede Zeile enthält Statistiken für alle Ausführungen einer bestimmten SQL-Abfrage, für die Spanner während des angegebenen Intervalls Statistiken erfasst.

  • Wenn Spanner nicht alle während des Intervalls ausgeführten Abfragen speichern kann, priorisiert das System Abfragen mit der höchsten CPU-Nutzung im angegebenen Intervall.

  • Verfolgte Abfragen umfassen Abfragen, die abgeschlossen, fehlgeschlagen oder vom Nutzer abgebrochen wurden.

  • Eine Teilmenge der Statistiken bezieht sich auf Abfragen, die ausgeführt, aber nicht abgeschlossen wurden:

    • Ausführungsanzahl und durchschnittliche Latenz in Sekunden für alle Abfragen, die nicht erfolgreich waren.

    • Ausführungsanzahl für Abfragen, die zu einer Zeitüberschreitung geführt haben.

    • Ausführungsanzahl für Abfragen, die vom Nutzer abgebrochen oder aufgrund von Problemen mit der Netzwerkverbindung fehlgeschlagen sind.

Tabellenschema

Spaltenname Typ Beschreibung
INTERVAL_END TIMESTAMP Ende des Zeitintervalls, in dem die eingeschlossene Abfrage ausgeführt wurde
REQUEST_TAG STRING Das optionale Anfrage-Tag für diesen Abfragevorgang. Weitere Informationen zur Verwendung von Tags finden Sie unter Fehlerbehebung bei Anfrage-Tags.
QUERY_TYPE STRING Gibt an, ob eine Abfrage PARTITIONED_QUERY oder QUERY ist. Ein PARTITIONED_QUERY ist eine Abfrage mit einem partitionToken, die von der PartitionQuery API abgerufen wurde. Alle anderen Abfragen und DML-Anweisungen sind durch den Abfragetyp QUERY gekennzeichnet. Abfragestatistiken für partitionierte DML werden nicht unterstützt.
TEXT STRING SQL-Abfragetext, verkürzt auf ca. 64 KB

Statistiken für mehrere Abfragen, die denselben Tag-String haben, werden in einer einzelnen Zeile gruppiert, wobei REQUEST_TAG mit diesem Tag-String übereinstimmt. In diesem Feld wird nur der Text einer dieser Abfragen angezeigt, verkürzt auf ca. 64 KB. Für Batch-DML wird der Satz von SQL-Anweisungen zu einer einzelnen Zeile vereinfacht und mithilfe eines Semikolon-Trennzeichens verkettet. Aufeinanderfolgende identische SQL-Texte werden vor dem Abschneiden dedupliziert.
TEXT_TRUNCATED BOOL Ob der Abfragetext gekürzt wurde oder vollständig ist
TEXT_FINGERPRINT INT64 Der Hash des Werts REQUEST_TAG, falls vorhanden; andernfalls der Hash des Werts TEXT.
EXECUTION_COUNT INT64 Gibt an, wie oft Spanner die Abfrage während des Intervalls gesehen hat.
AVG_LATENCY_SECONDS FLOAT64 Durchschnittliche Zeit in Sekunden für jede Abfrageausführung in der Datenbank; dieser Durchschnitt schließt die Codierungs- und Übertragungszeit für die Ergebnismenge sowie den Aufwand aus.
AVG_ROWS FLOAT64 Durchschnittliche Anzahl der Zeilen, die die Abfrage zurückgegeben hat
AVG_BYTES FLOAT64 Die durchschnittliche Anzahl der von der Abfrage zurückgegebenen Datenbyte, ohne den Aufwand der Übertragungskodierung
AVG_ROWS_SCANNED FLOAT64 Durchschnittliche Anzahl der Zeilen, die von der Abfrage gescannt wurden, ausgenommen gelöschte Werte
AVG_CPU_SECONDS FLOAT64 Durchschnittliche Anzahl von Sekunden der CPU-Zeit, die Spanner zum Ausführen der Abfrage für alle Vorgänge aufgewendet hat.
ALL_FAILED_EXECUTION_COUNT INT64 Häufigkeit, mit der die Abfrage während des Intervalls fehlgeschlagen ist.
ALL_FAILED_AVG_LATENCY_SECONDS FLOAT64 Durchschnittliche Zeit in Sekunden für jede Abfrageausführung, die in der Datenbank fehlgeschlagen ist dieser Durchschnitt schließt die Codierungs- und Übertragungszeit für die Ergebnismenge sowie den Aufwand aus.
CANCELLED_OR_DISCONNECTED_EXECUTION_COUNT INT64 Häufigkeit, mit der die Abfrage vom Nutzer abgebrochen oder aufgrund einer unterbrochenen Netzwerkverbindung während des Intervalls abgebrochen wurde.
TIMED_OUT_EXECUTION_COUNT INT64 Häufigkeit, mit der die Abfrage während des Intervalls das Zeitlimit überschritten hat.
AVG_BYTES_WRITTEN FLOAT64 Durchschnittliche Anzahl der von der Anweisung geschriebenen Byte.
AVG_ROWS_WRITTEN FLOAT64 Durchschnittliche Anzahl der Zeilen, die durch die Anweisung geändert wurden.
STATEMENT_COUNT INT64 Die Summe der in diesem Eintrag aggregierten Anweisungen. Bei regulären Abfragen und DML entspricht dies der Ausführungszahl. Bei Batch-DML erfasst Spanner die Anzahl der Anweisungen im Batch.
RUN_IN_RW_TRANSACTION_EXECUTION_COUNT INT64 Die Häufigkeit, mit der die Abfrage als Teil einer Lese-Schreib-Transaktion ausgeführt wurde. Mithilfe dieser Spalte können Sie feststellen, ob Sie Sperrenkonflikte vermeiden können, indem Sie die Abfrage in eine schreibgeschützte Transaktion verschieben.
LATENCY_DISTRIBUTION ARRAY<STRUCT>

Ein Histogramm der Abfrageausführungszeit. Die Werte werden in Sekunden gemessen.

Das Array enthält ein einzelnes Element und hat den folgenden Typ:
ARRAY<STRUCT<
  COUNT INT64,
  MEAN FLOAT64,
  SUM_OF_SQUARED_DEVIATION FLOAT64,
  NUM_FINITE_BUCKETS INT64,
  GROWTH_FACTOR FLOAT64,
  SCALE FLOAT64,
  BUCKET_COUNTS ARRAY<INT64>>>

Weitere Informationen zu den Werten finden Sie unter Verteilung.

Verwenden Sie die Funktion SPANNER_SYS.DISTRIBUTION_PERCENTILE(distribution, n FLOAT64), die das geschätzte n Perzentil zurückgibt, um die gewünschte Perzentillatenz aus der Verteilung zu berechnen. Ein entsprechendes Beispiel finden Sie unter Latenz des 99. Perzentils für Abfragen ermitteln.

Weitere Informationen finden Sie unter Perzentil und Messwerte mit Verteilungsmesswerten.

EXECUTION_COUNT, AVG_LATENCY_SECONDS und LATENCY_DISTRIBUTION für fehlgeschlagene Abfragen enthalten Abfragen, die aufgrund einer falschen Syntax fehlgeschlagen sind oder bei denen ein vorübergehender Fehler aufgetreten ist, aber bei einem erneuten Versuch erfolgreich war.

Zusammengefasste Statistiken

Es gibt auch Tabellen, in denen aggregierte Daten für alle Abfragen nachverfolgt werden, für die Spanner Statistiken zu einem bestimmten Zeitraum erfasst hat:

  • SPANNER_SYS.QUERY_STATS_TOTAL_MINUTE: Abfragen in Intervallen von 1 Minute
  • SPANNER_SYS.QUERY_STATS_TOTAL_10MINUTE: Abfragen in Intervallen von 10 Minuten
  • SPANNER_SYS.QUERY_STATS_TOTAL_HOUR: Abfragen in Intervallen von 1 Stunde

Diese Tabellen haben folgende Attribute:

  • Jede Tabelle enthält Daten für nicht überlappende Zeitintervalle in der Länge, die der Tabellenname festlegt.

  • Die Intervalle basieren auf der Uhrzeit. 1-Minuten-Intervalle enden jeweils zur vollen Minute, 10-Minuten-Intervalle enden alle 10 Minuten ab der vollen Stunde und 1-Stunden-Intervalle enden zur vollen Stunde.

    Beispielsweise sind die neuesten, für SQL-Abfragen verfügbaren Intervalle um 11:59:30 Uhr:

    • 1 Minute: 11:58:00–11:58:59 Uhr
    • 10 Minuten: 11:40:00–11:49:59 Uhr
    • 1 Stunde: 10:00:00–10:59:59 Uhr
  • Jede Zeile enthält zusammengefasste Statistiken für alle Abfragen, die während des angegebenen Intervalls über die Datenbank ausgeführt werden. Es gibt nur eine Zeile pro Zeitintervall und enthält abgeschlossene Abfragen, fehlgeschlagene Abfragen und vom Nutzer abgebrochene Abfragen.

  • Die in den TOTAL-Tabellen erfassten Statistiken können Abfragen enthalten, die Spanner nicht in den TOP-Tabellen erfasst hat.

  • Einige Spalten in diesen Tabellen werden in Cloud Monitoring als Messwerte angezeigt. Die exponierten Messwerte sind:

    • Anzahl der Abfrageausführungen
    • Abfragefehler
    • Abfragelatenzen
    • Anzahl der zurückgegebenen Zeilen
    • Anzahl gescannter Zeilen
    • Anzahl der zurückgegebenen Byte
    • CPU-Zeit für Abfragen

    Weitere Informationen finden Sie unter Spanner-Messwerte.

Tabellenschema

Spaltenname Typ Beschreibung
INTERVAL_END TIMESTAMP Ende des Zeitintervalls, in dem die eingeschlossene Abfrage ausgeführt wurde
EXECUTION_COUNT INT64 Gibt an, wie oft Spanner die Abfrage während des Zeitintervalls gesehen hat.
AVG_LATENCY_SECONDS FLOAT64 Durchschnittliche Zeit in Sekunden für jede Abfrageausführung in der Datenbank; dieser Durchschnitt schließt die Codierungs- und Übertragungszeit für die Ergebnismenge sowie den Aufwand aus.
AVG_ROWS FLOAT64 Durchschnittliche Anzahl der Zeilen, die die Abfrage zurückgegeben hat
AVG_BYTES FLOAT64 Die durchschnittliche Anzahl der von der Abfrage zurückgegebenen Datenbyte, ohne den Aufwand der Übertragungskodierung
AVG_ROWS_SCANNED FLOAT64 Durchschnittliche Anzahl der Zeilen, die von der Abfrage gescannt wurden, ausgenommen gelöschte Werte
AVG_CPU_SECONDS FLOAT64 Durchschnittliche Anzahl von Sekunden der CPU-Zeit, die Spanner zum Ausführen der Abfrage für alle Vorgänge aufgewendet hat.
ALL_FAILED_EXECUTION_COUNT INT64 Häufigkeit, mit der die Abfrage während des Intervalls fehlgeschlagen ist.
ALL_FAILED_AVG_LATENCY_SECONDS FLOAT64 Durchschnittliche Zeit in Sekunden für jede Abfrageausführung, die in der Datenbank fehlgeschlagen ist dieser Durchschnitt schließt die Codierungs- und Übertragungszeit für die Ergebnismenge sowie den Aufwand aus.
CANCELLED_OR_DISCONNECTED_EXECUTION_COUNT INT64 Häufigkeit, mit der die Abfrage vom Nutzer abgebrochen oder aufgrund einer unterbrochenen Netzwerkverbindung während des Intervalls abgebrochen wurde.
TIMED_OUT_EXECUTION_COUNT INT64 Häufigkeit, mit der die Abfrage während des Intervalls das Zeitlimit überschritten hat.
AVG_BYTES_WRITTEN FLOAT64 Durchschnittliche Anzahl der von der Anweisung geschriebenen Byte.
AVG_ROWS_WRITTEN FLOAT64 Durchschnittliche Anzahl der Zeilen, die durch die Anweisung geändert wurden.
RUN_IN_RW_TRANSACTION_EXECUTION_COUNT INT64 Die Häufigkeit, mit der Abfragen als Teil von Lese-/Schreibtransaktionen ausgeführt wurden. Mithilfe dieser Spalte können Sie feststellen, ob Sie Sperrenkonflikte vermeiden können, indem Sie einige Abfragen in schreibgeschützte Transaktionen verschieben.
LATENCY_DISTRIBUTION ARRAY<STRUCT>

Ein Histogramm der Ausführungszeit über Abfragen hinweg. Die Werte werden in Sekunden gemessen.

Geben Sie das Array so an:
ARRAY<STRUCT<
  COUNT INT64,
  MEAN FLOAT64,
  SUM_OF_SQUARED_DEVIATION FLOAT64,
  NUM_FINITE_BUCKETS INT64,
  GROWTH_FACTOR FLOAT64,
  SCALE FLOAT64,
  BUCKET_COUNTS ARRAY<INT64>>>

Weitere Informationen zu den Werten finden Sie unter Verteilung.

Verwenden Sie die Funktion SPANNER_SYS.DISTRIBUTION_PERCENTILE(distribution, n FLOAT64), die das geschätzte n Perzentil zurückgibt, um die gewünschte Perzentillatenz aus der Verteilung zu berechnen. Ein entsprechendes Beispiel finden Sie unter Latenz des 99. Perzentils für Abfragen ermitteln.

Weitere Informationen finden Sie unter Perzentil und Messwerte mit Verteilungsmesswerten.

Datenaufbewahrung

Spanner speichert die Daten für jede Tabelle mindestens für die folgenden Zeiträume:

  • SPANNER_SYS.QUERY_STATS_TOP_MINUTE und SPANNER_SYS.QUERY_STATS_TOTAL_MINUTE: Intervalle der letzten 6 Stunden.

  • SPANNER_SYS.QUERY_STATS_TOP_10MINUTE und SPANNER_SYS.QUERY_STATS_TOTAL_10MINUTE: Intervalle der letzten 4 Tage.

  • SPANNER_SYS.QUERY_STATS_TOP_HOUR und SPANNER_SYS.QUERY_STATS_TOTAL_HOUR: Intervalle der letzten 30 Tage.

Beispielabfragen

Dieser Abschnitt enthält mehrere Beispiel-SQL-Anweisungen, die Abfragestatistiken abrufen. Sie können diese SQL-Anweisungen mit den Clientbibliotheken, der Google Cloud CLI oder der Google Cloud Console ausführen.

Grundlegende Statistiken für jede Abfrage in einem bestimmten Zeitraum auflisten

Die folgende Abfrage gibt die Rohdaten für die Top-Abfragen der vorherigen Minute zurück:

SELECT text,
       request_tag,
       interval_end,
       execution_count,
       avg_latency_seconds,
       avg_rows,
       avg_bytes,
       avg_rows_scanned,
       avg_cpu_seconds
FROM spanner_sys.query_stats_top_minute
ORDER BY interval_end DESC;

Abfragen mit der höchsten CPU-Nutzung auflisten

Die folgende Abfrage gibt die Abfragen mit der höchsten CPU-Nutzung der vorherigen Stunde zurück:

SELECT text,
       request_tag,
       execution_count AS count,
       avg_latency_seconds AS latency,
       avg_cpu_seconds AS cpu,
       execution_count * avg_cpu_seconds AS total_cpu
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_hour)
ORDER BY total_cpu DESC;

Gesamtzahl der Ausführungen in einem bestimmten Zeitraum ermitteln

Die folgende Abfrage gibt die Gesamtzahl der im letzten vollständigen 1-Minuten-Intervall ausgeführten Abfragen zurück:

SELECT interval_end,
       execution_count
FROM spanner_sys.query_stats_total_minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_minute);

Durchschnittliche Latenz für eine Abfrage ermitteln

Die folgende Abfrage gibt die durchschnittliche Latenzzeit für eine bestimmte Abfrage zurück:

SELECT avg_latency_seconds
FROM spanner_sys.query_stats_top_hour
WHERE text LIKE "SELECT x FROM table WHERE x=@foo;";

Latenz des 99. Perzentils für Abfragen ermitteln

Die folgende Abfrage gibt das 99. Perzentil der Ausführungszeit für alle Abfragen zurück, die in den letzten 10 Minuten ausgeführt wurden:

SELECT interval_end, avg_latency_seconds, SPANNER_SYS.DISTRIBUTION_PERCENTILE(latency_distribution[OFFSET(0)], 99.0)
  AS percentile_latency
FROM spanner_sys.query_stats_total_10minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_total_10minute)
ORDER BY interval_end;

Ein Vergleich der durchschnittlichen Latenz mit der Latenz des 99. Perzentils hilft beim Identifizieren möglicher Ausreißerabfragen mit langen Ausführungszeiten.

Abfragen finden, die die meisten Daten scannen

Sie können die Anzahl der von einer Abfrage gescannten Zeilen als Maß für die Datenmenge verwenden, die von der Abfrage gescannt wurde. Die folgende Abfrage gibt die Anzahl der Zeilen zurück, die von Abfragen gescannt wurden, die in der vorherigen Stunde ausgeführt wurden:

SELECT text,
       execution_count,
       avg_rows_scanned
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_hour)
ORDER BY avg_rows_scanned DESC;

Die Aussagen finden, die die meisten Daten geschrieben haben

Sie können die Anzahl der von DML geschriebenen Zeilen (oder Byte) als Maß für die Datenmenge verwenden, die durch die Abfrage geändert wurde. Die folgende Abfrage gibt die Anzahl der Zeilen zurück, die von DML-Anweisungen geschrieben wurden, die in der vorherigen Stunde ausgeführt wurden:

SELECT text,
       execution_count,
       avg_rows_written
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_hour)
ORDER BY avg_rows_written DESC;

Gesamte CPU-Nutzung über alle Abfragen hinweg

Die folgende Abfrage gibt die Anzahl der in der vorherigen Stunde verwendeten CPU-Stunden zurück:

SELECT (avg_cpu_seconds * execution_count / 60 / 60)
  AS total_cpu_hours
FROM spanner_sys.query_stats_total_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_total_hour);

Abfragen auflisten, die in einem bestimmten Zeitraum fehlgeschlagen sind

Die folgende Abfrage gibt die Rohdaten zurück, einschließlich Ausführungsanzahl und durchschnittlicher Latenz fehlgeschlagener Abfragen für die Top-Abfragen der vorherigen Minute:

SELECT text,
       request_tag,
       interval_end,
       execution_count,
       all_failed_execution_count,
       all_failed_avg_latency_seconds,
       avg_latency_seconds,
       avg_rows,
       avg_bytes,
       avg_rows_scanned,
       avg_cpu_seconds
FROM spanner_sys.query_stats_top_minute
WHERE all_failed_execution_count > 0
ORDER BY interval_end;

Gesamtfehleranzahl in einem bestimmten Zeitraum ermitteln

Die folgende Abfrage gibt die Gesamtzahl der Abfragen zurück, die im letzten vollständigen 1-Minuten-Intervall nicht ausgeführt werden konnten.

SELECT interval_end,
       all_failed_execution_count
FROM spanner_sys.query_stats_total_minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_minute)
ORDER BY interval_end;

Listen Sie die Abfragen auf, die am häufigsten Zeitüberschreitungen verursachen

Die folgende Abfrage gibt die Abfragen mit der höchsten Zeitüberschreitung in der vorherigen Stunde zurück.

SELECT text,
       execution_count AS count,
       timed_out_execution_count AS timeout_count,
       avg_latency_seconds AS latency,
       avg_cpu_seconds AS cpu,
       execution_count * avg_cpu_seconds AS total_cpu
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_hour)
ORDER BY timed_out_execution_count DESC;

Die durchschnittliche Latenz erfolgreicher und fehlgeschlagener Ausführungen einer Abfrage ermitteln

Die folgende Abfrage gibt die kombinierte durchschnittliche Latenz, die durchschnittliche Latenz für erfolgreiche Ausführungen und die durchschnittliche Latenz für fehlgeschlagene Ausführungen für eine bestimmte Abfrage zurück.

SELECT avg_latency_seconds AS combined_avg_latency,
       all_failed_avg_latency_seconds AS failed_execution_latency,
       ( avg_latency_seconds * execution_count -
         all_failed_avg_latency_seconds * all_failed_execution_count
       ) / (
       execution_count - all_failed_execution_count ) AS success_execution_latency
FROM   spanner_sys.query_stats_top_hour
WHERE  text LIKE "select x from table where x=@foo;";

Fehlerbehebung bei hoher CPU-Auslastung oder erhöhter Abfragelatenz mit Abfragestatistiken

Abfragestatistiken sind nützlich, wenn Sie eine hohe CPU-Auslastung in Ihrer Spanner-Datenbank untersuchen oder einfach versuchen möchten, die CPU-lastigen Abfrageformen in Ihrer Datenbank zu verstehen. Die Prüfung von Abfragen, die große Mengen an Datenbankressourcen nutzen, bietet Spanner-Nutzern eine Möglichkeit, die Betriebskosten zu senken und möglicherweise die allgemeinen Systemlatenzen zu verbessern.

Sie können SQL-Code oder das Dashboard Query Insights verwenden, um problematische Abfragen in Ihrer Datenbank zu untersuchen. In den folgenden Abschnitten wird gezeigt, wie Sie solche Abfragen mithilfe von SQL-Code untersuchen können.

Im folgenden Beispiel liegt der Fokus auf der CPU-Auslastung. Es können ähnliche Schritte ausgeführt werden, um eine erhöhte Abfragelatenz zu beheben und die Abfragen mit den höchsten Latenzen zu ermitteln. Wählen Sie einfach Zeitintervalle und Abfragen nach Latenz anstatt nach CPU-Auslastung aus.

Zeitraum für die Untersuchung auswählen

Starten Sie die Prüfung mit der Suche nach einem Zeitpunkt, an dem Ihre Anwendung begann, eine hohe CPU-Auslastung zu verzeichnen. Beispiel: Das Problem trat am 24. Juli 2020 um 17:00 Uhr auf.

Abfragestatistiken für den ausgewählten Zeitraum erfassen

Nachdem ein Zeitraum zum Starten der Prüfung ausgewählt wurde, betrachten wir die Statistikdaten, die etwa zu diesem Zeitpunkt in der Tabelle QUERY_STATS_TOTAL_10MINUTE gesammelt wurden. Die Ergebnisse dieser Abfrage können darauf hinweisen, wie sich die CPU und andere Abfragestatistiken in diesem Zeitraum geändert haben.

Die folgende Abfrage gibt die zusammengefassten Abfragestatistiken von 16:30 bis einschließlich 17:30 UTC zurück. Wir verwenden ROUND in unserer Abfrage, um die Anzahl der Dezimalstellen für Anzeigezwecke einzuschränken.

SELECT interval_end,
       execution_count AS count,
       ROUND(avg_latency_seconds,2) AS latency,
       ROUND(avg_rows,2) AS rows_returned,
       ROUND(avg_bytes,2) AS bytes,
       ROUND(avg_rows_scanned,2) AS rows_scanned,
       ROUND(avg_cpu_seconds,3) AS avg_cpu
FROM spanner_sys.query_stats_total_10minute
WHERE
  interval_end >= "2020-07-24T16:30:00Z"
  AND interval_end <= "2020-07-24T17:30:00Z"
ORDER BY interval_end;

Die Abfrage liefert folgende Ergebnisse.

interval_end count Latenz rows_returned Byte rows_scanned avg_cpu
2020-07-24T16:30:00Z 6 0,06 5,00 536,00 16,67 0,035
2020-07-24T16:40:00Z 55 0,02 0.22 25,29 0.22 0,004
2020-07-24T16:50:00Z 102 0,02 0,30 33,35 0,30 0,004
2020-07-24T17:00:00Z 154 1.06 4.42 486.33 7792208.12 4.633
2020-07-24T17:10:00Z 94 0,02 1,68 106,84 1,68 0,006
2020-07-24T17:20:00Z 110 0,02 0,38 34,60 0,38 0,005
2020-07-24T17:30:00Z 47 0,02 0.23 24,96 0.23 0,004

In der vorherigen Tabelle sehen Sie, dass die durchschnittliche CPU-Zeit (die Spalte avg_cpu) in der Ergebnistabelle in den hervorgehobenen Intervallen um 17:00 Uhr am höchsten ist. Außerdem sehen wir eine durchschnittlich viel höhere Anzahl von Zeilen, die gescannt werden. Dies zeigt an, dass teurere Abfragen zwischen 16:50 und 17:00 Uhr ausgeführt wurden. Wir wählen dieses Intervall aus, um es im nächsten Schritt genauer zu untersuchen.

Abfragen ermitteln, die eine hohe CPU-Auslastung verursachen

Wir prüfen nun die ausgewählte Tabelle QUERY_STATS_TOP_10MINUTE mit einem Zeitintervall, um den ausgewählten Wert zu untersuchen. Die Ergebnisse dieser Abfrage können dabei helfen, zu erkennen, welche Abfragen eine hohe CPU-Auslastung verursachen.

SELECT text_fingerprint AS fingerprint,
       execution_count AS count,
       ROUND(avg_latency_seconds,2) AS latency,
       ROUND(avg_cpu_seconds,3) AS cpu,
       ROUND(execution_count * avg_cpu_seconds,3) AS total_cpu
FROM spanner_sys.query_stats_top_10MINUTE
WHERE
  interval_end = "2020-07-24T17:00:00Z"
ORDER BY total_cpu DESC;

Die Abfrage liefert folgende Ergebnisse.

Fingerprint count Latenz cpu total_cpu
5505124206529314852 30 3.88 17.635 529.039
1697951036096498470 10 4.49 18.388 183.882
2295109096748351518 1 0,33 0,048 0,048
11618299167612903606 1 0,25 0,021 0,021
10302798842433860499 1 0,04 0,006 0,006
123771704548746223 1 0,04 0,006 0,006
4216063638051261350 1 0,04 0,006 0,006
3654744714919476398 1 0,04 0,006 0,006
2999453161628434990 1 0,04 0,006 0,006
823179738756093706 1 0,02 0,005 0.0056

Die beiden wichtigsten Abfragen, die in der Ergebnistabelle hervorgehoben sind, sind Ausreißer in Bezug auf durchschnittliche CPU- und Latenz sowie Anzahl der Ausführungen und Gesamt-CPU. Sehen wir uns die erste Abfrage an, die in diesen Ergebnissen aufgeführt ist.

Abfrageausführungen im Zeitverlauf vergleichen

Nachdem wir die Untersuchung eingegrenzt haben, können wir uns der Tabelle QUERY_STATS_TOP_MINUTE widmen. Durch den Vergleich von Durchläufen für eine bestimmte Abfrage können wir nach Korrelationen zwischen der Anzahl der zurückgegebenen Zeilen oder Byte oder der Anzahl der gescannten und erhöhten CPUs oder Latenzen suchen. Eine Abweichung kann auf eine Ungleichförmigkeit in den Daten hinweisen. Eine konstant hohe Anzahl von gescannten Zeilen kann auf das Fehlen der entsprechenden Indexe oder der nicht optimalen Join-Reihenfolge hinweisen.

Wir untersuchen die Abfrage mit der höchsten durchschnittlichen CPU-Auslastung und der höchsten Latenz. Dazu führen Sie die folgende Anweisung aus, die nach dem text_fingerprint dieser Abfrage filtert.

SELECT interval_end,
       ROUND(avg_latency_seconds,2) AS latency,
       avg_rows AS rows_returned,
       avg_bytes AS bytes_returned,
       avg_rows_scanned AS rows_scanned,
       ROUND(avg_cpu_seconds,3) AS cpu,
FROM spanner_sys.query_stats_top_minute
WHERE text_fingerprint = 5505124206529314852
ORDER BY interval_end DESC;

Die Abfrage liefert folgende Ergebnisse.

interval_end Latenz rows_returned bytes_returned rows_scanned cpu
2020-07-24T17:00:00Z 4.55 21 2365 30000000 19.255
2020-07-24T16:00:00Z 3,62 21 2365 30000000 17,255
2020-07-24T15:00:00Z 4,37 21 2365 30000000 18,350
2020-07-24T14:00:00Z 4,02 21 2365 30000000 17,748
2020-07-24T13:00:00Z 3.12 21 2365 30000000 16,380
2020-07-24T12:00:00Z 3,45 21 2365 30000000 15,476
2020-07-24T11:00:00Z 4,94 21 2365 30000000 22,611
2020-07-24T10:00:00Z 6,48 21 2365 30000000 21,265
2020-07-24T09:00:00Z 0.23 21 2365 5 0,040
2020-07-24T08:00:00Z 0,04 21 2365 5 0,021
2020-07-24T07:00:00Z 0,09 21 2365 5 0,030

Bei der Untersuchung der vorhergehenden Ergebnisse sehen wir, dass sich die Anzahl der gescannten Zeilen, die verwendete CPU und die Latenz alle gegen 9:00 Uhr erheblich geändert haben. Um zu verstehen, warum diese Zahlen so drastisch angestiegen sind, untersuchen wir den Abfragetext und prüfen, ob sich Änderungen im Schema auf die Abfrage ausgewirkt haben könnten.

Verwenden Sie die folgende Abfrage, um den Abfragetext für die untersuchte Abfrage abzurufen.

SELECT text,
       text_truncated
FROM spanner_sys.query_stats_top_hour
WHERE text_fingerprint = 5505124206529314852
LIMIT 1;

Dies gibt das folgende Ergebnis zurück.

text text_truncated
select * aus Bestellungen mit o_custkey = 36901; false

Bei der Überprüfung des zurückgegebenen Abfragetexts sehen wir, dass die Abfrage nach einem Feld namens o_custkey filtert. Dies ist eine Nicht-Schlüsselspalte in der Tabelle orders. In diesem Fall war bis zu 9:00 Uhr ein Index für diese Spalte vorhanden. Dies erklärt die Änderung der Kosten für diese Abfrage. Wir können den Index wieder hinzufügen oder, wenn die Abfrage selten ausgeführt wird, entscheiden, dass wir den Index nicht haben und die höheren Lesekosten akzeptieren.

Unsere Untersuchung hat sich bisher auf Abfragen konzentriert, die erfolgreich abgeschlossen wurden, und wir haben einen Grund dafür gefunden, warum die Datenbank eine gewisse Beeinträchtigung der Leistung aufweist. Im nächsten Schritt konzentrieren wir uns auf fehlgeschlagene oder abgebrochene Abfragen und zeigen, wie Sie diese Daten untersuchen können, um weitere Informationen zu erhalten.

Fehlgeschlagene Abfragen untersuchen

Abfragen, die nicht erfolgreich abgeschlossen werden, verbrauchen weiterhin Ressourcen, bevor eine Zeitüberschreitung auftritt, werden abgebrochen oder anderweitig fehlschlagen. Spanner verfolgt die Anzahl der Ausführungen und die von fehlgeschlagenen Abfragen verbrauchten Ressourcen sowie erfolgreiche Abfragen.

Um zu prüfen, ob fehlgeschlagene Abfragen einen erheblichen Einfluss auf die Systemauslastung haben, können wir zuerst prüfen, wie viele Abfragen im gewünschten Zeitintervall fehlgeschlagen sind.

SELECT interval_end,
       all_failed_execution_count AS failed_count,
       all_failed_avg_latency_seconds AS latency
FROM spanner_sys.query_stats_total_minute
WHERE
  interval_end >= "2020-07-24T16:50:00Z"
  AND interval_end <= "2020-07-24T17:00:00Z"
ORDER BY interval_end;
interval_end failed_count Latenz
2020-07-24T16:52:00Z 1 15,211391
2020-07-24T16:53:00Z 3 58,312232

Wir können weiter untersuchen, indem wir nach Abfragen suchen, die mit der folgenden Abfrage am wahrscheinlichsten fehlschlagen.

SELECT interval_end,
       text_fingerprint,
       execution_count,
       avg_latency_seconds AS avg_latency,
       all_failed_execution_count AS failed_count,
       all_failed_avg_latency_seconds AS failed_latency,
       cancelled_or_disconnected_execution_count AS cancel_count,
       timed_out_execution_count AS to_count
FROM spanner_sys.query_stats_top_minute
WHERE all_failed_execution_count > 0
ORDER BY interval_end;
interval_end text_fingerprint execution_count failed_count cancel_count to_count
2020-07-24T16:52:00Z 5505124206529314852 3 1 1 0
2020-07-24T16:53:00Z 1697951036096498470 2 1 1 0
2020-07-24T16:53:00Z 5505124206529314852 5 2 1 1

Wie die vorherige Tabelle zeigt, ist die Abfrage mit dem Fingerabdruck 5505124206529314852 in verschiedenen Zeitintervallen mehrmals fehlgeschlagen. Angesichts eines solchen Ausfallmusters ist es interessant, die Latenz erfolgreicher und fehlgeschlagener Ausführungen zu vergleichen.

SELECT interval_end,
       avg_latency_seconds AS combined_avg_latency,
       all_failed_avg_latency_seconds AS failed_execution_latency,
       ( avg_latency_seconds * execution_count -
         all_failed_avg_latency_seconds * all_failed_execution_count
       ) / (
       execution_count - all_failed_execution_count ) AS success_execution_latency
FROM   spanner_sys.query_stats_top_hour
WHERE  text_fingerprint = 5505124206529314852;
interval_end combined_avg_latency failed_execution_latency success_execution_latency
2020-07-24T17:00:00Z 3,880420 13,830709 2,774832

Best Practices anwenden

Nachdem wir eine Kandidatenabfrage zur Optimierung ermittelt haben, können wir als Nächstes das Abfrageprofil betrachten und versuchen, eine Optimierung mit Best Practices für SQL durchzuführen.

Nächste Schritte