Best Practices für SQL

Wie in Abfrageausführungsplänen beschrieben, kann der SQL-Compiler eine SQL-Anweisung in einen Abfrageausführungsplan um, um die Ergebnisse der Abfrage zu erhalten. Auf dieser Seite werden Best Practices für SQL-Anweisungen erstellen, um Spanner dabei zu helfen, eine effiziente Ausführung zu finden Pläne.

Für die auf dieser Seite gezeigten SQL-Beispielanweisungen wird das folgende Beispielschema verwendet:

GoogleSQL

CREATE TABLE Singers (
 SingerId   INT64 NOT NULL,
 FirstName  STRING(1024),
 LastName   STRING(1024),
 SingerInfo BYTES(MAX),
 BirthDate  DATE
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
 SingerId     INT64 NOT NULL,
 AlbumId      INT64 NOT NULL,
 AlbumTitle   STRING(MAX),
 ReleaseDate  DATE
) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

Die vollständige SQL-Referenz finden Sie unter Anweisungssyntax, Funktionen und Operatoren und Lexikalische Struktur und Syntax.

PostgreSQL

CREATE TABLE Singers (
 SingerId   BIGINT PRIMARY KEY,
 FirstName  VARCHAR(1024),
 LastName   VARCHAR(1024),
 SingerInfo BYTEA,
 BirthDate  TIMESTAMPTZ
);

CREATE TABLE Albums (
 SingerId        BIGINT NOT NULL,
 AlbumId         BIGINT NOT NULL,
 AlbumTitle      VARCHAR(1024),
 ReleaseDate     DATE,
 PRIMARY KEY(SingerId, AlbumId),
 FOREIGN KEY (SingerId) REFERENCES Singers(SingerId)
) INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

Weitere Informationen finden Sie unter Die PostgreSQL-Sprache in Spanner

Abfrageparameter verwenden

Spanner unterstützt Abfrageparameter, um die Leistung zu steigern und Hilfe zu erhalten SQL-Injection zu verhindern, wenn Abfragen über Nutzereingaben erstellt werden. Sie können Abfrageparameter als Ersatz für beliebige Ausdrücke verwenden, aber nicht als für Kennzeichnungen, Spaltennamen, Tabellennamen oder andere Teile des Abfrage.

Parameter können überall dort vorkommen, wo ein Literalwert erwartet wird. Das Gleiche Parametername kann mehr als einmal in einer einzelnen SQL-Anweisung verwendet werden.

Zusammenfassend lässt sich sagen, dass Suchparameter die Ausführung von Abfragen auf folgende Arten unterstützen:

  • Voroptimierte Pläne: Abfragen, die Parameter verwenden, können auf jeden Aufruf, da die Parametrisierung die Spanner, um den Ausführungsplan im Cache zu speichern.
  • Vereinfachte Abfragezusammensetzung: Sie müssen Stringwerte nicht mit einem Escapezeichen versehen, wenn wenn Sie diese in Abfrageparametern angeben. Abfrageparameter verringern auch das Risiko von Syntaxfehlern.
  • Sicherheit: Abfrageparameter machen Ihre Abfragen sicherer, da sie Sie schützen SQL-Injection-Angriffen zu schützen. Dieser Schutz ist besonders wichtig für Abfragen, die Sie aus Nutzereingaben erstellen.

So führt Spanner Abfragen aus

Mit Spanner können Sie Datenbanken mithilfe von deklarativen SQL-Anweisungen abfragen die angeben, welche Daten Sie abrufen möchten. Wenn Sie wissen möchten, Spanner erhält die Ergebnisse. Prüfen Sie den Ausführungsplan für die Abfrage. A Abfrageausführungsplan zeigt die mit jedem Schritt verbundenen Berechnungskosten an der Abfrage. Mit diesen Kosten können Sie Leistungsprobleme bei Abfragen beheben und Ihre Abfrage optimieren. Weitere Informationen finden Sie unter Abfrageausführungspläne.

Abfrageausführungspläne können über die Google Cloud Console oder Clientbibliotheken

So rufen Sie über die Google Cloud Console einen Abfrageausführungsplan für eine bestimmte Abfrage ab: führen Sie folgende Schritte aus:

  1. Öffnen Sie die Seite mit den Spanner-Instanzen.

    Spanner-Instanzen aufrufen

  2. Wählen Sie die Namen der Spanner-Instanz und der Datenbank aus, die Sie abfragen möchten.

  3. Klicken Sie im linken Navigationsbereich auf Spanner Studio.

  4. Geben Sie die Abfrage in das Textfeld ein und klicken Sie auf Abfrage ausführen.

  5. Klicken Sie auf Erläuterung
    . In der Google Cloud Console wird ein visuelles Element Ausführungsplan für Ihre Abfrage.

    Screenshot des visuellen Ausführungsplans in der Cloud Console

Weitere Informationen zum Verständnis visueller Pläne und deren Verwendung zur Fehlerbehebung Siehe Abfragen mit dem Abfrageplan-Visualizer abstimmen.

Sie können sich auch Beispiele für bisherige Abfragepläne ansehen und die Leistung vergleichen für bestimmte Abfragen im Zeitverlauf. Weitere Informationen finden Sie unter Stichprobenabfragepläne:

Sekundäre Indexe verwenden

Wie andere relationale Datenbanken bietet Spanner sekundäre Indexe, die können Sie Daten mithilfe einer SQL-Anweisung oder Leseschnittstelle von Spanner. Die gebräuchlichere Methode zum Abrufen von Daten aus einem ist die Verwendung von Spanner Studio. Sekundären Index in einer SQL-Abfrage verwenden können Sie angeben, wie Spanner die Ergebnisse erhalten soll. Das Angeben eines sekundären Index kann die Ausführung von Abfragen beschleunigen.

Angenommen, Sie möchten die IDs aller Sänger mit einem Nachname angegeben haben. Hier ist eine Möglichkeit, eine solche SQL-Abfrage zu schreiben:

SELECT s.SingerId
FROM Singers AS s
WHERE s.LastName = 'Smith';

Diese Abfrage würde die erwarteten Ergebnisse zurückgeben. Es kann jedoch lange dauern. Die Dauer hängt von der Anzahl der Zeilen in der Tabelle Singers ab und davon, wie viele das Prädikat WHERE s.LastName = 'Smith' erfüllen. Wenn es keinen sekundären Index gibt, der die Spalte LastName enthält, aus der gelesen werden soll, liest der Abfrageplan die gesamte Tabelle Singers, um Zeilen zu finden, die mit dem Prädikat übereinstimmen. Wenn Sie den gesamten wird als vollständiger Tabellenscan bezeichnet. Ein Scan der gesamten Tabelle ist teuer erhalten, wenn die Tabelle nur einen kleinen Prozentsatz Singers mit diesem Nachnamen.

Sie können die Leistung dieser Abfrage verbessern, wenn Sie einen sekundären Index für die Nachname-Spalte definieren:

CREATE INDEX SingersByLastName ON Singers (LastName);

Weil der sekundäre Index SingersByLastName die indexierte Tabelle enthält LastName und die Primärschlüsselspalte SingerId hat, kann Spanner alle Daten aus der viel kleineren Indextabelle abzurufen, vollständige Singers-Tabelle.

In diesem Szenario verwendet Spanner automatisch die sekundäre SingersByLastName beim Ausführen der Abfrage indexieren (solange drei Tage seit der Datenbankerstellung vergangen sind; Siehe Hinweis zu neuen Datenbanken). Es ist jedoch am besten, explizit Spanner anweisen, diesen Index zu verwenden, indem Sie einer Indexanweisung in der FROM-Klausel:

GoogleSQL

SELECT s.SingerId
FROM Singers@{FORCE_INDEX=SingersByLastName} AS s
WHERE s.LastName = 'Smith';

PostgreSQL

 SELECT s.SingerId
FROM Singers /*@ FORCE_INDEX=SingersByLastName */ AS s
WHERE s.LastName = 'Smith';

Beispiel: Sie wollten neben der ID auch den Vornamen des Sängers abrufen. Auch wenn die Spalte FirstName nicht im Index enthalten ist, sollten Sie die Indexanweisung wie zuvor angeben:

GoogleSQL

SELECT s.SingerId, s.FirstName
FROM Singers@{FORCE_INDEX=SingersByLastName} AS s
WHERE s.LastName = 'Smith';

PostgreSQL

SELECT s.SingerId, s.FirstName
FROM Singers /*@ FORCE_INDEX=SingersByLastName */ AS s
WHERE s.LastName = 'Smith';

Sie profitieren dennoch von der Verwendung des Index, da Spanner muss beim Ausführen des Abfrageplans keinen vollständigen Tabellenscan ausführen. Stattdessen werden sie Wählt die Teilmenge der Zeilen aus, die das Prädikat aus SingersByLastName erfüllen und führt dann eine Suche aus der Basistabelle Singers durch, um die erste für diese Teilmenge der Zeilen.

Wenn Spanner keine Zeilen aus der Basis abrufen muss überhaupt nicht, können Sie eine Kopie der Spalte FirstName im den Index selbst:

GoogleSQL

CREATE INDEX SingersByLastName ON Singers (LastName) STORING (FirstName);

PostgreSQL

CREATE INDEX SingersByLastName ON Singers (LastName) INCLUDE (FirstName);

Mit einer STORING-Klausel (für den GoogleSQL-Dialekt) oder einer INCLUDE-Klausel (für den PostgreSQL-Dialekt) wie dieser zusätzliche Speicher, bietet folgende Vorteile:

  • SQL-Abfragen, die den Index verwenden und Spalten auswählen, die in STORING oder INCLUDE-Klausel erfordert keine zusätzliche Verknüpfung mit der Basistabelle.
  • Leseaufrufe, die den Index verwenden, können Spalten lesen, die im STORING oder INCLUDE-Klausel angegeben werden.

Die Beispiele oben zeigen, wie sekundäre Indexe Abfragen beschleunigen können, wenn die von der WHERE-Klausel einer Abfrage ausgewählten Zeilen mit dem sekundären Index schnell identifiziert werden können.

Ein weiteres Szenario, in dem sekundäre Indexe Leistungsvorteile bieten können, sind bestimmte Abfragen, die geordnete Ergebnisse zurückgeben. Für Angenommen, Sie möchten alle Albumtitel und deren Veröffentlichungsdaten abrufen. in aufsteigender Reihenfolge nach Veröffentlichungsdatum und absteigender Reihenfolge nach Albumtiteln. Eine SQL-Abfrage könnte zum Beispiel so geschrieben werden:

SELECT a.AlbumTitle, a.ReleaseDate
FROM Albums AS a
ORDER BY a.ReleaseDate, a.AlbumTitle DESC;

Ohne einen sekundären Index erfordert diese Abfrage möglicherweise einen teuren Sortierschritt im Ausführungsplan. Sie können die Abfrageausführung beschleunigen, wenn Sie diesen sekundären Index definieren:

CREATE INDEX AlbumsByReleaseDateTitleDesc on Albums (ReleaseDate, AlbumTitle DESC);

Schreiben Sie dann die Abfrage um, um den sekundären Index zu verwenden:

GoogleSQL

SELECT a.AlbumTitle, a.ReleaseDate
FROM Albums@{FORCE_INDEX=AlbumsByReleaseDateTitleDesc} AS a
ORDER BY a.ReleaseDate, a.AlbumTitle DESC;

PostgreSQL

SELECT a.AlbumTitle, a.ReleaseDate
FROM Albums /*@ FORCE_INDEX=AlbumsByReleaseDateTitleDesc */ AS s
ORDER BY a.ReleaseDate, a.AlbumTitle DESC;

Diese Abfrage und diese Indexdefinition erfüllen die beiden folgenden Kriterien:

  • Wenn Sie den Sortierschritt entfernen möchten, muss die Spaltenliste im ORDER BY ist ein Präfix der Indexschlüsselliste.
  • Um eine Verbindung aus der Basistabelle zu vermeiden, um fehlende Spalten abzurufen, dass der Index alle Spalten in der Tabelle abdeckt, die von der Abfrage verwendet werden.

Obwohl sekundäre Indizes häufige Abfragen beschleunigen können, sekundäre Indexe können die Latenz Ihrer Commit-Vorgänge erhöhen, da jeder Index Für den sekundären Index muss in der Regel bei jedem Commit ein zusätzlicher Knoten verwendet werden. Bei den meisten Arbeitslasten ist es ausreichend, einige wenige sekundäre Indizes zu haben. Sie sollten jedoch überlegen, ob Ihnen Leselatenz oder Schreiblatenz wichtiger ist und welche Vorgänge für Ihre Arbeitslast am wichtigsten sind. Benchmarking durchführen um sicherzustellen, dass sie erwartungsgemäß funktioniert.

Die vollständige Referenz zu sekundären Indexen finden Sie unter Sekundäre Indexe.

Scans optimieren

Bestimmte Spanner-Abfragen könnten von der Verwendung eines Batch-orientierten beim Scannen von Daten statt mit der gebräuchlicheren zeilenorientierten Datenverarbeitungsmethode. Die Batchverarbeitung von Scans ist eine effizientere Methode, gleichzeitig große Datenmengen verarbeiten und Abfragen können eine geringere CPU-Auslastung und eine geringere Latenz.

Der Spanner-Scanvorgang startet immer die Ausführung in zeilenorientierten Modus. Während dieser Zeit erfasst Spanner mehrere Laufzeitmesswerten. Dann wendet Spanner eine Reihe von heuristikbasierten anhand des Ergebnisses dieser Messwerte, um den optimalen Scanmodus zu ermitteln. Wann? wechselt Spanner in einen Batch-orientierten Verarbeitungsmodus, um Durchsatz und Leistung von Scans zu verbessern.

Gängige Anwendungsfälle

Abfragen mit den folgenden Eigenschaften profitieren im Allgemeinen von der Verwendung von Batch-orientierte Verarbeitung:

  • Große Scans von selten aktualisierten Daten.
  • Scannt mit Prädikaten für Spalten mit fester Breite.
  • Scans mit vielen Suchläufen. Bei einer Suche wird ein Index zum Abrufen von Datensätzen verwendet.

Anwendungsfälle ohne Leistungssteigerungen

Nicht alle Abfragen profitieren von einer Batch-orientierten Verarbeitung. Mit der folgenden Abfrage -Typen funktionieren bei der zeilenorientierten Scanverarbeitung besser:

  • Punktsuchabfragen: Abfragen, die nur eine Zeile abrufen.
  • Kleine Scanabfragen: Tabellenscans, die nur wenige Zeilen scannen, es sei denn, sie haben hohe Suchzahlen.
  • Abfragen, die LIMIT verwenden.
  • Abfragen, die Daten mit hoher Abwanderung lesen: Abfragen, bei denen mehr als ~10% der die gelesenen Daten regelmäßig aktualisiert werden.
  • Abfragen mit Zeilen, die große Werte enthalten: Zeilen mit großen Werten sind solche mit Werten,die größer als 32.000 Byte sind (Vorkomprimierung) in einem einzigen Spalte.

Von einer Abfrage verwendete Scanmethode prüfen

Um zu überprüfen, ob Ihre Abfrage batch- oder zeilenorientierte Verarbeitung oder zwischen den beiden Scanmethoden wechselt:

  1. Rufen Sie in der Google Cloud Console die Seite Spanner-Instanzen auf.

    Zur Seite "VM-Instanzen"

  2. Klicken Sie auf den Namen der Instanz mit der Abfrage, die Sie untersuchen möchten.

  3. Klicken Sie unter der Tabelle „Datenbanken“ auf die Datenbank mit der Abfrage, die Sie verwenden möchten. zu untersuchen.

  4. Klicken Sie im Navigationsmenü auf Spanner Studio.

  5. Neuen Tab durch Klicken auf öffnen Neuer SQL-Editor-Tab oder Neuer Tab:

  6. Wenn der Abfrageeditor angezeigt wird, geben Sie Ihre Abfrage ein.

  7. Klicken Sie auf Ausführen.

    Spanner führt die Abfrage aus und zeigt die Ergebnisse an.

  8. Klicken Sie unter dem Abfrageeditor auf den Tab Erläuterung.

    Spanner zeigt eine Visualisierung des Ausführungsplans eines Abfrageplans. Jede Karte im Diagramm steht für einen Iterator.

  9. Klicken Sie auf die Iteratorkarte Table scan (Tabellenscan), um einen Informationsbereich zu öffnen.

    Im Infobereich werden Kontextinformationen angezeigt. über den ausgewählten Scan. Die Scanmethode wird auf dieser Karte angezeigt. Automatisch bedeutet, dass Spanner den Scanvorgang festlegt. . Weitere mögliche Werte sind Vectorized für Batch-orientierte Werte. und Scalar für die zeilenorientierte Verarbeitung.

    Screenshot einer Tabelle zum Scannen einer Tabelle mit der Scanmethode „Automatisch“

Von einer Abfrage verwendete Scanmethode erzwingen

Zur Optimierung der Abfrageleistung wählt Spanner den optimalen Scan aus -Methode für Ihre Abfrage hinzu. Wir empfehlen, diese Standardscanmethode zu verwenden. Es kann jedoch Szenarien geben, in denen Sie eine bestimmte Art der Scanmethode.

Batchorientiertes Scannen erzwingen

Sie können Batch-orientiertes Scannen auf Tabellen- und Anweisungsebene erzwingen.

Verwenden Sie einen Tabellenhinweis, um die Batch-orientierte Scanmethode auf Tabellenebene zu erzwingen in Ihrer Abfrage:

GoogleSQL

  SELECT ...
  FROM (t1@{SCAN_METHOD=BATCH} JOIN t2 ON ...)
  WHERE ...

PostgreSQL

  SELECT ...
  FROM (t1/*@ scan_method=batch */ JOIN t2 on ...)
  WHERE ...

Um die Batch-orientierte Scanmethode auf Anweisungsebene zu erzwingen, verwenden Sie eine Anweisung hinzufügen:

GoogleSQL

  @{SCAN_METHOD=BATCH}
  SELECT ...
  FROM ...
  WHERE ...

PostgreSQL

  /*@ scan_method=batch */
  SELECT ...
  FROM ...
  WHERE ...

So deaktivieren Sie das automatische Scannen und erzwingen das zeilenorientierte Scannen

Auch wenn wir nicht raten, die automatische Auswahlmethode zu deaktivieren, können Sie das Tool deaktivieren und die Methode zeilenorientierte Auswahlmethode zur Fehlerbehebung, z. B. für die Diagnose Latenz.

Um die automatische Scanmethode zu deaktivieren und die Zeilenverarbeitung in der Tabelle zu erzwingen Ebene verwenden, verwenden Sie einen Tabellenhinweis in Ihrer Abfrage:

GoogleSQL

  SELECT ...
  FROM (t1@{SCAN_METHOD=ROW} JOIN t2 ON ...)
  WHERE ...

PostgreSQL

  SELECT ...
  FROM (t1/*@ scan_method=row */ JOIN t2 on ...)
  WHERE ...

Um die automatische Scanmethode zu deaktivieren und die Zeilenverarbeitung in der Anweisung zu erzwingen Ebene verwenden, verwenden Sie einen Anweisungshinweis in Ihrer Abfrage:

GoogleSQL

  @{SCAN_METHOD=ROW}
  SELECT ...
  FROM ...
  WHERE ...

PostgreSQL

  /*@ scan_method=row */
  SELECT ...
  FROM ...
  WHERE ...

Bereichsschlüsselsuchen optimieren

Eine häufige Verwendung einer SQL-Abfrage ist das Lesen mehrerer Zeilen aus Spanner-basierten bekannten Schlüsseln stehen.

Die folgenden Best Practices helfen Ihnen beim Schreiben effizienter Abfragen beim Abrufen von Daten mit einem Schlüsselbereich:

  • Wenn die Liste der Schlüssel kurz ist und keine benachbarten Schlüssel enthält, verwenden Sie Abfrageparameter und UNNEST zur Erstellung der Abfrage.

    Wenn die Schlüsselliste beispielsweise {1, 5, 1000} lautet, schreiben Sie die Abfrage so:

    GoogleSQL

    SELECT *
    FROM Table AS t
    WHERE t.Key IN UNNEST (@KeyList)
    

    PostgreSQL

    SELECT *
    FROM Table AS t
    WHERE t.Key IN UNNEST ($1)
    

    Hinweise:

    • Der Operator Array UNNEST vereinfacht ein Eingabe-Array so, dass es in Zeilen von Elementen vorliegt.

    • Der Abfrageparameter @KeyList für GoogleSQL und $1 für PostgreSQL, kann Ihre Abfrage beschleunigen, wie in den vorherigen Best Practice.

  • Wenn die Liste der Schlüssel benachbarte Schlüssel enthält und innerhalb eines Bereichs liegt, geben Sie die untere und Höhere Grenzwerte des Schlüsselbereichs in der WHERE-Klausel.

    Wenn die Schlüsselliste beispielsweise {1,2,3,4,5} lautet, erstellen Sie die Abfrage so: folgt:

    GoogleSQL

    SELECT *
    FROM Table AS t
    WHERE t.Key BETWEEN @min AND @max
    

    PostgreSQL

    SELECT *
    FROM Table AS t
    WHERE t.Key BETWEEN $1 AND $2
    

    Diese Abfrage ist nur effizienter, wenn die Schlüssel im Schlüsselbereich nebeneinander. Mit anderen Worten: Wenn Ihre Schlüsselliste {1, 5, 1000} ist, wie in der vorherigen Abfrage die Unter- und Obergrenze angeben, würde jeder Wert zwischen 1 und 1000 durchgehen.

Optimize-Verknüpfungen

Join-Vorgänge können teuer sein, da sie Anzahl der Zeilen erhöhen, die Ihre Abfrage scannen muss, was zu langsamere Abfragen ausführen. Neben den Techniken, die Sie üblicherweise in anderen relationalen Datenbanken nutzen können, um Join-Abfragen zu optimieren. Praktiken für einen effizienteren JOIN bei der Verwendung von Spanner SQL:

  • Verbinden Sie nach Möglichkeit Daten in verschränkten Tabellen mit dem Primärschlüssel. Beispiel:

    SELECT s.FirstName, a.ReleaseDate
    FROM Singers AS s JOIN Albums AS a ON s.SingerId = a.SingerId;
    

    Die Zeilen in der verschränkten Tabelle Albums werden in denselben Splits wie die übergeordnete Zeile in Singers gespeichert, wie in Schema und Datenmodell erläutert. Joins können daher ohne große Datenmengen über das Netzwerk zu senden.

  • Verwenden Sie die Join-Anweisung, wenn Sie die Reihenfolge des Join erzwingen möchten. Beispiel:

    GoogleSQL

    SELECT *
    FROM Singers AS s JOIN@{FORCE_JOIN_ORDER=TRUE} Albums AS a
    ON s.SingerId = a.Singerid
    WHERE s.LastName LIKE '%x%' AND a.AlbumTitle LIKE '%love%';
    

    PostgreSQL

    SELECT *
    FROM Singers AS s JOIN/*@ FORCE_JOIN_ORDER=TRUE */ Albums AS a
    ON s.SingerId = a.Singerid
    WHERE s.LastName LIKE '%x%' AND a.AlbumTitle LIKE '%love%';
    

    Die Join-Anweisung FORCE_JOIN_ORDER weist Spanner an, die Die in der Abfrage angegebene Join-Reihenfolge (d. h. Singers JOIN Albums, nicht Albums JOIN Singers). Die zurückgegebenen Ergebnisse sind unabhängig von Reihenfolge, die Spanner auswählt. Sie können diesen Join jedoch wenn Sie im Abfrageplan feststellen, dass Spanner geändert wurde, und unerwünschte Folgen verursacht hat, wie etwa oder verpasste Möglichkeiten für die Suche in Zeilen.

  • Wählen Sie mit einer Join-Anweisung eine Join-Implementierung aus. Wenn Sie mit SQL Abfrage mehrerer Tabellen abfragen, verwendet Spanner automatisch eine Join-Methode wird die Abfrage wahrscheinlich effizienter. Google empfiehlt jedoch, mit verschiedenen Join-Algorithmen zu testen. Wenn Sie den richtigen Join-Algorithmus auswählen, können Latenz, Speicherverbrauch oder beides verbessert werden. Diese Abfrage zeigt die Syntax für die Verwendung einer JOIN-Anweisung mit dem Hinweis JOIN_METHOD zur Auswahl HASH JOIN:

    GoogleSQL

    SELECT *
    FROM Singers s JOIN@{JOIN_METHOD=HASH_JOIN} Albums AS a
    ON a.SingerId = a.SingerId
    

    PostgreSQL

    SELECT *
    FROM Singers s JOIN/*@ JOIN_METHOD=HASH_JOIN */ Albums AS a
    ON a.SingerId = a.SingerId
    
  • Wenn Sie eine HASH JOIN oder APPLY JOIN verwenden und eine WHERE haben die auf einer Seite der JOIN hochselektiv ist, die die kleinste Anzahl von Zeilen als erste Tabelle im FROM erzeugt. der JOIN-Anweisung. Diese Struktur ist hilfreich, weil Sie derzeit in HASH JOIN Spanner wählt immer die linke Tabelle als Build in der rechten Tabelle als Sonde. Ähnlich verhält es sich mit Spanner für APPLY JOIN: wählt die linke Tabelle als äußere und die rechte Tabelle als inneren Zustand. Weitere Informationen zu diesen Join-Typen finden Sie unter Hash Join und Join anwenden.

  • Geben Sie für Abfragen, die für Ihre Arbeitslast kritisch sind, die leistungsstärkste an Join-Methode und Join-Reihenfolge in Ihren SQL-Anweisungen, um eine einheitlichere die Leistung.

Große Lesevorgänge in Lese-Schreib-Transaktionen vermeiden

Lese-Schreib-Transaktionen ermöglichen eine Sequenz von null oder mehr Lesevorgängen oder SQL-Abfragen und können eine Reihe von Mutationen vor einem Aufruf zum Commit enthalten. Um die Konsistenz Ihrer Daten zu wahren, erhält Sperren beim Lesen und Schreiben von Zeilen in Ihren Tabellen und Indexen. Für Weitere Informationen zum Sperren finden Sie unter Lebensdauer von Lese- und Schreibvorgängen.

Aufgrund der Funktionsweise von Sperren in Spanner Abfrage, die eine große Anzahl von Zeilen liest (z. B. SELECT * FROM Singers) bedeutet, dass keine anderen Transaktionen in die Zeilen schreiben können, die Sie gelesen haben, Ihre Transaktion wurde entweder festgeschrieben oder abgebrochen.

Da Ihre Transaktion eine große Anzahl von Zeilen verarbeitet, länger dauern als eine Transaktion, die einen viel kleineren Bereich von Zeilen liest (z. B. SELECT LastName FROM Singers WHERE SingerId = 7), die weiter verschlimmert das Problem und verringert den Systemdurchsatz.

Vermeiden Sie daher große Lesevorgänge (z. B. vollständige Tabellenscans oder massive Joins). Vorgänge) in Ihren Transaktionen, es sei denn, Sie sind bereit, niedrigere Schreibvorgänge Durchsatz.

In einigen Fällen kann das folgende Muster bessere Ergebnisse liefern:

  1. Führen Sie Ihre großen Lesevorgänge in einer schreibgeschützten Transaktion aus. Schreibgeschützte Transaktionen ermöglichen einen höheren Gesamtdurchsatz, keine Schlösser verwenden.
  2. Optional: Führen Sie eine Verarbeitung der gerade gelesenen Daten durch.
  3. Starten Sie eine Lese-Schreib-Transaktion.
  4. Achten Sie darauf, dass sich die Werte der kritischen Zeilen nicht geändert haben, seit Sie die der schreibgeschützten Transaktion in Schritt 1.
    • Wenn sich die Zeilen geändert haben, führen Sie einen Rollback der Transaktion durch und beginnen Sie noch einmal bei Schritt 1.
    • Wenn alles in Ordnung ist, können Sie einen Commit Ihrer Mutationen durchführen.

Eine Möglichkeit, um große Lesevorgänge in Lese-/Schreibvorgängen zu vermeiden Transaktionen besteht darin, sich die Ausführungspläne anzusehen, die Ihre Abfragen generieren.

Verwenden Sie ORDER BY, um die Reihenfolge Ihrer SQL-Ergebnisse sicherzustellen

Wenn Sie eine bestimmte Reihenfolge für die Ergebnisse einer SELECT-Abfrage erwarten, die ORDER BY-Klausel explizit einschließen. Wenn Sie zum Beispiel alle Sänger in Primärschlüsselreihenfolge auflisten, verwenden Sie diese Abfrage:

SELECT * FROM Singers
ORDER BY SingerId;

Spanner garantiert nur dann die Ergebnissortierung, wenn die ORDER BY-Klausel in der Abfrage vorhanden ist. Mit anderen Worten, betrachten Sie diese Abfrage ohne ORDER BY:

SELECT * FROM Singers;

Spanner garantiert nicht, dass die Ergebnisse dieser Abfrage in Primärschlüsselreihenfolge. Außerdem kann sich die Reihenfolge der Ergebnisse jederzeit ändern. und ist nicht zwangsläufig von Aufruf zu Aufruf konsistent. Wenn eine Abfrage eine ORDER BY-Klausel hat und Spanner einen Index verwendet, der die erforderlich, dann sortiert Spanner die Daten nicht explizit. Dementsprechend wird die Auswirkungen dieser Klausel auf die Leistung nicht. Sie können die ob ein expliziter Sortiervorgang in der Ausführung enthalten ist, Abfrageplan.

STARTS_WITH statt LIKE verwenden

Weil Spanner parametrisierte LIKE-Muster erst dann auswertet Ausführungszeit müssen, muss Spanner alle Zeilen lesen und anhand der Ausdruck LIKE, um nicht übereinstimmende Zeilen herauszufiltern.

Wenn ein LIKE-Muster das Format foo% hat (z. B. wenn es mit einer festen String und endet mit einem einzelnen Platzhalterprozentsatz) und die Spalte ist indexiert. Verwenden Sie STARTS_WITH statt LIKE. Dieses ermöglicht Spanner, die Abfrageausführung effektiver zu optimieren. zu erstellen.

Nicht empfohlen:

GoogleSQL

SELECT a.AlbumTitle FROM Albums a
WHERE a.AlbumTitle LIKE @like_clause;

PostgreSQL

SELECT a.AlbumTitle FROM Albums a
WHERE a.AlbumTitle LIKE $1;

<ph type="x-smartling-placeholder"></ph> Empfohlen:

GoogleSQL

SELECT a.AlbumTitle FROM Albums a
WHERE STARTS_WITH(a.AlbumTitle, @prefix);

PostgreSQL

SELECT a.AlbumTitle FROM Albums a
WHERE STARTS_WITH(a.AlbumTitle, $2);

Commit-Zeitstempel verwenden

Wenn Ihre Anwendung Daten abfragen muss, die nach einem bestimmten Zeitpunkt geschrieben wurden, Commit-Zeitstempelspalten zu den relevanten Tabellen hinzufügen. Commit-Zeitstempel eine Spanner-Optimierung ermöglichen, die den E/A- Abfragen, deren WHERE-Klauseln die Ergebnisse auf kürzlich geschriebene Zeilen beschränken als eine bestimmte Zeit.

Weitere Informationen zu dieser Optimierung erhalten Sie mit GoogleSQL-Dialekt-Datenbanken oder mit PostgreSQL-Dialekt-Datenbanken