Best Practices für die Datenbearbeitungssprache

Auf dieser Seite werden die Best Practices für die Verwendung der Datenbearbeitungssprache (Data Manipulation Language – DML) und der partitionierten DML beschrieben.

Mit einer WHERE-Klausel die Anzahl der gesperrten Zeilen reduzieren

Sie führen DML-Anweisungen in Lese- und Schreibtransaktionen aus. Wenn Spanner Daten liest, werden gemeinsame Lesesperren für begrenzte Teile der gelesenen Zeilenbereiche übernommen. Insbesondere werden diese Sperren nur für die Spalten übernommen, auf die Sie zugreifen. Die Sperren können Daten enthalten, die die Filterbedingung der WHERE-Klausel nicht erfüllen.

Wenn Spanner Daten mit DML-Anweisungen ändert, werden exklusive Sperren für die Daten übernommen, die Sie ändern. Darüber hinaus werden gemeinsame Sperren auf die gleiche Weise wie beim Lesen von Daten angewendet. Wenn Ihre Anfrage große Zeilenbereiche oder eine ganze Tabelle enthält, verhindern die gemeinsamen Sperren möglicherweise, dass andere Transaktionen parallel weiterarbeiten.

Um Daten so effizient wie möglich zu ändern, verwenden Sie die WHERE-Klausel, die es Spanner ermöglicht, nur die erforderlichen Zeilen zu lesen. Sie können dafür einen Filter für den Primärschlüssel oder für den Schlüssel eines Sekundärindex nutzen. Die WHERE-Klausel schränkt den Umfang der gemeinsamen Sperren ein und ermöglicht Spanner, die Aktualisierung effizienter zu verarbeiten.

Angenommen, einer der Musiker in der Tabelle Singers ändert seinen Vornamen und Sie müssen den Namen in Ihrer Datenbank aktualisieren. Sie können die folgende DML-Anweisung ausführen. Spanner wird jedoch gezwungen, die gesamte Tabelle zu scannen und gemeinsame Sperren abzurufen, die die gesamte Tabelle abdecken. Daher muss Spanner mehr Daten als nötig lesen und gleichzeitige Transaktionen können die Daten nicht parallel ändern:

-- ANTI-PATTERN: SENDING AN UPDATE WITHOUT THE PRIMARY KEY COLUMN
-- IN THE WHERE CLAUSE

UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards";

Für eine effizientere Aktualisierung nehmen Sie die Spalte SingerId in die WHERE-Klausel auf. Die Spalte SingerId ist die einzige primäre Schlüsselspalte für die Tabelle Singers:

-- ANTI-PATTERN: SENDING AN UPDATE THAT MUST SCAN THE ENTIRE TABLE

UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards"

Wenn für FirstName oder LastName kein Index vorhanden ist, müssen Sie die gesamte Tabelle nach den Zielsingern durchsuchen. Wenn Sie keinen sekundären Index hinzufügen möchten, um die Aktualisierung effizienter zu machen, fügen Sie die Spalte SingerId in die WHERE-Klausel ein.

Die Spalte SingerId ist die einzige Primärschlüsselspalte für die Tabelle Singers. Führen Sie SELECT vor der Aktualisierungstransaktion in einer separaten, schreibgeschützten Transaktion aus, um sie zu ermitteln:


  SELECT SingerId
  FROM Singers
  WHERE FirstName = "Marc" AND LastName = "Richards"
  
  -- Recommended: Including a seekable filter in the where clause
  
  UPDATE Singers SET FirstName = "Marcel"
  WHERE SingerId = 1;

Vermeiden Sie die Verwendung von DML-Anweisungen und -Mutationen in derselben Transaktion

Spanner speichert Einfügungen, Aktualisierungen und Löschungen, die mit DML-Anweisungen auf der Serverseite ausgeführt wurden, im Zwischenspeicher. Die Ergebnisse sind für nachfolgende SQL- und DML-Anweisungen in derselben Transaktion sichtbar. Dieses Verhalten unterscheidet sich von der Mutation API, bei der Spanner die Mutationen auf der Clientseite zwischenspeichert und sie serverseitig als Teil des Commit-Vorgangs sendet. Folglich sind Mutationen in der Commit-Anfrage für SQL- oder DML-Anweisungen in derselben Transaktion nicht sichtbar.

Vermeiden Sie die Verwendung von DML-Anweisungen und Mutationen in derselben Transaktion. Wenn Sie beide in derselben Transaktion verwenden, müssen Sie die Reihenfolge der Ausführung in Ihrem Clientbibliothekscode berücksichtigen. Wenn eine Transaktion sowohl DML-Anweisungen als auch Mutationen in derselben Anfrage enthält, führt Spanner die DML-Anweisungen vor den Mutationen aus.

Bei Vorgängen, die nur mit Mutationen unterstützt werden, können Sie DML-Anweisungen und Mutationen in derselben Transaktion kombinieren, z. B. insert_or_update.

Wenn Sie beide verwenden, schreibt der Zwischenspeicher nur ganz am Ende der Transaktion.

Mit der Funktion PENDING_COMMIT_TIMESTAMP um Commit-Zeitstempel schreiben

GoogleSQL

Schreiben Sie mit der Funktion PENDING_COMMIT_TIMESTAMP den Commit-Zeitstempel in eine DML-Anweisung. Spanner wählt den Commit-Zeitstempel aus, wenn der Commit der Transaktion durchgeführt wird.

PostgreSQL

Schreiben Sie mit der Funktion SPANNER.PENDING_COMMIT_TIMESTAMP() den Commit-Zeitstempel in eine DML-Anweisung. Spanner wählt den Commit-Zeitstempel aus, wenn der Commit der Transaktion durchgeführt wird.

Partitionierte DML-, Datums- und Zeitstempelfunktionen

Partitionierte DML verwendet eine oder mehrere Transaktionen, die möglicherweise zu unterschiedlichen Zeitpunkten ausgeführt und bereitgestellt werden. Wenn Sie die Datums- oder Zeitstempelfunktion verwenden, können die geänderten Zeilen andere Werte enthalten.

Latenz mit Batch-DML verbessern

Verwenden Sie Batch-DML, um innerhalb eines einzelnen Client-Server-Roundtrips mehrere DML-Anweisungen an Spanner zu senden, um die Latenz zu verringern.

Batch-DML kann Optimierungen auf Gruppen von Anweisungen innerhalb eines Batches anwenden, um schnellere und effizientere Datenaktualisierungen zu ermöglichen.

  • Schreibvorgänge mit einer einzigen Anfrage ausführen

    Spanner optimiert automatisch zusammenhängende Gruppen ähnlicher INSERT-, UPDATE- oder DELETE-Batchanweisungen mit unterschiedlichen Parameterwerten, wenn sie nicht gegen Datenabhängigkeiten verstoßen.

    Stellen Sie sich beispielsweise ein Szenario vor, in dem Sie eine große Menge neuer Zeilen in eine Tabelle mit dem Namen Albums einfügen möchten. Damit Spanner alle erforderlichen INSERT-Anweisungen in einer einzigen, effizienten serverseitigen Aktion optimieren kann, müssen Sie zuerst eine entsprechende DML-Anweisung schreiben, die SQL-Abfrageparameter verwendet:

    INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (@Singer, @Album, @Title);
    

    Senden Sie dann Spanner einen DML-Batch, der diese Anweisung wiederholt und fortlaufend aufruft, wobei sich die Wiederholungen nur in den Werten unterscheiden, die Sie an die drei Abfrageparameter der Anweisung binden. Spanner optimiert diese strukturell identischen DML-Anweisungen vor der Ausführung in einem einzigen serverseitigen Vorgang.

  • Schreibvorgänge parallel ausführen

    Spanner optimiert automatisch zusammenhängende Gruppen von DML-Anweisungen, indem es parallel ausgeführt wird, wenn dies nicht gegen Datenabhängigkeiten verstößt. Diese Optimierung bietet einem breiteren Satz von DML-Batch-Anweisungen Leistungsvorteile, da sie sich auf eine Mischung aus DML-Anweisungstypen (INSERT, UPDATE und DELETE) und sowohl auf parametrisierte als auch nicht parametrisierte DML-Anweisungen anwenden können.

    Unser Beispielschema enthält beispielsweise die Tabellen Singers, Albums und Accounts. Albums ist mit Singers verschränkt und speichert Informationen zu Alben für Singers. Die folgende zusammenhängende Gruppe von Anweisungen schreibt neue Zeilen in mehrere Tabellen und hat keine komplexen Datenabhängigkeiten.

    INSERT INTO Singers (SingerId, Name) VALUES(1, "John Doe");
    INSERT INTO Singers (SingerId, Name) VALUES(2, "Marcel Richards");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10001, "Album 1");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10002, "Album 2");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (2, 10001, "Album 1");
    UPDATE Accounts SET Balance = 100 WHERE AccountId = @AccountId;
    

    Spanner optimiert diese Gruppe von DML-Anweisungen, indem die Anweisungen parallel ausgeführt werden. Die Schreibvorgänge werden in der Reihenfolge der Anweisungen im Batch angewendet und behält die Batch-DML-Semantik bei, wenn eine Anweisung während der Ausführung fehlschlägt.