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. Damit Sie diese Funktion verwenden können, legen Sie für eine TIMESTAMP
-Spalte die Option allow_commit_timestamp
fest, und schreiben Sie dann den Zeitstempel als Teil jeder Transaktion.
Übersicht
Der Commit-Zeitstempel basiert auf der TrueTime-Technologie und ist der Zeitpunkt, zu dem eine Transaktion in der Datenbank zugesichert wird. Mit der Spaltenoption allow_commit_timestamp
können Sie den Commit-Zeitstempel in kleinstmöglicher Form 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
TIMESTAMP
, wobei die Spaltenoptionallow_commit_timestamp
in der Schemadefinition auftrue
gesetzt ist. Beispiel:CREATE TABLE Performances ( ... LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true) ... ) PRIMARY KEY (...);
Wenn Sie Einfügungen oder Aktualisierungen mit DML durchführen, verwenden Sie die Funktion
PENDING_COMMIT_TIMESTAMP
, um den Commit-Zeitstempel zu schreiben.Wenn Sie Einfügungen oder Aktualisierungen mit Mutationen durchführen, verwenden Sie beim Einfügen oder Aktualisieren der Spalte mit den Commit-Zeitstempeln den Platzhalter-String
spanner.commit_timestamp()
. Sie können auch die Commit-Zeitstempelkonstante, die von der Clientbibliothek bereitgestellt wird. Zum Beispiel im Java-Client istValue.COMMIT_TIMESTAMP
.
Wenn Spanner die Transaktion mit diesen Platzhaltern als Spaltenwerte festschreibt, wird der tatsächliche Commit-Zeitstempel in die angegebene Spalte geschrieben (z. B. die Spalte LastUpdateTime
). 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.
Commit-Zeitstempel von Spanner haben einen Detaillierungsgrad von Mikrosekunden.
Sie werden beim Speichern in TIMESTAMP
-Spalten in Nanosekunden konvertiert.
Commit-Zeitstempelspalte erstellen und löschen
Verwenden Sie die Spaltenoption allow_commit_timestamp
, um Unterstützung für Commit-Zeitstempel hinzuzufügen und zu entfernen:
- Beim Erstellen einer neuen Tabelle, um anzugeben, dass eine Spalte Commit-Zeitstempel unterstützt.
- Beim Ändern einer vorhandenen Tabelle:
- um eine neue Spalte hinzuzufügen, die Commit-Zeitstempel unterstützt,
- eine vorhandene
TIMESTAMP
-Spalte ändern, um Commit-Zeitstempel zu unterstützen, - zum Ändern einer vorhandenen
TIMESTAMP
-Spalte, um die Unterstützung von Commit-Zeitstempeln zu entfernen
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.
Die Option allow_commit_timestamp
muss für die Primärschlüssel der über- und untergeordneten Tabellen konsistent sein. Wenn die Option nicht einheitlich ist,
Primärschlüssel verwenden, gibt Spanner einen Fehler zurück. Die Option kann nur dann uneinheitlich festgelegt sein, wenn Sie das Schema erstellen oder aktualisieren.
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 TIMESTAMP NOT NULL, UserId INT64 NOT NULL, ... ) PRIMARY KEY (LastAccess, UserId);
Der erste Teil des Primärschlüssels eines Sekundärindex:
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 erstellen
Die folgende DDL erstellt eine Tabelle mit einer Spalte, die Commit-Zeitstempel unterstützt.
CREATE TABLE Performances (
SingerId INT64 NOT NULL,
VenueId INT64 NOT NULL,
EventDate Date,
Revenue INT64,
LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)
) PRIMARY KEY (SingerId, VenueId, EventDate),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE
Durch Hinzufügen dieser Option ergeben sich für die Zeitstempelspalte folgende Änderungen:
- Sie können den Platzhalterstring
spanner.commit_timestamp()
bzw. eine Konstante, die von der Clientbibliothek bereitgestellt wird, für Einfügungen und Aktualisierungen verwenden. - Die Spalte darf nur Werte enthalten, die in der Vergangenheit liegen. Weitere Informationen finden Sie unter Bereitstellen eines eigenen Wertes für den Zeitstempel.
Bei der Option allow_commit_timestamp
wird zwischen Groß- und Kleinschreibung unterschieden.
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 TIMESTAMP
NOT NULL OPTIONS (allow_commit_timestamp=true)
Zeitstempelspalte in Commit-Zeitstempelspalte konvertieren
Sie können eine vorhandene Zeitstempelspalte in eine Commit-Zeitstempelspalte konvertieren. Dazu muss Spanner jedoch überprüfen, dass die vorhandenen Zeitstempelwerte in der Vergangenheit liegen. Beispiel:
ALTER TABLE Performances ALTER COLUMN LastUpdateTime
SET OPTIONS (allow_commit_timestamp=true)
In einer ALTER TABLE
-Anweisung, die SET OPTIONS
enthält, können Sie den Datentyp bzw. die NULL
-Anmerkung einer Spalte nicht ändern. Weitere Informationen finden Sie unter Datendefinitionssprache.
Option „Commit-Zeitstempel“ entfernen
Wenn Sie die Unterstützung für Commit-Zeitstempel aus einer Spalte entfernen möchten, verwenden Sie die Option allow_commit_timestamp=null
in einer ALTER TABLE
-Anweisung. Das Verhalten für Commit-Zeitstempel wird entfernt, aber die Spalte bleibt weiterhin ein Zeitstempel. Durch die Änderung der Option verändern sich keine anderen Eigenschaften der Spalte, wie Typ oder Unwirksamkeit (NOT NULL
). Beispiel:
ALTER TABLE Performances ALTER COLUMN LastUpdateTime
SET OPTIONS (allow_commit_timestamp=null)
Commit-Zeitstempel mit einer DML-Anweisung schreiben
Schreiben Sie mit der Funktion 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 die Spalte LastUpdateTime
im
Performances
mit dem Commit-Zeitstempel:
UPDATE Performances SET LastUpdateTime = PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
Im folgenden Codebeispiel wird die Funktion PENDING_COMMIT_TIMESTAMP
zum Schreiben des Commit-Zeitstempels in die Spalte LastUpdateTime
verwendet.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Ruby
Commit-Zeitstempel können nur in Spalten geschrieben werden, die mit der Option allow_commit_timestamp=true
gekennzeichnet sind.
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
Sie können Ihren eigenen Wert für die Commit-Zeitstempelspalte verwenden, anstatt spanner.commit_timestamp()
bzw. die Konstante der Clientbilbiothek 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. 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 INT64 NOT NULL,
DocumentId INT64 NOT NULL,
Contents STRING(MAX) NOT NULL,
) PRIMARY KEY (UserId, DocumentId);
CREATE TABLE DocumentHistory (
UserId INT64 NOT NULL,
DocumentId INT64 NOT NULL,
Ts TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true),
Delta STRING(MAX),
) PRIMARY KEY (UserId, DocumentId, Ts),
INTERLEAVE IN PARENT Documents ON DELETE NO ACTION;
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. In der Einfügung
der neuen Zeile in DocumentHistory
den Platzhalter verwenden
spanner.commit_timestamp()
(oder die Konstante der Clientbibliothek),
Spanner so 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 ermöglichen eine Spanner-Optimierung, kann die Abfrage-E/A reduzieren, wenn Daten abgerufen werden, die nach einer bestimmten .
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 jeweilige Zeit als konstanten Ausdruck an: ein Literal, ein oder einer Funktion, deren Argumente als Konstanten ausgewertet werden.
Vergleichen Sie, ob der Commit-Zeitstempel aktueller ist als der für einen bestimmten Zeitpunkt, entweder über den Operator
>
oder den Operator>=
.Fügen Sie optional mit
AND
weitere Einschränkungen zurWHERE
-Klausel hinzu. 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 INT64 NOT NULL,
VenueId INT64 NOT NULL,
EventDate DATE,
Revenue INT64,
LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)
) 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-05-01";
Die folgende Abfrage kommt ebenfalls für die Optimierung infrage, da sie einen Vergleich zwischen dem Commit-Zeitstempel und einer Funktion enthält, deren Argumente während der Ausführung der Abfrage alle zu Konstanten ausgewertet werden:
SELECT * FROM Performances
WHERE LastUpdateTime > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY);
Nächste Schritte
- Mit Commit-Zeitstempeln ein Änderungslog mit Go erstellen.