In diesem Thema wird beschrieben, wie Sie einen Commit-Zeitstempel für jeden Einfüge- und Aktualisierungsvorgang schreiben, den Sie mit Spanner ausführen.
Commit-Zeitstempel
Der Commit-Zeitstempel basiert auf der TrueTime-Technologie und ist der Zeitpunkt, an dem eine Transaktion in der Datenbank festgeschrieben wird. Sie können den Commit-Zeitstempel einer Transaktion in kleinstmöglichen Schritten in einer Spalte 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 Platzhalterstring
SPANNER.COMMIT_TIMESTAMP()
für Ihre Commit-Zeitstempelspalte. Sie können auch die Commit-Zeitstempelkonstante verwenden, die von der Clientbibliothek bereitgestellt wird. Diese Konstante im Java-Client ist beispielsweiseValue.COMMIT_TIMESTAMP
.
Wenn Spanner die Transaktion mithilfe dieser Platzhalter als Spaltenwerte festschreibt, wird der tatsächliche Commit-Zeitstempel in die angegebene Spalte geschrieben. Sie können diesen Spaltenwert dann verwenden, um einen Verlauf der Aktualisierungen der Tabelle zu 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.
Spanner-Commit-Zeitstempel haben eine Genauigkeit von Mikrosekunden und werden in Nanosekunden umgewandelt, wenn sie in SPANNER.COMMIT_TIMESTAMP
-Spalten gespeichert sind.
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
Wenn Sie in den folgenden Szenarien Commit-Zeitstempel verwenden, werden Hotspots erstellt, wodurch die Datenleistung reduziert wird:
Commit-Zeitstempelspalte als erster Teil des Primärschlüssels einer Tabelle.
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId INT64 NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;
Commit des Zeitstempel-Primärschlüssels als erster 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.
Commit-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
NOT NULL;
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 ein Commit für die 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 mit 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()
(oder die Konstante der Clientbibliothek) als Wert übergeben wird. Beispiel:
C++
C#
Einfach loslegen (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()
(oder 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#
Einfach loslegen (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#
Einfach loslegen (Go)
Java
Node.js
PHP
Python
Ruby
Eigenen Wert für die Commit-Zeitstempelspalte angeben
In Ihrem Code können Sie 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 einfache 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 beim Einfügen der neuen Zeile in DocumentHistory
den Platzhalter spanner.commit_timestamp()
(oder 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 kürzlicher Daten mit Commit-Zeitstempeln optimieren
Commit-Zeitstempel ermöglichen eine Spanner-Optimierung, die die Abfrage-E/A beim Abrufen von Daten reduzieren kann, die nach einer bestimmten Zeit geschrieben werden.
Zum Aktivieren dieser Optimierung muss die WHERE
-Klausel einer Abfrage einen Vergleich zwischen der Commit-Zeitstempelspalte und einer angegebenen Zeit mit den folgenden Attributen enthalten:
Geben Sie die genaue Zeit als konstanten Ausdruck an: ein Literal, einen Parameter oder eine Funktion, deren eigene Argumente als Konstanten ausgewertet werden.
Vergleichen Sie mit den Operatoren
>
oder>=
, ob der Commit-Zeitstempel aktueller als der angegebene Zeitpunkt ist.Fügen Sie optional weitere Einschränkungen für die
WHERE
-Klausel mitAND
hinzu. Durch das Erweitern der Klausel mitOR
wird die Abfrage von dieser Optimierung ausgeschlossen.
Betrachten Sie beispielsweise die folgende Tabelle Performances
, die eine Commit-Zeitstempelspalte enthält:
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 zuvor beschriebenen Commit-Zeitstempeloptimierung, da sie einen Vergleich von mehr als oder gleich dem Commit-Zeitstempelspalte und einem konstanten Ausdruck enthält – in diesem Fall ein Literal:
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';