In diesem Thema wird beschrieben, wie Sie für jeden Einfüge- und Aktualisierungsvorgang, den Sie mit Spanner ausführen, einen Commit-Zeitstempel schreiben können.
Commit-Zeitstempel – Übersicht
Der Commit-Zeitstempel, basierend auf TrueTime Technologie ist die Zeit, in der ein für die Transaktion in der Datenbank ein Commit durchgeführt wird. Sie können das Commit in kleinstmöglichen Schritten speichern. Zeitstempel einer Transaktion in eine Spalte ein. 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 zu schreiben. Zeitstempel.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. Zum Beispiel im Java-Client istValue.COMMIT_TIMESTAMP
.
Wenn Spanner die Transaktion durch Verwendung dieser Platzhalter als Spaltenwerten wird der tatsächliche Commit-Zeitstempel in die angegebene Spalte geschrieben. Sie können dann diesen Spaltenwert 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.
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 werden reduziert 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 die Transaktion
Commits übergeben.
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
Geben Sie Ihren eigenen Wert für die Commit-Zeitstempelspalte an
In Ihrem Code können Sie Ihren eigenen Wert für die Commit-Zeitstempelspalte angeben.
statt spanner.commit_timestamp()
(oder die verfügbare Clientbibliothek
Konstante) als
Spaltenwert. 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 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.
Aktuelle Datenabfragen mit Commit-Zeitstempeln optimieren
Commit-Zeitstempel ermöglichen eine Spanner-Optimierung, mit der die Abfrage-I/O beim Abrufen von Daten reduziert werden kann, die nach einem bestimmten Zeitpunkt geschrieben wurden.
Zum Aktivieren dieser Optimierung muss die WHERE
-Klausel einer Abfrage Folgendes enthalten:
Vergleich zwischen der Commit-Zeitstempelspalte einer Tabelle und einer bestimmten Zeit
mit den folgenden Attributen:
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 als die angegebene Zeit ist.Optional können Sie der
WHERE
-Klausel mitAND
weitere Einschränkungen hinzufügen. Durch das Erweitern der Klausel mitOR
wird die Abfrage aus dieser Optimierung.
Sehen Sie sich beispielsweise die folgende Performances
-Tabelle an, die Folgendes enthält:
eine Commit-Zeitstempelspalte aus:
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 beschriebenen Commit-Zeitstempeloptimierung. weil es einen Größer-als-oder-Gleich-Vergleich der Commit-Zeitstempelspalte der Tabelle und einem konstanten Ausdruck – case, ein Literal:
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';