Auf dieser Seite wird beschrieben, wie Sie für jeden Einfüge- und Aktualisierungsvorgang, den Sie mit Spanner in PostgreSQL-Datenbanken ausführen, einen Commit-Zeitstempel schreiben können.
Commit-Zeitstempel einfügen
Der Commit-Zeitstempel basiert auf der TrueTime-Technologie und ist der Zeitpunkt, zu dem eine Transaktion in der Datenbank zugesichert wird. Sie können den Commit-Zeitstempel einer Transaktion in einer Spalte in kleinstmöglicher Form speichern. Mit den in Tabellen gespeicherten Commit-Zeitstempeln können Sie die genaue Reihenfolge von Mutationen bestimmen und Elemente wie Änderungslogs erstellen.
Führen Sie die folgenden Schritte aus, um Commit-Zeitstempel in eine Datenbank einzufügen:
Erstellen Sie eine Spalte vom Typ
SPANNER.COMMIT_TIMESTAMP
. Beispiel:CREATE TABLE Performances ( ... LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, ... PRIMARY KEY (...) ) ;
Wenn Sie Einfügungen oder Aktualisierungen mit DML durchführen, verwenden Sie die Funktion
SPANNER.PENDING_COMMIT_TIMESTAMP()
, um den Commit-Zeitstempel zu schreiben.Wenn Sie Einfügungen oder Aktualisierungen mit vorbereiteten Anweisungen oder Mutationen durchführen, verwenden Sie den Platzhalter-String
SPANNER.COMMIT_TIMESTAMP()
für die Spalte mit den Commit-Zeitstempeln. Sie können auch die von der Clientbibliothek bereitgestellte Commit-Zeitstempelkonstante verwenden. Im Java-Client ist diese Konstante beispielsweiseValue.COMMIT_TIMESTAMP
.
Wenn Spanner die Transaktion mit diesen Platzhaltern als Spaltenwerte festschreibt, wird der tatsächliche Commit-Zeitstempel in die angegebene Spalte geschrieben. Mit diesem Spaltenwert können Sie dann einen Verlauf der Aktualisierungen der Tabelle erstellen.
Die Werte der Commit-Zeitstempel sind nicht zwangsläufig eindeutig. Transaktionen, bei denen in nicht überlappende Gruppen von Feldern geschrieben wird, haben möglicherweise den gleichen Zeitstempel. Transaktionen, bei denen in überlappende Gruppen von Feldern geschrieben wird, haben eindeutige Zeitstempel.
Die Genauigkeit der Commit-Zeitstempel von Spanner liegt im Bereich von Mikrosekunden, die beim Speichern in SPANNER.COMMIT_TIMESTAMP
-Spalten in Nanosekunden umgewandelt werden.
Schlüssel und Indexe
Sie können eine Commit-Zeitstempelspalte als Primärschlüsselspalte oder als Spalte verwenden, die keine Schlüsselspalte ist. Primärschlüssel können als ASC
oder DESC
definiert werden.
ASC
(Standard): Aufsteigende Schlüssel sind ideal für die Beantwortung von Abfragen ab einem bestimmten Zeitpunkt.DESC
: Bei absteigenden Schlüsseln werden die neuesten Zeilen am Tabellenanfang gespeichert. Sie bieten schnellen Zugriff auf die neuesten Datensätze.
Hotspots vermeiden
Werden in den folgenden Szenarien Commit-Zeitstempel verwendet, entstehen Hotspots, wodurch die Datenleistung verringert wird:
Spalte der Commit-Zeitstempel als erster Teil des Primärschlüssels einer Tabelle.
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId bigint NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;
Primärschlüsselspalte für Commit-Zeitstempel als ersten Teil eines sekundären Index
CREATE INDEX UsersByLastAccess ON Users(LastAccess)
oder
CREATE INDEX UsersByLastAccessAndName ON Users(LastAccess, FirstName)
Hotspots verringern die Datenleistung selbst bei niedrigen Schreibraten. Wenn Commit-Zeitstempel für Nicht-Schlüsselspalten ohne Indexierung aktiviert sind, gibt es keine Leistungseinbußen.
Zeitstempelspalte zu einer vorhandenen Tabelle hinzufügen
Verwenden Sie die Anweisung ALTER TABLE
, um einer vorhandenen Tabelle eine Commit-Zeitstempelspalte hinzuzufügen: Verwenden Sie beispielsweise die folgende Anweisung, um der Tabelle Performances
eine Spalte LastUpdateTime
hinzuzufügen:
ALTER TABLE Performances ADD COLUMN LastUpdateTime SPANNER.COMMIT_TIMESTAMP;
Einen Commit-Zeitstempel mit einer DML-Anweisung schreiben
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 ausgeführt wird.
Mit der folgenden DML-Anweisung wird der Commit-Zeitstempel in die Spalte LastUpdateTime
in der Tabelle Performances
geschrieben.
UPDATE Performances SET LastUpdateTime = SPANNER.PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
Zeile mithilfe einer Mutation einfügen
Beim Einfügen einer Zeile schreibt Spanner den Wert für den Commit-Zeitstempel nur, wenn die Spalte in der Spaltenliste aufgeführt ist und der Platzhalterstring spanner.commit_timestamp()
bzw. die Konstante der Clientbibliothek als Wert übergeben wird. Beispiel:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Wenn Sie Mutationen in Zeilen in mehreren Tabellen haben, müssen Sie spanner.commit_timestamp()
bzw. die Konstante der Clientbibliothek für die Commit-Zeitstempelspalte in jeder Tabelle angeben.
Zeile mit einer Mutation aktualisieren
Beim Aktualisieren einer Zeile schreibt Spanner den Wert für den Commit-Zeitstempel nur, wenn die Spalte in der Spaltenliste aufgeführt ist und der Platzhalterstring spanner.commit_timestamp()
bzw. die Konstante der Clientbibliothek als Wert übergeben wird. Der Primärschlüssel einer Zeile kann nicht aktualisiert werden. Sie müssen die vorhandene Zeile löschen und eine neue Zeile erstellen, um den Primärschlüssel zu aktualisieren.
Die Commit-Zeitstempelspalte mit dem Namen LastUpdateTime
können Sie beispielsweise so aktualisieren:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Wenn Sie Mutationen in Zeilen in mehreren Tabellen haben, müssen Sie spanner.commit_timestamp()
bzw. die Konstante der Clientbibliothek für die Commit-Zeitstempelspalte in jeder Tabelle angeben.
Commit-Zeitstempelspalte abfragen
Im folgenden Beispiel wird die Commit-Zeitstempelspalte der Tabelle abgefragt.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Eigenen Wert für die Commit-Zeitstempelspalte verwenden
Sie können in Ihrem Code einen eigenen Wert für die Commit-Zeitstempelspalte angeben, anstatt spanner.commit_timestamp()
(oder die verfügbare Konstante der Clientbibliothek) als Spaltenwert zu übergeben. Der Wert muss ein Zeitstempel sein, der in der Vergangenheit liegt. Mit dieser Einschränkung wird sichergestellt, dass das Schreiben von Zeitstempeln ein kostengünstiger und schneller Vorgang ist. Eine Möglichkeit, um zu bestätigen, dass ein Wert in der Vergangenheit liegt, besteht darin, ihn mit dem von der SQL-Funktion CURRENT_TIMESTAMP
zurückgegebenen Wert zu vergleichen. Der Server gibt den Fehler FailedPrecondition
zurück, wenn ein Zeitstempel angegeben ist, der in der Zukunft liegt.
Änderungsprotokoll erstellen
Angenommen, Sie möchten für jede an einer Tabelle vorgenommene Mutation ein Änderungslog erstellen und dieses Änderungslog dann zur Überprüfung verwenden. Ein Beispiel wäre eine Tabelle, in der der Änderungsverlauf von Textverarbeitungsdokumenten gespeichert wird. Der Commit-Zeitstempel erleichtert das Erstellen des Änderungslogs, weil die Einträge im Änderungslog aufgrund der Zeitstempel in die entsprechende Reihenfolge gebracht werden können. Sie könnten ein Änderungslog erstellen, in dem der Verlauf der Änderungen an einem bestimmten Dokument gespeichert wird, indem Sie ein Schema wie in folgendem Beispiel verwenden:
CREATE TABLE Documents (
UserId int8 NOT NULL,
DocumentId int8 NOT NULL,
Contents text NOT NULL,
PRIMARY KEY (UserId, DocumentId)
);
CREATE TABLE DocumentHistory (
UserId int8 NOT NULL,
DocumentId int8 NOT NULL,
Ts SPANNER.COMMIT_TIMESTAMP NOT NULL,
Delta text,
PRIMARY KEY (UserId, DocumentId, Ts)
) INTERLEAVE IN PARENT Documents;
Wenn Sie ein Änderungslog erstellen möchten, fügen Sie in derselben Transaktion, in die Sie eine Zeile in Document
einfügen oder aktualisieren, eine neue Zeile in DocumentHistory
ein. Verwenden Sie dabei beim Einfügen der neuen Zeile in DocumentHistory
den Platzhalter spanner.commit_timestamp()
bzw. die Konstante der Clientbibliothek, damit Spanner den Commit-Zeitstempel in die Spalte Ts
schreibt.
Das Verschränken der Tabelle DocumentsHistory
mit der Tabelle Documents
sorgt für Datenlokalität und effizientere Einfüge- und Aktualisierungsvorgänge. Dadurch ergibt sich jedoch auch die zusätzliche Einschränkung, dass die übergeordneten und untergeordneten Zeilen zusammen gelöscht werden müssen. Sie sollten die Tabellen nicht verschränken, damit die Zeilen in DocumentHistory
beibehalten werden, nachdem Zeilen in Documents
gelöscht wurden.
Abfragen zu aktuellen Daten mit Commit-Zeitstempeln optimieren
Commit-Zeitstempel optimieren Ihre Spanner-Datenbank und können die Abfrage-I/O beim Abrufen von Daten reduzieren, die nach einem bestimmten Zeitpunkt geschrieben wurden.
Um diese Optimierung zu aktivieren, muss die WHERE
-Klausel einer Abfrage einen Vergleich zwischen der Commit-Zeitstempelspalte einer Tabelle und einer von Ihnen angegebenen bestimmten Uhrzeit mit den folgenden Attributen enthalten:
Geben Sie die Uhrzeit als konstanten Ausdruck an: ein Literal, einen Parameter oder eine Funktion, deren eigene Argumente zu Konstanten ausgewertet werden.
Mit den Operatoren
>
oder>=
können Sie prüfen, ob der Commit-Zeitstempel aktueller ist als die angegebene Zeit.Optional können Sie der
WHERE
-Klausel mitAND
weitere Einschränkungen hinzufügen. Wenn Sie die Klausel umOR
erweitern, kann sie nicht mehr optimiert werden.
Betrachten Sie beispielsweise die folgende Performances
-Tabelle mit einer Commit-Zeitstempelspalte:
CREATE TABLE Performances (
SingerId bigint NOT NULL,
VenueId bigint NOT NULL,
EventDate timestamp with time zone NOT NULL,
Revenue bigint,
LastUpdateTime spanner.commit_timestamp,
PRIMARY KEY(SingerId, VenueId, EventDate)
);
Diese Abfrage profitiert von der oben beschriebenen Optimierung des Commit-Zeitstempels, da sie einen Vergleich zwischen der Spalte „Commit-Zeitstempel“ der Tabelle und einem konstanten Ausdruck enthält, in diesem Fall einem Literal:
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';