In diesem Thema wird beschrieben, wie Sie einen Commit-Zeitstempel für jeden Einfüge- und Aktualisierungsvorgang schreiben, den Sie mit Spanner ausführen. 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.
Überblick
Der Commit-Zeitstempel basierend auf der TrueTime-Technologie ist der Zeitpunkt, zu dem eine Transaktion in der Datenbank per Commit festgeschrieben wird. Mit der Spaltenoption allow_commit_timestamp
können Sie den Commit-Zeitstempel 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
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 den Platzhalterstring
spanner.commit_timestamp()
bei Einfügungen oder Aktualisierungen der Commit-Zeitstempelspalte. Sie können auch die von der Clientbibliothek bereitgestellte Commit-Zeitstempelkonstante verwenden. Diese Konstante im Java-Client ist beispielsweiseValue.COMMIT_TIMESTAMP
.
Wenn Spanner die Transaktion unter Verwendung dieser Platzhalter als Spaltenwerte mit Commit ausführt, 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.
Spanner-Commit-Zeitstempel haben einen Detaillierungsgrad auf Mikrosekunden und werden beim Speichern in TIMESTAMP
-Spalten in Nanosekunden umgewandelt.
Spalte mit Commit-Zeitstempel 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 in den Primärschlüsseln nicht einheitlich ist, 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.
Spalte für Commit-Zeitstempel 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.
Einer vorhandenen Tabelle eine Commit-Zeitstempelspalte 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 eine Commit-Zeitstempelspalte konvertieren
Sie können eine vorhandene Zeitstempelspalte in eine Commit-Zeitstempelspalte konvertieren. Dazu muss Spanner jedoch prüfen, ob 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 für 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 der Commit der Transaktion durchgeführt wird.
Mit der folgenden DML-Anweisung wird der Commit-Zeitstempel in die Spalte LastUpdateTime
in der Tabelle Performances
geschrieben.
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.
Spalte mit Commit-Zeitstempel abfragen
Im folgenden Beispiel wird die Commit-Zeitstempelspalte der Tabelle abgefragt.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Geben Sie einen eigenen Wert für die Commit-Zeitstempelspalte ein
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 in der Zukunft angegeben wurde.
Ä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. 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
schreiben soll. 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.
Letzte Datenabfragen mit Commit-Zeitstempeln optimieren
Commit-Zeitstempel ermöglichen eine Spanner-Optimierung, die die E/A-Abfrage von Abfragen reduzieren kann, wenn Daten abgerufen werden, die nach einer bestimmten Zeit geschrieben wurden.
Zum Aktivieren dieser Optimierung muss die WHERE
-Klausel einer Abfrage einen Vergleich zwischen der Commit-Zeitstempelspalte einer Tabelle und einer von Ihnen angegebenen Zeit mit den folgenden Attributen enthalten:
Geben Sie die bestimmte Zeit als konstanten Ausdruck an: ein Literal, ein Parameter oder eine Funktion, deren eigene Argumente als Konstanten ausgewertet werden.
Vergleichen Sie, ob der Commit-Zeitstempel nach der angegebenen Zeit liegt. Verwenden Sie dazu entweder den Operator
>
oder>=
.Optional können Sie mit
AND
weitere Einschränkungen zurWHERE
-Klausel hinzufügen. Durch das Erweitern der Klausel mitOR
wird die Abfrage von dieser Optimierung ausgeschlossen.
Betrachten Sie beispielsweise die folgende Performances
-Tabelle, die eine Commit-Zeitstempelspalte enthält:
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 zuvor beschriebenen Commit-Zeitstempeloptimierung, da sie einen größeren-als-oder-gleich-zu-Vergleich zwischen der Commit-Zeitstempelspalte der Tabelle und einem konstanten Ausdruck – in diesem Fall ein Literal – hat:
SELECT * FROM Performances WHERE LastUpdateTime >= "2022-05-01";
Auch die folgende Abfrage ist für die Optimierung qualifiziert, da sie einen größeren als-Vergleich zwischen dem Commit-Zeitstempel und einer Funktion hat, deren Argumente während der Ausführung der Abfrage alle als 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.