Cette page explique comment écrire un code temporel de commit pour chaque opération d'insertion et de mise à jour effectuée avec Spanner dans les bases de données utilisant le dialecte PostgreSQL.
Insérer des codes temporels de commit
Le code temporel de commit, basé sur la technologie TrueTime, est l'heure à laquelle une transaction est validée dans la base de données. Vous pouvez stocker de manière atomique le code temporel de commit d'une transaction dans une colonne. À l'aide des codes temporels 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 codes temporels 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 le code temporel de commit.Si vous effectuez des insertions ou des mises à jour avec des mutations ou des instructions préparées, utilisez la chaîne d'espace réservé
SPANNER.COMMIT_TIMESTAMP()pour la colonne de code temporel de commit. Vous pouvez également utiliser la constante de code temporel de commit fournie par la bibliothèque cliente. Par exemple, cette constante dans le client Java estValue.COMMIT_TIMESTAMP.
Lorsque Spanner valide la transaction en utilisant ces espaces réservés comme valeurs de colonne, le code temporel 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 de code temporel de commit n'est pas garanti. Les transactions qui écrivent dans des ensembles de champs ne se chevauchant pas peuvent avoir le même code temporel. Les transactions qui écrivent dans des ensembles de champs qui se chevauchent ont des codes temporels uniques.
Les codes temporels 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 de code temporel 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 de codes temporels de commit dans les scénarios suivants engendre des problèmes de hotspotting et réduit les performances de traitement des données :
Colonne de code temporel 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 de 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 codes temporels de commit sur des colonnes non clé non indexées n'impacte pas les performances.
Ajouter une colonne de code temporel de commit à une table existante
Pour ajouter une colonne de code temporel 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 code temporel de commit à l'aide d'une instruction LMD
Pour écrire le code temporel de commit dans une instruction LMD, utilisez la fonction SPANNER.PENDING_COMMIT_TIMESTAMP(). Cloud Spanner sélectionne le code temporel de commit lorsque la transaction est validée.
L'instruction LMD suivante met à jour la colonne LastUpdateTime de la table Performances avec le code temporel 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 la valeur de code temporel 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 la 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 de code temporel 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 de code temporel 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 la 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 de code temporel 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 de code temporel de commit de chaque table.
Interroger une colonne de code temporel de commit
L'exemple suivant interroge la colonne de code temporel de commit de la table.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Fournir votre propre valeur pour la colonne de code temporel de commit
Dans votre code, vous pouvez fournir votre propre valeur pour la colonne de code temporel de commit au lieu de transmettre spanner.commit_timestamp() (ou la constante de la bibliothèque cliente disponible) comme valeur de colonne. La valeur doit être un code temporel antérieur au moment actuel. Cette restriction garantit que l'écriture de codes temporels est une opération rapide et peu coûteuse. Un moyen 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 code temporel futur est spécifié.
Créer un journal des 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. Le code temporel de commit facilite la création du journal des modifications, car les codes temporels peuvent appliquer 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 la table DocumentHistory, utilisez l'espace réservé spanner.commit_timestamp() (ou la constante de la bibliothèque cliente) pour indiquer à Spanner d'écrire le code temporel de commit dans la colonne Ts.
L'entrelacement de la table DocumentsHistory avec la table Documents permet de localiser les données et d'améliorer l'efficacité des insertions et des mises à jour. Cependant, ce procédé ajoute également une contrainte : les lignes parents et enfants doivent être supprimées ensemble. Pour conserver les lignes de 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 codes temporels de commit
Les codes temporels de commit optimisent votre base de données Spanner et peuvent réduire les E/S des requêtes lors de la récupération de données écrites après une heure spécifique.
Pour activer cette optimisation, la clause WHERE d'une requête doit inclure une comparaison entre la colonne de code temporel de commit d'une table et une heure spécifique que vous fournissez, avec les attributs suivants :
Indiquez l'heure spécifique sous la forme d'une expression constante : un littéral, un paramètre ou une fonction dont les arguments renvoient à des constantes.
Comparez le code temporel de commit à l'heure indiquée à l'aide des opérateurs
>ou>=.Vous pouvez également ajouter d'autres restrictions à la clause
WHEREavecAND. Si vous étendez la clause avecOR, la requête ne pourra pas bénéficier de cette optimisation.
Par exemple, prenons la table Performances suivante, qui inclut une colonne de code temporel 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 de code temporel de commit décrite précédemment, car elle comporte une comparaison supérieure ou égale entre la colonne de code temporel de commit de la table et une expression constante (dans ce cas, un littéral) :
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';