Comparer les LMD et les mutations

Le langage de manipulation de données (LMD) et les mutations sont deux API dans Spanner qui vous permettent de modifier les données. Chacun offre des fonctionnalités de manipulation de données similaires. Cette page compare les deux approches.

Qu'est-ce que le langage de manipulation de données (LMD) ?

Le langage de manipulation de données (LMD) de Spanner vous permet manipuler les données de vos tables de base de données à l'aide des méthodes INSERT, UPDATE et DELETE. . Vous pouvez exécuter des instructions LMD à l'aide des bibliothèques clientes, de la console Google Cloud et de gcloud spanner.

Spanner propose les deux implémentations d'exécution LMD suivantes, chacune avec des propriétés différentes.

  • LMD standard : adapté aux charges de travail OLTP (Online Transaction Processing) standards.

    Pour en savoir plus et obtenir des exemples de code, consultez la section Utiliser le LMD.

  • LMD partitionné : conçu pour les mises à jour et les suppressions de manière groupée, comme dans les exemples suivants.

    • Nettoyage périodique et récupération de mémoire. Il s'agit par exemple de supprimer d'anciennes lignes ou de définir des colonnes sur NULL.

    • Remplissage de nouvelles colonnes avec des valeurs par défaut. Par exemple, on utilise une fonction UPDATE pour définir la valeur d'une nouvelle colonne sur False lorsqu'elle est NULL.

    Pour en savoir plus et obtenir des exemples de code, consultez la section Utiliser le LMD partitionné.

    Vous pouvez utiliser des écritures par lot pour un grand nombre d'opérations d'écriture sans opérations de lecture qui ne nécessitent pas de transactions atomiques. Pour en savoir plus, consultez la section Modifier des données à l'aide d'écritures par lot.

Que sont les mutations ?

Une mutation représente une séquence d'opérations (insertions, mises à jour, suppressions, etc.) que Spanner applique de manière atomique à différentes lignes et tables d'une base de données. Vous pouvez inclure des opérations qui s'appliquent à différentes lignes ou à différentes tables d'une mutation. Après avoir défini une ou plusieurs mutations contenant une ou plusieurs écritures, vous devez appliquer la mutation pour valider les écritures. Chaque modification est appliquée dans l'ordre dans lequel elles ont été ajoutées à la mutation.

Pour en savoir plus et obtenir des exemples de code, consultez la section Insérer, mettre à jour et supprimer des données à l'aide de mutations.

Comparaison des fonctionnalités entre LMD et mutations

Le tableau suivant récapitule la prise en charge des opérations et des fonctionnalités courantes de la base de données par le LMD et les mutations.

Opérations LMD Mutations
Insérer des données Compatible Compatible
Supprimer des données Compatible Compatible
Mettre à jour des données Compatible Compatible
Insérer ou ignorer des données Compatible Non compatible
Lecture de vos écritures (RYW) Compatible Non compatible
Insérer ou mettre à jour des données (upsert) Compatible Compatible
Syntaxe SQL Compatible Non compatible
Vérification des contraintes Après chaque instruction Au moment du commit

Le LMD et les mutations ne prennent pas en charge les fonctionnalités suivantes:

  • Read Your Writes: lecture des résultats non validés dans un transaction. Les modifications que vous apportez à l'aide d'instructions LMD sont visibles les instructions suivantes dans la même transaction. Cette méthode est différente des mutations, avec lesquelles les modifications ne sont visibles dans les opérations de lecture (y-compris les lectures effectuées dans la même transaction) que lors du commit de la transaction. En effet, les mutations d'une transaction sont mises en mémoire tampon côté client (localement) et envoyées au serveur dans le cadre de l'opération de commit. En conséquence, les mutations dans la requête de commit ne sont pas visibles pour les instructions SQL ou LMD dans la même transaction.

  • Vérification des contraintes: Spanner vérifie les contraintes toutes les Instruction LMD. Ce comportement est différent de celui applicable aux mutations : Spanner place ces mutations en tampon dans le client jusqu'au commit, puis vérifie les contraintes au moment du commit. L'évaluation des contraintes une fois que chaque instruction LMD autorise Spanner pour garantir que les données renvoyées par une requête ultérieure dans le même renvoie des données cohérentes avec le schéma.

  • Syntaxe SQL : le LMD fournit une méthode traditionnelle pour manipuler les données. Vous pouvez réutiliser les compétences SQL pour modifier les données à l'aide de l'API LMD.

Bonne pratique - éviter de mélanger LMD et mutation dans la même transaction

Si une transaction contient à la fois des instructions LMD et des mutations dans le commit Spanner exécute les instructions LMD avant les mutations. Pour éviter de devoir prendre en compte l'ordre d'exécution dans le code de votre bibliothèque cliente, vous devez utiliser soit les instructions LMD, soit les mutations d'une même transaction, mais pas les deux.

L'exemple Java suivant illustre un comportement potentiellement surprenant. Le code insère deux lignes dans des Albums à l'aide de l'API Mutation. L'extrait appelle ensuite executeUpdate() pour mettre à jour les lignes nouvellement insérées et executeQuery() pour lire les albums mis à jour.

static void updateMarketingBudget(DatabaseClient dbClient) {
  dbClient
      .readWriteTransaction()
      .run(
          new TransactionCallable<Void>() {
            @Override
            public Void run(TransactionContext transaction) throws Exception {
               transaction.buffer(
                    Mutation.newInsertBuilder("Albums")
                        .set("SingerId")
                        .to(1)
                        .set("AlbumId")
                        .to(1)
                        .set("AlbumTitle")
                        .to("Total Junk")
                        .set("MarketingBudget")
                        .to(800)
                        .build());
               transaction.buffer(
                    Mutation.newInsertBuilder("Albums")
                        .set("SingerId")
                        .to(1)
                        .set("AlbumId")
                        .to(2)
                        .set("AlbumTitle")
                        .to("Go Go Go")
                        .set("MarketingBudget")
                        .to(200)
                        .build());

                // This UPDATE will not include the Albums inserted above.
                String sql =
                  "UPDATE Albums SET MarketingBudget = MarketingBudget * 2"
                      + " WHERE SingerId = 1";
                long rowCount = transaction.executeUpdate(Statement.of(sql));
                System.out.printf("%d records updated.\n", rowCount);

                // Read a newly updated record.
                sql =
                  "SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
                      + " WHERE SingerId = 1 AND MarketingBudget < 1000";
                ResultSet resultSet =
                                 transaction.executeQuery(Statement.of(sql));
                while (resultSet.next()) {
                   System.out.printf(
                        "%s %s\n",
                        resultSet.getString("FirstName"),
                        resultSet.getString("LastName"));
                }
                return null;
              }
            });
}

En exécutant ce code, vous verriez 0 enregistrement mis à jour. Pourquoi ? Cela est dû aux modifications apportées à l'aide des Mutations, qui ne sont pas visibles pour les instructions suivantes jusqu'au commit de la transaction. Idéalement, nous aurions dû mettre en mémoire tampon les écritures seulement à la toute fin de la transaction.

Étape suivante