Cette page explique comment insérer, mettre à jour et supprimer des données Spanner à l'aide d'instructions LMD (langage de manipulation de données). Vous pouvez exécuter des instructions LMD à l'aide des bibliothèques clientes, de la consoleGoogle Cloud et de la Google Cloud CLI. Vous pouvez exécuter des instructions LMD partitionnées à l'aide des bibliothèques clientes et de la gcloud CLI.
Pour obtenir la documentation de référence complète sur la syntaxe LMD, consultez Syntaxe du langage de manipulation de données pour les bases de données de dialecte GoogleSQL ou Langage de manipulation de données PostgreSQL pour les bases de données de dialecte PostgreSQL.
Utiliser le LMD
Le LMD accepte les instructions INSERT, UPDATE et DELETE dans la consoleGoogle Cloud , gcloud CLI et les bibliothèques clientes.
Verrouillage
Les instructions LMD sont exécutées dans les transactions de lecture-écriture. Lorsque Spanner lit des données, il acquiert des verrous de lecture partagés sur des parties limitées des plages de lignes que vous lisez. Plus précisément, il n'acquiert ces verrous que sur les colonnes auxquelles vous accédez. Les verrous peuvent inclure des données qui ne remplissent pas la condition de filtre de la clause WHERE.
Lorsque Spanner modifie des données à l'aide d'instructions LMD, il acquiert des verrous exclusifs sur les données spécifiques que vous modifiez. De plus, il acquiert des verrous partagés de la même manière que lorsque vous consultez des données. Si votre requête inclut de grandes plages de lignes ou une table entière, les verrous partagés peuvent empêcher d'autres transactions de progresser en parallèle.
Pour modifier les données aussi efficacement que possible, utilisez une clause WHERE qui permet à Spanner de ne lire que les lignes nécessaires. Pour ce faire, appliquez un filtre sur la clé primaire ou sur la clé d'un index secondaire. La clause WHERE limite le champ d'application des verrous partagés et permet à Spanner de traiter la mise à jour plus efficacement.
Par exemple, imaginons que l'un des musiciens de la table Singers change de prénom et que vous deviez mettre à jour ce prénom dans votre base de données. Vous pouvez exécuter l'instruction LMD suivante, mais elle force Spanner à analyser l'intégralité de la table et acquiert des verrous partagés qui couvrent l'intégralité de la table. Par conséquent, Spanner doit lire plus de données que nécessaire, et les transactions simultanées ne peuvent pas modifier les données en parallèle :
-- ANTI-PATTERN: SENDING AN UPDATE WITHOUT THE PRIMARY KEY COLUMN
-- IN THE WHERE CLAUSE
UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards";
Pour optimiser l'opération de mise à jour, incluez la colonne SingerId dans la clause WHERE. La colonne SingerId est la seule colonne de clé primaire pour la table Singers :
-- ANTI-PATTERN: SENDING AN UPDATE THAT MUST SCAN THE ENTIRE TABLE
UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards"
S'il n'y a pas d'index sur FirstName ou LastName, vous devez analyser l'intégralité de la table pour trouver les chanteurs cibles. Si vous ne souhaitez pas ajouter d'index secondaire pour rendre la mise à jour plus efficace, incluez la colonne SingerId dans la clause WHERE.
La colonne SingerId est la seule colonne de clé primaire de la table Singers. Pour le trouver, exécutez SELECT dans une transaction distincte en lecture seule avant la transaction de mise à jour :
SELECT SingerId
FROM Singers
WHERE FirstName = "Marc" AND LastName = "Richards"
-- Recommended: Including a seekable filter in the where clause
UPDATE Singers SET FirstName = "Marcel"
WHERE SingerId = 1;
Simultanéité
Spanner exécute de manière séquentielle toutes les instructions SQL (SELECT, INSERT, UPDATE et DELETE) d'une transaction. Elles ne sont pas exécutées simultanément. La seule exception est que Spanner peut exécuter plusieurs instructions SELECT simultanément, car il s'agit d'opérations en lecture seule.
Limites de transaction
Une transaction qui comprend des instructions LMD est soumise aux mêmes limites que toute autre transaction. Si vous devez effectuer des modifications à grande échelle, envisagez d'utiliser le LMD partitionné.
La limite de mutations est appliquée différemment selon que vous utilisez des instructions LMD ou l'API Mutation :
Instructions LMD : la limite de 80 000 mutations (y compris les index) est appliquée par instruction et est réinitialisée à la fin de chaque instruction. Si une seule instruction LMD dépasse cette limite, elle échoue et renvoie une erreur
BadUsage. Toutefois, une transaction peut dépasser 80 000 modifications en contenant plusieurs instructions LMD, à condition que chaque instruction individuelle reste en dessous de cette limite.API Mutation : les mutations utilisant l'API Mutation ne peuvent être appliquées que dans le cadre de l'opération de commit, et non au milieu d'une transaction, contrairement au LMD. La limite de 80 000 mutations (index compris) est cumulative pour toutes les mutations du commit. Si une transaction utilise des mutations (seules ou combinées avec le LMD), cette limite cumulative s'applique à toutes les mutations du commit.
Taille des transactions : toutes les transactions sont limitées à une taille de 100 Mio. Pour le LMD, si les instructions d'une transaction entraînent une transaction de plus de 100 Mio, l'instruction qui dépasse la limite échoue avec une erreur
BadUsage. Les mutations effectuées à l'aide du LMD ne sont pas comptabilisées dans la limite de 80 000 instructions, mais elles sont comptabilisées dans la limite de taille de transaction lorsqu'elles sont validées.
Exécuter des instructions dans la console Google Cloud
Suivez les étapes ci-dessous pour exécuter une instruction LMD dans la consoleGoogle Cloud .
Accédez à la page Instances de Spanner.
Sélectionnez votre projet dans la liste déroulante de la barre d'outils.
Cliquez sur le nom de l'instance contenant votre base de données pour accéder à la page Détails de l'instance.
Dans l'onglet Vue d'ensemble, cliquez sur le nom de votre base de données. La page Détails de la base de données s'affiche.
Cliquez sur Spanner Studio.
Entrez une instruction LMD. Par exemple, l'instruction suivante ajoute une ligne à la table
Singers.INSERT Singers (SingerId, FirstName, LastName) VALUES (1, 'Marc', 'Richards')Cliquez sur Exécuter la requête. La console Google Cloud affiche le résultat.
Exécuter des instructions avec la gcloud CLI
Pour exécuter des instructions LMD, utilisez la commande gcloud spanner databases execute-sql. L'exemple suivant ajoute une ligne à la table Singers.
gcloud spanner databases execute-sql example-db --instance=test-instance \ --sql="INSERT Singers (SingerId, FirstName, LastName) VALUES (1, 'Marc', 'Richards')"
Modifier des données à l'aide de la bibliothèque cliente
Pour exécuter des instructions LMD à l'aide de la bibliothèque cliente :
- Créez une transaction en lecture/écriture.
- Appelez la méthode de la bibliothèque cliente pour une exécution LMD, et transmettez l'instruction LMD.
- Utilisez la valeur de retour de la méthode d'exécution LMD pour obtenir le nombre de lignes insérées, mises à jour ou supprimées.
L'exemple de code suivant insère une ligne dans la table Singers.
C++
Vous utilisez la fonction ExecuteDml() pour exécuter une instruction LMD.
C#
L'exécution d'une instruction LMD s'effectue via la méthode ExecuteNonQueryAsync().
Go
L'exécution d'une instruction LMD s'effectue via la méthode Update().
Java
L'exécution d'une instruction LMD s'effectue via la méthode executeUpdate().
Node.js
L'exécution d'une instruction LMD s'effectue via la méthode runUpdate().
PHP
L'exécution d'une instruction LMD s'effectue via la méthode executeUpdate().
Python
L'exécution d'une instruction LMD s'effectue via la méthode execute_update().
Ruby
L'exécution d'une instruction LMD s'effectue via la méthode execute_update().
L'exemple de code suivant met à jour la colonne MarketingBudget de la table Albums en fonction d'une clause WHERE.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
L'exemple de code suivant supprime toutes les lignes de la table Singers pour lesquelles la colonne FirstName contient Alice.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
L'exemple suivant, destiné uniquement aux bases de données utilisant le dialecte GoogleSQL, utilise une instruction STRUCT avec des paramètres liés pour mettre à jour la valeur LastName dans les lignes filtrées par FirstName et LastName.
GoogleSQL
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Modifier des données avec les instructions LMD RETURNING
La clause THEN RETURN (bases de données utilisant le dialecte GoogleSQL) ou la clause RETURNING (bases de données utilisant le dialecte PostgreSQL) est destinée aux scénarios dans lesquels vous souhaitez récupérer des données à partir de lignes modifiées. Cela est particulièrement utile lorsque vous souhaitez afficher des valeurs non spécifiées dans les instructions LMD, les valeurs par défaut ou les colonnes générées.
Pour exécuter des instructions LMD de renvoi à l'aide de la bibliothèque cliente :
- Créez une transaction en lecture/écriture.
- Appelez la méthode de la bibliothèque cliente pour l'exécution de la requête et transmettez l'instruction LMD de retour pour obtenir les résultats.
L'exemple de code suivant insère une nouvelle ligne dans la table Singers et renvoie la colonne générée FullName des enregistrements insérés.
GoogleSQL
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
PostgreSQL
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
L'exemple de code suivant met à jour la colonne MarketingBudget de la table Albums en fonction d'une clause WHERE et renvoie la colonne MarketingBudget modifiée des enregistrements mis à jour.
GoogleSQL
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
PostgreSQL
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
L'exemple de code suivant supprime toutes les lignes de la table Singers où la colonne FirstName est Alice, et renvoie les colonnes SingerId et FullName des enregistrements supprimés.
GoogleSQL
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
PostgreSQL
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Lire les données écrites dans la même transaction
Les modifications que vous effectuez à l'aide d'instructions LMD sont visibles pour les instructions suivantes dans la même transaction. Cette méthode est différente des mutations, avec lesquelles les modifications ne sont visibles que lors du commit de la transaction.
Spanner vérifie les contraintes après chaque instruction LMD. Cette méthode est différente de l'utilisation de mutations, où Spanner met en mémoire tampon les mutations dans le client jusqu'au commit et vérifie les contraintes au moment du commit. L'évaluation des contraintes après chaque instruction permet à Spanner de garantir que les données renvoyées par une instruction LMD sont cohérentes avec le schéma.
L'exemple ci-dessous permet de mettre à jour une ligne de la table Singers, puis d'exécuter une instruction SELECT pour afficher les nouvelles valeurs.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Obtenir le plan de requête
Vous pouvez récupérer un plan de requête à l'aide de la console Google Cloud , des bibliothèques clientes et de la gcloud CLI.
Utiliser le LMD partitionné
Le LMD partitionné est conçu pour les mises à jour et les suppressions groupées, notamment les nettoyages et les remplissages périodiques.
Exécuter des instructions avec la gcloud CLI
Pour exécuter une instruction LMD partitionnée, utilisez la commande gcloud spanner databases execute-sql avec l'option --enable-partitioned-dml. L'exemple suivant met à jour les lignes de la table Albums.
gcloud spanner databases execute-sql example-db \ --instance=test-instance --enable-partitioned-dml \ --sql='UPDATE Albums SET MarketingBudget = 0 WHERE MarketingBudget IS NULL'
Modifier des données à l'aide de la bibliothèque cliente
L'exemple de code suivant met à jour la colonne MarketingBudget de la table Albums.
C++
Pour exécuter une instruction LMD partitionnée, utilisez la fonction ExecutePartitionedDml().
C#
Vous utilisez la méthode ExecutePartitionedUpdateAsync() pour exécuter une instruction LMD partitionnée.
Go
Vous utilisez la méthode PartitionedUpdate() pour exécuter une instruction LMD partitionnée.
Java
Vous utilisez la méthode executePartitionedUpdate() pour exécuter une instruction LMD partitionnée.
Node.js
Vous utilisez la méthode runPartitionedUpdate() pour exécuter une instruction LMD partitionnée.
PHP
Vous utilisez la méthode executePartitionedUpdate() pour exécuter une instruction LMD partitionnée.
Python
Vous utilisez la méthode execute_partitioned_dml() pour exécuter une instruction LMD partitionnée.
Ruby
Vous utilisez la méthode execute_partitioned_update() pour exécuter une instruction LMD partitionnée.
L'exemple de code suivant supprime les lignes de la table Singers, en fonction de la colonne SingerId.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Utiliser le LMD par lot
Si vous devez éviter le temps de latence supplémentaire occasionné par l'envoi de plusieurs requêtes en série, utilisez le LMD par lots pour envoyer plusieurs instructions INSERT, UPDATE ou DELETE au sein d'une même transaction :
C++
Utilisez la fonction ExecuteBatchDml() pour exécuter une liste d'instructions LMD.
C#
Utilisez la méthode connection.CreateBatchDmlCommand() pour créer votre commande par lot, puis la méthode Add pour ajouter des instructions LMD. Enfin, exécutez l'ensemble à l'aide de la méthode ExecuteNonQueryAsync().
Go
Utilisez la méthode BatchUpdate() pour exécuter un tableau d'objets constitué d'instructions LMD Statement.
Java
Utilisez la méthode transaction.batchUpdate() pour exécuter un objet ArrayList constitué d'instructions LMD Statement.
Node.js
Utilisez transaction.batchUpdate() pour exécuter une liste d'instructions LMD.
PHP
Utilisez executeUpdateBatch() pour créer une liste d'instructions LMD, puis utilisez commit() pour exécuter les instructions.
Python
Utilisez transaction.batch_update() pour exécuter plusieurs chaînes correspondant à des instructions LMD.
Ruby
Utilisez transaction.batch_update pour exécuter plusieurs chaînes correspondant à des instructions LMD.