Lebensdauer einer Cloud Spanner-Abfrage

Client

Cloud Spanner unterstützt SQL-Abfragen. Hier eine Beispielabfrage:

SELECT s.SingerId, s.FirstName, s.LastName, s.SingerInfo
FROM Singers AS s
WHERE s.FirstName = @firstName;

Die Formulierung @firstName ist ein Verweis auf einen Abfrageparameter. Sie können einen Abfrageparameter überall verwenden, wo ein Literalwert verwendet werden kann. Es wird dringend empfohlen, Parameter in programmatischen APIs zu verwenden. Die Verwendung von Abfrageparametern hilft, SQL-Injection-Angriffe zu vermeiden. Die daraus resultierenden Abfragen werden eher von verschiedenen serverseitigen Caches profitieren. Siehe Caching unten.

Abfrageparameter müssen auf einen Wert begrenzt werden, wenn die Abfrage ausgeführt wird. Beispiel:

Statement statement =
    Statement.newBuilder("SELECT s.SingerId...").bind("firstName").to("Jimi").build();
try (ResultSet resultSet = dbClient.singleUse().executeQuery(statement)) {
 while (resultSet.next()) {
 ...
 }
}

Sobald Cloud Spanner-API einen Aufruf startet, analysiert es die Abfrage und Grenzparameter, um festzustellen, welcher Cloud Spanner-Serverknoten die Abfrage bearbeiten soll. Der Server sendet einen Stream von Ergebniszeilen zurück, die von den Aufrufen an ResultSet.next() genutzt werden.

Abfrage ausführen

Die Abfrageausführung beginnt mit dem Eintreffen der Anfrage "Abfrage ausführen" auf einem beliebigen Cloud Spanner-Server. Der Server führt die folgenden Schritte aus:

  • Die Anfrage validieren
  • Den Text der Suchanfrage parsen
  • Eine erste Abfragealgebra generieren
  • Eine optimierte Abfragealgebra generieren
  • Einen ausführbaren Abfrageplan generieren
  • Den Plan ausführen (Berechtigungen überprüfen, Daten lesen, Ergebnisse codieren usw.)

Flussdiagramm Abfrageverarbeitung, das die Client-, Stamm- und Blattserver darstellt

Parsen

Der SQL-Parser analysiert den Abfragetext und wandelt ihn in eine abstrakte Syntaxstruktur um. Es extrahiert die grundlegende Abfragestruktur (SELECT … FROM … WHERE …) und führt syntaktische Prüfungen durch.

Algebra

Das Cloud Spanner-Typsystem kann Skalare, Arrays, Strukturen usw. darstellen. Die Abfragealgebra definiert Vorgänge für Tabellenscans, das Filtern, Sortieren/Gruppieren, verschiedene Verknüpfungen, Aggregation und vieles mehr. Die ursprüngliche Abfragealgebra besteht aus der Ausgabe des Parsers. Feldnamenreferenzen in der Strukturansicht werden mit dem Datenbankschema gelöst. Dieser Code überprüft auch auf semantische Fehler (z. B. falsche Anzahl von Parametern, nicht übereinstimmende Typen usw.).

Der nächste Schritt ("Abfrageoptimierung") geht von der ersten Algebra aus und erzeugt eine optimalere Algebra. Diese kann einfacher, effizienter oder einfach besser an die Fähigkeiten der Ausführungsengine angepasst sein. Beispielsweise könnte die erste Algebra nur "Join" angeben, wobei die optimierte Algebra "Hash Join" angibt.

Ausführung

Der endgültige ausführbare Abfrageplan wird aus der neu geschriebenen Algebra erstellt. Im Grunde ist der ausführbare Plan eine gerichtete azyklische Grafik von "Iteratoren". Jeder Iterator enthält eine Wertesequenz. Iteratoren verbrauchen eventuell Eingaben, um Ausgaben zu generieren (z. B. Iterator sortieren). Abfragen mit einem einzelnen Split können von einem einzelnen Server ausgeführt werden (von dem, der die Daten enthält). Der Server scannt Bereiche verschiedener Tabellen und führt Joins, Aggregationen und alle anderen von der Abfragealgebra definierten Vorgänge aus.

Abfragen mit mehreren Splits werden in mehrere Teile einbezogen. Ein Teil der Abfrage wird weiterhin auf dem Hauptserver (Stammserver) ausgeführt. Andere partielle Unterabfragen werden an Blattknoten übergeben (die Inhaber der Splits, die gelesen werden). Diese Übergabe kann für komplexe Abfragen rekursiv angewendet werden, was zu einer Baumstruktur von Serverausführungen führt. Alle Server vereinbaren einen Zeitstempel, damit die Abfrageergebnisse ein konsistenter Snapshot der Daten sind. Jeder Blattserver gibt einen Stream von Teilergebnissen zurück. Bei Abfragen mit Aggregation können dies partiell aggregierte Ergebnisse sein. Der Abfrage-Stammserver verarbeitet die Ergebnisse von den Blatt-Servern und führt den Rest des Abfrageplans aus. Weitere Informationen dazu finden Sie hier.

Caching

Viele Artefakte der Abfrageverarbeitung werden automatisch im Cache gespeichert und noch einmal für alle nachfolgenden Abfragen verwendet. Dazu gehören Abfragealgebren, ausführbare Abfragepläne usw. Das Caching basiert auf dem Abfragetext, den Namen und Typen der gebundenen Parameter und so weiter. Aus diesem Grund ist die Verwendung von gebundenen Parametern wie @firstName im obigen Beispiel besser als die Verwendung von Literalwerten im Abfragetext. Erstere können einmal im Cache gespeichert werden und unabhängig vom tatsächlichen Grenzwert wiederverwendet werden. Weitere Informationen finden Sie unter Optimieren der Cloud Spanner-Abfrageleistung.

Fehlerbehebung

Verschiedene Gründe können für eine Unterbrechung des Streams von Ergebniszeilen aus der Methode executeQuery verantwortlich sein: vorübergehende Netzwerkfehler, Übergabe eines Splits an einen anderen Server (z. B. Load-Balancing), Serverneustarts (z. B. Upgrade auf eine neue Version). Zur Behebung dieser Fehler sendet Cloud Spanner intransparente "Fortfahren-Tokens" und Batches partieller Ergebnisdaten. Diese Fortfahren-Tokens können bei der Wiederholung der Abfrage verwendet werden, um an der Stelle fortzufahren, an der die unterbrochene Abfrage abgebrochen wurde. Wenn Sie die Cloud Spanner-Clientbibliotheken verwenden, geschieht dies automatisch. Nutzer der Clientbibliothek müssen sich daher nicht mit solchen vorübergehenden Fehlern befassen.