Questo argomento descrive come scrivere un timestamp di commit per ogni operazione di inserimento e aggiornamento eseguita con Spanner. Per utilizzare questa funzionalità, imposta l'opzione allow_commit_timestamp
in una colonna TIMESTAMP
, quindi scrivi il timestamp all'interno 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 colonna allow_commit_timestamp
consente di memorizzare in modo atomico il timestamp del commit in una colonna.
Utilizzando i timestamp dei commit memorizzati nelle tabelle, puoi determinare l'ordine esatto delle mutazioni e creare funzionalità come i log delle modifiche.
Per inserire i timestamp dei commit nel database:
Crea una colonna di tipo
TIMESTAMP
con l'opzione 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 inserimenti o aggiornamenti con DML, utilizza la funzione
PENDING_COMMIT_TIMESTAMP
per scrivere il timestamp del commit.Se esegui inserimenti o aggiornamenti con mutazioni, utilizza la stringa segnaposto
spanner.commit_timestamp()
per gli inserimenti o gli aggiornamenti della colonna del timestamp del commit. Puoi anche utilizzare la costante del 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 colonna, il timestamp del commit effettivo viene scritto nella colonna specificata (ad esempio, la colonna LastUpdateTime
). Potresti quindi utilizzare questo valore della colonna per creare una cronologia degli aggiornamenti della tabella.
Non è garantito che i valori del timestamp del 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 dei commit di Spanner hanno una granularità in microsecondi
e vengono convertiti in nanosecondi quando vengono memorizzati nelle colonne TIMESTAMP
.
Creare ed eliminare una colonna del timestamp del commit
Utilizza l'opzione della colonna allow_commit_timestamp
per aggiungere e rimuovere il supporto per i timestamp dei commit:
- Quando crei una nuova tabella, per specificare che una colonna supporta i timestamp dei commit.
- Quando modifichi una tabella esistente:
- per aggiungere una nuova colonna che supporti i timestamp dei commit.
- per modificare una colonna
TIMESTAMP
esistente in modo da supportare i timestamp dei commit, - per modificare una colonna
TIMESTAMP
esistente al fine di rimuovere il supporto del timestamp del commit
Chiavi e indici
Puoi utilizzare una colonna del timestamp del commit come colonna della chiave primaria o come colonna non chiave. Le chiavi principali 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 righe più recenti nella parte superiore della tabella. Forniscono un accesso rapido agli ultimi record.
L'opzione allow_commit_timestamp
deve essere coerente nelle chiavi principali delle tabelle principali e secondarie. Se l'opzione non è coerente tra le chiavi principali, Spanner restituisce un errore. L'unica volta che l'opzione può essere incoerente è quando crei o aggiorni lo schema.
L'utilizzo dei timestamp dei commit nei seguenti scenari crea hotspot che riducono il rendimento dei dati:
Colonna timestamp commit 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 velocità di scrittura ridotte. Non è previsto alcun sovraccarico delle prestazioni se i timestamp dei commit sono attivati nelle colonne non chiave non indicizzate.
Creare una colonna del timestamp del commit
Il seguente DDL crea una tabella con una colonna che supporta i timestamp dei 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 gli inserimenti e gli aggiornamenti. - La colonna può contenere solo valori passati. Per ulteriori informazioni, consulta Fornire un valore personalizzato per il timestamp.
L'opzione allow_commit_timestamp
è sensibile alle maiuscole.
Aggiungere 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)
Convertire una colonna timestamp in una colonna timestamp commit
Puoi convertire una colonna timestamp esistente in una colonna timestamp commit, ma per farlo è necessario che Spanner convalidi i valori timestamp esistenti nel passato. 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
statement ALTER TABLE
che include SET OPTIONS
. Per informazioni dettagliate, consulta
Data Definition Language.
Rimuovere l'opzione Timestamp commit
Se vuoi rimuovere il supporto del timestamp del 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 altera altre caratteristiche della colonna, ad esempio il tipo o la possibilità di inserire valori null (NOT NULL
). Ad esempio:
ALTER TABLE Performances ALTER COLUMN LastUpdateTime
SET OPTIONS (allow_commit_timestamp=null)
Scrivere un timestamp di commit utilizzando un'istruzione DML
Utilizza la funzione PENDING_COMMIT_TIMESTAMP
per scrivere il timestamp del commit in un'istruzione DML. Spanner seleziona il timestamp del commit al momento del 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#
Vai
Java
Node.js
PHP
Python
Ruby
Ruby
I timestamp dei commit possono essere scritti solo nelle colonne annotate con l'opzione allow_commit_timestamp=true
.
Se hai mutazioni nelle righe di più tabelle, devi specificare spanner.commit_timestamp()
(o la costante della libreria client) per la colonna dell'ora del commit in ogni tabella.
Esegui una query su una colonna del timestamp di commit
L'esempio seguente esegue una query sulla colonna del timestamp del commit della tabella.
C++
C#
Vai
Java
Node.js
PHP
Python
Ruby
Fornisci il tuo valore per la colonna del timestamp del commit
Puoi fornire un valore personalizzato per la colonna del timestamp del commit anziché passare spanner.commit_timestamp()
(o la costante della libreria client) come valore della colonna. Il valore deve essere un timestamp nel passato. Questa limitazione garantisce che la scrittura dei timestamp sia un'operazione economica e rapida. Il server
restituisce un errore FailedPrecondition
se viene specificato un timestamp futuro.
Creare un log delle modifiche
Supponiamo che tu voglia creare un log delle modifiche di ogni mutazione che si verifica in una tabella e poi utilizzarlo per il controllo. Un esempio è una tabella che memorizza la cronologia delle modifiche ai documenti di elaborazione testi. Il timestamp del commit semplifica la creazione del log delle modifiche, in quanto i timestamp possono imporre l'ordinamento delle voci del log delle modifiche. Puoi creare un log delle modifiche che memorizza la cronologia delle modifiche a un determinato documento utilizzando uno schema come 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'interlacciamento
della tabella DocumentsHistory
con la tabella Documents
consente la località dei dati e inserimenti e aggiornamenti più efficienti. Tuttavia, aggiunge anche il vincolo che le righe principali e secondarie devono essere eliminate insieme. Per mantenere le righe in DocumentHistory
dopo l'eliminazione delle righe in Documents
, non intercala le tabelle.
Ottimizzare le query sui dati recenti con i timestamp dei commit
I timestamp di commit consentono un'ottimizzazione di Spanner che può ridurre le operazioni di I/O di query durante il recupero dei dati scritti dopo un determinato momento.
Per attivare questa ottimizzazione, la clausola WHERE
di una query deve includere un
confronto tra la colonna del timestamp del commit di una tabella e un'ora specifica
fornita, con i seguenti attributi:
Fornisci l'ora specifica come espressione costante: un valore letterale, un parametro o una funzione i cui argomenti si valutano in costanti.
Confronta se il timestamp del commit è più recente rispetto al momento specificato tramite gli operatori
>
o>=
.Se vuoi, aggiungi ulteriori limitazioni alla clausola
WHERE
conAND
. L'estensione della clausola conOR
esclude la query 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 sfrutta l'ottimizzazione del timestamp del commit descritta in precedenza, perché esegue un confronto maggiore o uguale tra la colonna del timestamp del commit della tabella e un'espressione costante, in questo caso un valore letterale:
SELECT * FROM Performances WHERE LastUpdateTime >= "2022-05-01";
Anche la seguente query è idonea per l'ottimizzazione, poiché presenta un confronto maggiore tra il timestamp del commit e una funzione cuyostratti vengono tutti valutati come costanti durante l'esecuzione della query:
SELECT * FROM Performances
WHERE LastUpdateTime > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY);
Passaggi successivi
- Utilizza i timestamp dei commit per creare un log delle modifiche con Go.