Questo documento 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 su una colonna TIMESTAMP, quindi scrivi il timestamp come parte di ogni transazione.
Panoramica
Il timestamp di commit, basato sulla tecnologia TrueTime, è l'ora in cui viene eseguito il commit di una
transazione nel database. L'opzione della colonna allow_commit_timestamp consente di archiviare in modo atomico il timestamp di commit in una colonna.
Utilizzando i timestamp di commit archiviati nelle tabelle, puoi determinare l'ordinamento esatto delle mutazioni e creare funzionalità come i log delle modifiche.
Per inserire i timestamp di commit nel database:
Crea una colonna di tipo
TIMESTAMPcon l'opzione della colonnaallow_commit_timestampimpostata sutruenella 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_TIMESTAMPper scrivere il timestamp di commit.Se esegui inserimenti o aggiornamenti con le mutazioni, utilizza la stringa segnaposto
spanner.commit_timestamp()negli inserimenti o negli aggiornamenti della colonna del timestamp di commit. Puoi anche utilizzare la costante del timestamp di 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). Puoi quindi utilizzare 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 di Spanner hanno una granularità di microsecondi e vengono convertiti in nanosecondi quando vengono archiviati nelle colonne TIMESTAMP.
Creare ed eliminare una colonna del timestamp di commit
Utilizza l'opzione della colonna allow_commit_timestamp per aggiungere e rimuovere il supporto per i timestamp di 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 supporta i timestamp di commit,
- per modificare una colonna
TIMESTAMPesistente in modo che supporti i timestamp di commit, - per modificare una colonna
TIMESTAMPesistente in modo da rimuovere il supporto per i timestamp di commit
Chiavi e indici
Puoi utilizzare una colonna del timestamp di commit come colonna della chiave primaria o come colonna non chiave. Le chiavi primarie possono essere definite come ASC o DESC.
ASC(valore 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 ai record più recenti.
L'opzione allow_commit_timestamp deve essere coerente tra le chiavi primarie delle tabelle padre e figlio. Se l'opzione non è coerente tra le chiavi primarie, Spanner restituisce un errore. L'opzione può essere incoerente solo quando crei o aggiorni lo schema.
L'utilizzo dei timestamp di commit nei seguenti scenari crea hotspot che riducono il rendimento dei dati:
Colonna del timestamp di 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 il rendimento dei dati, anche con tassi di scrittura bassi. Non si verifica alcun sovraccarico di prestazioni se i timestamp di commit sono abilitati nelle colonne non chiave che non sono indicizzate.
Creare una colonna del timestamp di 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 inserimenti e aggiornamenti. - La colonna può contenere solo valori nel passato. Per ulteriori informazioni, vedi Fornire il proprio valore per il timestamp.
L'opzione allow_commit_timestamp fa distinzione tra maiuscole e minuscole.
Aggiungere una colonna del timestamp di commit a una tabella esistente
Per aggiungere una colonna del timestamp di 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 del timestamp in una colonna del timestamp di commit
Puoi convertire una colonna del timestamp esistente in una colonna del timestamp di commit, ma in questo caso Spanner deve verificare che i valori del timestamp esistenti siano 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'istruzione ALTER TABLE che include SET OPTIONS. Per maggiori dettagli, vedi
Linguaggio di definizione dei dati.
Rimuovere l'opzione del timestamp di commit
Se vuoi rimuovere il supporto per i timestamp di commit da una colonna, utilizza l'opzione allow_commit_timestamp=null in un'istruzione ALTER TABLE. Il comportamento del timestamp di commit viene rimosso, ma la colonna rimane un timestamp. La modifica dell'opzione non altera altre caratteristiche della colonna, come il tipo o la nullabilità (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 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
PENDING_COMMIT_TIMESTAMP
funzione per scrivere il timestamp di commit nella LastUpdateTime colonna.
C++
C#
Vai
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 hai mutazioni sulle righe di più tabelle, devi specificare spanner.commit_timestamp() (o la costante della libreria client) per la colonna del timestamp di commit in ogni tabella.
Eseguire una query su una colonna del timestamp di commit
Il seguente esempio esegue una query sulla colonna del timestamp di commit della tabella.
C++
C#
Vai
Java
Node.js
PHP
Python
Ruby
Fornire il proprio valore per la colonna del timestamp di commit
Puoi fornire il tuo valore 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 nel passato. Questa limitazione garantisce che la scrittura dei timestamp sia un'operazione rapida ed economica. 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 l'audit. Un esempio è una tabella che memorizza la cronologia delle modifiche ai documenti di elaborazione testi. Il timestamp di commit semplifica la creazione del log delle modifiche, perché i timestamp possono applicare l'ordinamento delle voci del log delle modifiche. Puoi creare un log delle modifiche che memorizza la cronologia delle modifiche di un determinato documento utilizzando uno schema come il seguente esempio:
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 di commit nella colonna Ts. L'interleaving
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 padre e figlio devono essere eliminate insieme. Per conservare le righe in DocumentHistory dopo l'eliminazione delle righe in Documents, non eseguire l'interleaving delle tabelle.
Ottimizzare 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'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 vengono valutati come costanti.
Confronta se il timestamp di commit è più recente dell'ora specificata, tramite gli operatori
>o>=.(Facoltativo) Aggiungi ulteriori limitazioni alla clausola
WHEREconAND. L'estensione della clausola conORnon consente l'ottimizzazione della query.
Ad esempio, considera la seguente tabella Performances, che include una colonna del 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);
Questa query beneficia dell'ottimizzazione del timestamp di commit descritta in precedenza, perché include un confronto maggiore o uguale a 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";
Anche la seguente query è idonea per l'ottimizzazione, poiché include un confronto maggiore di tra il timestamp di commit e una funzione i cui argomenti vengono 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 di commit per creare un log delle modifiche con Go.