Questo argomento descrive come scrivere un timestamp di commit per ogni operazione di inserimento e aggiornamento che esegui con Spanner. Per utilizzare questa funzionalità, imposta l'opzione allow_commit_timestamp
su una colonna TIMESTAMP
, quindi scrivi il timestamp come parte di ogni transazione.
Panoramica
Il timestamp del commit, basato sulla tecnologia TrueTime, indica il momento in cui viene eseguito il commit di una transazione nel database. L'opzione della colonna allow_commit_timestamp
consente di archiviare a livello atomico il timestamp del commit in una colonna.
Utilizzando i timestamp di commit archiviati nelle tabelle, puoi determinare l'ordine esatto delle mutazioni e creare funzionalità come i log delle modifiche.
Per inserire i timestamp di commit nel database, completa i seguenti passaggi:
Crea una colonna di tipo
TIMESTAMP
con l'opzione della colonnaallow_commit_timestamp
impostata sutrue
nella definizione dello schema. Ad esempio:CREATE TABLE Performances ( ... LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true) ... ) PRIMARY KEY (...);
Se esegui insert o aggiornamenti con DML, utilizza la funzione
PENDING_COMMIT_TIMESTAMP
per scrivere il timestamp di commit.Se esegui insert o aggiornamenti con mutazioni, utilizza la stringa segnaposto
spanner.commit_timestamp()
per gli posizionamenti o gli aggiornamenti nella colonna del timestamp di commit. Puoi anche utilizzare la costante di timestamp del commit fornita dalla libreria client. Ad esempio, questa costante nel client Java èValue.COMMIT_TIMESTAMP
.
Quando Spanner esegue il commit della transazione utilizzando questi segnaposto come valori delle colonne, il timestamp di commit effettivo viene scritto nella colonna specificata (ad esempio, la colonna LastUpdateTime
). Poi puoi usare questo valore della colonna
per creare una cronologia degli aggiornamenti della tabella.
Non è garantito che i valori dei timestamp di commit siano univoci. Le transazioni che scrivono in insiemi di campi non sovrapposti potrebbero avere lo stesso timestamp. Le transazioni che scrivono in insiemi di campi sovrapposti hanno timestamp univoci.
I timestamp di commit Spanner hanno granularità in microsecondi e vengono convertiti in nanosecondi se archiviati in TIMESTAMP
colonne.
Creazione ed eliminazione di una colonna del timestamp del commit
Utilizza l'opzione della colonna allow_commit_timestamp
per aggiungere e rimuovere il supporto per i timestamp del commit:
- Quando crei una nuova tabella per specificare che una colonna supporta i timestamp di commit.
- Quando modifichi una tabella esistente:
- per aggiungere una nuova colonna che supporti i timestamp di commit,
- per modificare una colonna
TIMESTAMP
esistente in modo da supportare i timestamp di commit, - modificare una colonna
TIMESTAMP
esistente per rimuovere il supporto per il timestamp del commit
Chiavi e indici
Puoi utilizzare una colonna di timestamp di commit come colonna di chiave primaria o come colonna non chiave. Le chiavi primarie possono essere definite come ASC
o DESC
.
ASC
(predefinito): le chiavi crescenti sono ideali per rispondere alle query da un momento specifico in poi.DESC
: le chiavi decrescenti mantengono le ultime righe in cima alla tabella. Consentono di accedere rapidamente ai record più recenti.
L'opzione allow_commit_timestamp
deve essere coerente tra le chiavi primarie delle tabelle padre e di quelle figlio. Se l'opzione non è coerente nelle chiavi primarie, Spanner restituisce un errore. L'unica volta in cui l'opzione può essere incoerente è durante la creazione o l'aggiornamento dello schema.
L'utilizzo di timestamp di commit nei seguenti scenari crea hotspot che riducono le prestazioni dei dati:
Esegui il commit della colonna del timestamp come prima parte della chiave primaria di una tabella:
CREATE TABLE Users ( LastAccess TIMESTAMP NOT NULL, UserId INT64 NOT NULL, ... ) PRIMARY KEY (LastAccess, UserId);
La prima parte della chiave primaria di un indice secondario:
CREATE INDEX UsersByLastAccess ON Users(LastAccess)
o
CREATE INDEX UsersByLastAccessAndName ON Users(LastAccess, FirstName)
Gli hotspot riducono le prestazioni dei dati, anche con frequenze di scrittura basse. Non esiste un sovraccarico delle prestazioni se i timestamp di commit sono abilitati su colonne non chiave non indicizzate.
Crea una colonna del timestamp del commit
Il seguente DDL crea una tabella con una colonna che supporta i timestamp di commit.
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
L'aggiunta dell'opzione modifica la colonna del timestamp come segue:
- Puoi utilizzare la stringa segnaposto
spanner.commit_timestamp()
(o una costante fornita dalla libreria client) per inserti e aggiornamenti. - La colonna può contenere solo valori nel passato. Per maggiori informazioni, consulta Fornire un valore personale per il timestamp.
L'opzione allow_commit_timestamp
fa distinzione tra maiuscole e minuscole.
Aggiungi una colonna di timestamp del commit a una tabella esistente
Per aggiungere una colonna di timestamp del commit a una tabella esistente, utilizza l'istruzione ALTER TABLE
. Ad esempio, per aggiungere una colonna LastUpdateTime
alla tabella Performances
, utilizza la seguente istruzione:
ALTER TABLE Performances ADD COLUMN LastUpdateTime TIMESTAMP
NOT NULL OPTIONS (allow_commit_timestamp=true)
Converti una colonna di timestamp in una colonna di timestamp del commit
Puoi convertire una colonna di timestamp esistente in una colonna di timestamp di commit, ma per farlo è necessario che Spanner verificare che i valori del timestamp esistenti siano antecedenti. Ad esempio:
ALTER TABLE Performances ALTER COLUMN LastUpdateTime
SET OPTIONS (allow_commit_timestamp=true)
Non puoi modificare il tipo di dati o l'annotazione NULL
di una colonna in un'istruzione ALTER TABLE
che include SET OPTIONS
. Per maggiori dettagli, consulta Data Definition Language.
Rimuovi l'opzione del timestamp del commit
Se vuoi rimuovere il supporto del timestamp di commit da una colonna, utilizza l'opzione allow_commit_timestamp=null
in un'istruzione ALTER TABLE
. Il comportamento del timestamp del commit viene rimosso, ma la colonna è ancora
un timestamp. La modifica dell'opzione non cambia le altre caratteristiche della colonna, come il tipo o il valore di valori null (NOT NULL
). Ad esempio:
ALTER TABLE Performances ALTER COLUMN LastUpdateTime
SET OPTIONS (allow_commit_timestamp=null)
Scrivi un timestamp di commit utilizzando un'istruzione DML
Puoi utilizzare la funzione PENDING_COMMIT_TIMESTAMP
per scrivere il timestamp di commit in un'istruzione DML. Spanner seleziona il timestamp di commit quando viene eseguito il commit della transazione.
La seguente istruzione DML aggiorna la colonna LastUpdateTime
nella
tabella Performances
con il timestamp di commit:
UPDATE Performances SET LastUpdateTime = PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
Il seguente esempio di codice utilizza la funzione PENDING_COMMIT_TIMESTAMP
per scrivere il timestamp del commit nella colonna LastUpdateTime
.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Ruby
I timestamp di commit possono essere scritti solo nelle colonne annotate con l'opzione allow_commit_timestamp=true
.
Se sono presenti modifiche nelle righe di più tabelle, devi specificare spanner.commit_timestamp()
(o la costante della libreria client) per la colonna del timestamp del commit in ogni tabella.
Esegui una query su una colonna del timestamp del commit
La query nell'esempio seguente viene eseguita nella colonna del timestamp del commit della tabella.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Fornisci un valore personale per la colonna del timestamp del commit
Puoi fornire un valore personale per la colonna del timestamp di commit anziché passare spanner.commit_timestamp()
(o la costante della libreria client) come valore della colonna. Il valore deve essere un timestamp passato. Questa limitazione garantisce che la scrittura di timestamp sia un'operazione rapida e poco costosa. Il server restituisce un errore FailedPrecondition
se viene specificato un timestamp futuro.
Crea un log delle modifiche
Supponiamo di voler creare un log delle modifiche per ogni mutazione che si verifica in una tabella e di utilizzare questo log per il controllo. Un esempio potrebbe essere una tabella che archivia la cronologia delle modifiche apportate ai documenti di elaborazione testi. Il timestamp del commit semplifica la creazione del log delle modifiche poiché i timestamp possono forzare l'ordine delle voci del log delle modifiche. Puoi creare un log delle modifiche che archivi la cronologia delle modifiche apportate a un determinato documento utilizzando uno schema come quello nell'esempio seguente:
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;
Per creare un log delle modifiche, inserisci una nuova riga in DocumentHistory
nella stessa transazione in cui inserisci o aggiorni una riga in Document
. Nell'inserimento
della nuova riga in DocumentHistory
, utilizza il segnaposto
spanner.commit_timestamp()
(o la costante della libreria client) per indicare a
Spanner di scrivere il timestamp del commit nella colonna Ts
. L'interfoliazione
della tabella DocumentsHistory
con la tabella Documents
consentirà la località dei dati
e l'inserimento e gli aggiornamenti in modo più efficiente. Tuttavia, aggiunge anche il vincolo che le righe padre e figlio devono essere eliminate insieme. Per mantenere le righe in DocumentHistory
dopo l'eliminazione delle righe in Documents
, non interfoliare le tabelle.
Ottimizza le query sui dati recenti con i timestamp di commit
I timestamp di commit consentono un'ottimizzazione di Spanner che può ridurre l'I/O delle query durante il recupero dei dati scritti dopo un determinato periodo di tempo.
Per attivare questa ottimizzazione, la clausola WHERE
di una query deve includere un confronto tra la colonna del timestamp di commit di una tabella e un orario specifico fornito, con i seguenti attributi:
Fornisci il tempo specifico come espressione costante: un valore letterale, un parametro o una funzione i cui argomenti vengono valutati in costanti.
Confronta se il timestamp del commit è più recente del tempo specificato tramite gli operatori
>
o>=
.Se vuoi, aggiungi ulteriori limitazioni alla clausola
WHERE
conAND
. L'estensione della clausola conOR
rende la query non idonea da questa ottimizzazione.
Ad esempio, considera la seguente tabella Performances
, che include una colonna del timestamp del commit:
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);
Questa query trae vantaggio dall'ottimizzazione del timestamp di commit descritta in precedenza, perché presenta un confronto maggiore o uguale tra la colonna del timestamp di commit della tabella e un'espressione costante, in questo caso un valore letterale:
SELECT * FROM Performances WHERE LastUpdateTime >= "2022-05-01";
La seguente query è idonea anche per l'ottimizzazione, poiché ha un confronto superiore tra il timestamp di commit e una funzione i cui argomenti valutano tutti in costanti durante l'esecuzione della query:
SELECT * FROM Performances
WHERE LastUpdateTime > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY);
Passaggi successivi
- Utilizza i timestamp di commit per creare un log delle modifiche con Go.