Cet article explique comment écrire un code temporel de commit pour chaque insertion et mise à jour que vous effectuez avec Spanner.
Présentation des horodatages de commit
L'horodatage de commit, basé sur la technologie TrueTime, est l'heure à laquelle une transaction est reçue dans la base de données. Vous pouvez stocker le commit de manière atomique l'horodatage d'une transaction dans une colonne. À l'aide des horodatages de commit stockés dans les tables, vous pouvez déterminer l'ordre exact des mutations et créer des fonctionnalités telles que les journaux des modifications.
Pour insérer des horodatages de commit dans votre base de données, procédez comme suit :
Créez une colonne de type
SPANNER.COMMIT_TIMESTAMP
. Exemple :CREATE TABLE Performances ( ... LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, ... PRIMARY KEY (...) ) ;
Si vous effectuez des insertions ou des mises à jour en langage LMD, utilisez la fonction
SPANNER.PENDING_COMMIT_TIMESTAMP()
pour écrire l'horodatage de commit.Si vous effectuez des insertions ou des mises à jour avec des instructions préparées ou des mutations, utilisez la chaîne d'espace réservé
SPANNER.COMMIT_TIMESTAMP()
pour votre la colonne d'horodatage de commit. Vous pouvez également utiliser Constante d'horodatage de commit fournie par la bibliothèque cliente. Par exemple, ce dans le client Java estValue.COMMIT_TIMESTAMP
.
Lorsque Spanner reçoit la transaction en utilisant ces espaces réservés comme valeurs de colonne, l'horodatage de commit réel est écrit dans la colonne spécifiée. Vous pouvez ensuite utiliser cette valeur de colonne pour créer un historique des mises à jour de la table.
Le caractère unique des valeurs d'horodatage de commit n'est pas garanti. Les transactions qui écrivent dans des ensembles de champs ne se chevauchant pas peuvent avoir le même horodatage. Les transactions qui écrivent dans des ensembles de champs qui se chevauchent ont des horodatages uniques.
Les horodatages de commit Spanner sont d'une précision qui s'exprime en microsecondes et sont convertis en nanosecondes lorsqu'ils sont stockés dans des colonnes SPANNER.COMMIT_TIMESTAMP
.
Clés et index
Vous pouvez utiliser une colonne d'horodatage de commit en tant que colonne de clé primaire ou en tant que colonne non clé. Les clés primaires peuvent être définies comme ASC
ou DESC
.
ASC
(valeur par défaut) : les clés croissantes sont idéales pour répondre aux requêtes à partir d'une heure spécifique.DESC
: les clés décroissantes conservent les dernières lignes en haut de la table. Elles fournissent un accès rapide aux derniers enregistrements.
Éviter les hotspots
L'utilisation d'horodatages de commit dans les scénarios suivants engendre des problèmes de hotspotting et réduit les performances de traitement des données :
Colonne d'horodatage de commit en tant que première partie de la clé primaire d'une table
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId bigint NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;
Colonne de clé primaire du code temporel de commit en tant que première partie d'un index secondaire.
CREATE INDEX UsersByLastAccess ON Users(LastAccess)
ou
CREATE INDEX UsersByLastAccessAndName ON Users(LastAccess, FirstName)
Les hotspots réduisent les performances de traitement des données, même avec des vitesses d'écriture faibles. L'activation de l'horodatage de commit sur des colonnes non clés non indexées n'impacte pas les performances.
Ajouter une colonne d'horodatage de commit à une table existante
Pour ajouter une colonne d'horodatage de commit à une table existante, utilisez l'instruction ALTER TABLE
. Par exemple, pour ajouter une colonne LastUpdateTime
à la table Performances
, utilisez l'instruction suivante :
ALTER TABLE Performances ADD COLUMN LastUpdateTime SPANNER.COMMIT_TIMESTAMP;
Écrire un horodatage de commit à l'aide d'une instruction LMD
Pour écrire l'horodatage de commit dans une instruction LMD, utilisez la fonction SPANNER.PENDING_COMMIT_TIMESTAMP()
. Spanner sélectionne le code temporel de commit lorsque la transaction
des commits.
L'instruction LMD suivante met à jour la colonne LastUpdateTime
de la table Performances
avec l'horodatage de commit :
UPDATE Performances SET LastUpdateTime = SPANNER.PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
Insérer une ligne à l'aide d'une mutation
Lors de l'insertion d'une ligne, Spanner n'écrit que la valeur d'horodatage de commit
si vous incluez la colonne dans la liste des colonnes et transmettez la valeur
Chaîne d'espace réservé spanner.commit_timestamp()
(ou constante de la bibliothèque cliente)
comme valeur. Exemple :
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Si des mutations sont présentes sur des lignes dans plusieurs tables, vous devez spécifier spanner.commit_timestamp()
(ou une constante de la bibliothèque cliente) pour la colonne d'horodatage de commit de chaque table.
Mettre à jour une ligne à l'aide d'une mutation
Lors de la mise à jour d'une ligne, Spanner n'écrit la valeur d'horodatage de commit que si vous incluez la colonne dans la liste des colonnes et transmettez la chaîne d'espace réservé spanner.commit_timestamp()
(ou constante de la bibliothèque cliente) comme valeur. Vous ne pouvez pas mettre à jour la clé primaire d'une ligne. Pour mettre à jour la clé primaire, supprimez la ligne existante et créez-en une nouvelle.
Par exemple, pour mettre à jour une colonne d'horodatage de commit nommée LastUpdateTime
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Si des mutations sont présentes sur des lignes dans plusieurs tables, vous devez spécifier spanner.commit_timestamp()
(ou la constante de la bibliothèque cliente) pour la colonne d'horodatage de commit de chaque table.
Interroger une colonne d'horodatage de commit
L'exemple suivant interroge la colonne d'horodatage de commit de la table.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Fournir votre propre valeur pour la colonne d'horodatage
Dans votre code, vous pouvez fournir votre propre valeur pour la colonne d'horodatage de commit au lieu de transmettre spanner.commit_timestamp()
(ou la constante de la bibliothèque cliente disponible) en tant que valeur de colonne. La valeur doit être un horodatage antérieur au moment actuel. Cette restriction garantit que l'écriture d'horodatages est une opération rapide et peu coûteuse. Un moyen simple de confirmer qu'une valeur est antérieure au moment actuel consiste à la comparer à la valeur renvoyée par la fonction SQL CURRENT_TIMESTAMP
.
Le serveur renvoie une erreur FailedPrecondition
si un horodatage futur est spécifié.
Créer un journal de modifications
Supposons que vous souhaitiez créer un journal des modifications pour chaque mutation qui se produit dans une table, puis l'utiliser pour un audit. Prenons l'exemple d'une table qui stocke l'historique des modifications apportées aux documents de traitement de texte. L'horodatage de commit facilite la création du journal des modifications, car les horodatages peuvent imposer le classement des modifications des entrées. Vous pouvez créer un journal des modifications qui stocke l'historique des modifications apportées à un document donné à l'aide d'un schéma semblable à l'exemple suivant :
CREATE TABLE Documents (
UserId int8 NOT NULL,
DocumentId int8 NOT NULL,
Contents text NOT NULL,
PRIMARY KEY (UserId, DocumentId)
);
CREATE TABLE DocumentHistory (
UserId int8 NOT NULL,
DocumentId int8 NOT NULL,
Ts SPANNER.COMMIT_TIMESTAMP NOT NULL,
Delta text,
PRIMARY KEY (UserId, DocumentId, Ts)
) INTERLEAVE IN PARENT Documents;
Pour créer un journal des modifications, insérez une nouvelle ligne dans la table DocumentHistory
, dans la même transaction que celle dans laquelle vous insérez ou mettez à jour une ligne dans la table Document
. Lors de l'insertion
de la nouvelle ligne dans DocumentHistory
, utilisez l'espace réservé
spanner.commit_timestamp()
(ou constante de la bibliothèque cliente) pour indiquer
Spanner pour écrire l'horodatage de commit dans la colonne Ts
. Si vous entrelacez la table DocumentsHistory
avec la table Documents
, la localité des données, les insertions et les mises à jour seront plus efficaces. Cependant, ce procédé ajoute également une contrainte : les lignes parents et enfants doivent être supprimées ensemble. Pour garder les lignes dans la table DocumentHistory
après la suppression des lignes de la table Documents
, n'entrelacez pas les tables.
Optimiser les requêtes de données récentes avec des horodatages de commit
Les horodatages de commit permettent une optimisation Spanner qui peut réduire les E/S de requête lors de la récupération de données écrites après un certain temps.
Pour activer cette optimisation, la clause WHERE
d'une requête doit inclure une comparaison entre la colonne d'horodatage de validation d'une table et une heure spécifique que vous fournissez, avec les attributs suivants :
Indiquez l'heure spécifique en tant qu'expression constante: un littéral, une ou une fonction dont les arguments sont évalués sur des constantes.
Comparez si l'horodatage du commit est plus récent que l'heure donnée, à l'aide des opérateurs
>
ou>=
.Vous pouvez également ajouter des restrictions supplémentaires à la clause
WHERE
avecAND
. L'extension de la clause avecOR
disqualifie la requête de ce l'optimisation.
Prenons l'exemple de la table Performances
suivante, qui inclut une colonne d'horodatage de commit :
CREATE TABLE Performances (
SingerId bigint NOT NULL,
VenueId bigint NOT NULL,
EventDate timestamp with time zone NOT NULL,
Revenue bigint,
LastUpdateTime spanner.commit_timestamp,
PRIMARY KEY(SingerId, VenueId, EventDate)
);
Cette requête bénéficie de l'optimisation du code temporel de commit décrite plus tôt, car il y a une comparaison supérieure ou égale à entre la colonne d'horodatage de commit de la table et une expression constante. case, un littéral:
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';