Bonnes pratiques relatives au langage de manipulation de données

Cette page décrit les bonnes pratiques d'utilisation du langage de manipulation de données (LMD) et du LMD partitionné.

Utiliser une clause WHERE pour réduire le nombre de lignes verrouillées

Les instructions LMD sont exécutées dans les transactions de lecture-écriture. Lorsque Spanner lit les données, acquiert des verrous en lecture partagés sur les 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 remplissent 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 le 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, l'élément partagé les verrous peuvent empêcher d'autres transactions de progresser en parallèle.

Pour modifier les données le plus efficacement possible, utilisez une clause WHERE qui active Spanner pour 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 les 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 le LMD suivant mais il oblige Spanner à analyser la table entière et à acquérir des verrous partagés couvrent l'ensemble du tableau. Par conséquent, Spanner doit lire plus de données que nécessaire. 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'ensemble de la table pour trouver les chanteurs cibles. Si vous ne souhaitez pas ajouter pour améliorer l'efficacité de la mise à jour, puis incluez la colonne SingerId dans la clause WHERE.

La colonne SingerId est la seule colonne de clé primaire pour le Singers. Pour le trouver, exécutez SELECT dans un fichier 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;

Évitez d'utiliser des instructions LMD et des mutations dans la même transaction

Spanner met en mémoire tampon les insertions, les mises à jour et les suppressions effectuées à l'aide du LMD côté serveur, et les résultats sont visibles pour les requêtes SQL Instructions LMD dans la même transaction. Ce comportement est différent de L'API Mutation, où Spanner met en mémoire tampon les mutations côté client et les envoie côté serveur 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.

Évitez d'utiliser à la fois des instructions LMD et des mutations dans la même transaction. Si vous utilisent les deux dans une même transaction, vous devez tenir compte de l'ordre dans le code de votre bibliothèque cliente. Si une transaction contient à la fois et des mutations dans une même requête, Spanner exécute Instructions LMD avant les mutations.

Pour les opérations qui ne sont compatibles qu'avec les mutations, vous pouvez combiner des instructions LMD et des mutations dans la même transaction (par exemple, insert_or_update.

Si vous utilisez les deux, le tampon n'écrit qu'à la toute fin de la transaction.

Utiliser la fonction PENDING_COMMIT_TIMESTAMP pour écrire des horodatages de commit

GoogleSQL

Pour écrire l'horodatage de commit dans une instruction LMD, utilisez la fonction PENDING_COMMIT_TIMESTAMP. Spanner sélectionne le code temporel de commit lorsque la transaction des commits.

PostgreSQL

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.

LMD partitionné, et fonctions de date et d'horodatage

Le LMD partitionné utilise une ou plusieurs transactions pouvant être exécutées et enregistrées à des moments différents. Si vous utilisez les fonctions de date ou d'horodatage, les lignes modifiées peuvent contenir des valeurs différentes.

Améliorer la latence avec le LMD par lot

Pour réduire la latence, utilisez le LMD par lot pour envoyer plusieurs instructions LMD vers Spanner au cours d'un seul cycle client-serveur voyage.

Le LMD par lot peut appliquer des optimisations à des groupes d'instructions au sein de un lot pour permettre des mises à jour des données plus rapides et plus efficaces.

  • Exécuter des écritures avec une seule requête

    Spanner optimise automatiquement les groupes contigus d'instructions INSERT similaires, les instructions par lot UPDATE ou DELETE ayant des valeurs de paramètre différentes, s'ils n'enfreignent pas les dépendances des données.

    Prenons l'exemple d'un scénario dans lequel vous souhaitez insérer un grand nombre lignes dans une table appelée Albums. Pour permettre à Spanner d'optimiser nécessitait des instructions INSERT en une seule action efficace côté serveur, commencez par écrire une instruction LMD appropriée qui utilise une requête SQL paramètres:

    INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (@Singer, @Album, @Title);
    

    Envoyez ensuite à Spanner un lot LMD qui appelle cette instruction de façon répétée et contiguë, les répétitions ne diffèrent que dans le que vous liez aux trois paramètres de requête de l'instruction. Spanner optimise ces LMD structurellement identiques en une seule opération côté serveur avant de l'exécuter.

  • Exécuter des écritures en parallèle

    Spanner optimise automatiquement les groupes d'instructions LMD contigus en lançant une exécution en parallèle sans enfreindre les dépendances de données. Cette optimisation permet d'améliorer les performances d'un plus grand nombre de LMD par lot car elles peuvent s'appliquer à différents types d'instruction LMD (INSERT, UPDATE et DELETE) et en LMD avec ou sans paramètre .

    Notre exemple de schéma contient les tables Singers, Albums et Accounts Albums est entrelacé dans Singers et stocke des informations sur les albums de Singers. Le groupe d'instructions contigus suivant écrit de nouvelles lignes dans plusieurs tables et ne contient pas de données complexes les dépendances.

    INSERT INTO Singers (SingerId, Name) VALUES(1, "John Doe");
    INSERT INTO Singers (SingerId, Name) VALUES(2, "Marcel Richards");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10001, "Album 1");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10002, "Album 2");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (2, 10001, "Album 1");
    UPDATE Accounts SET Balance = 100 WHERE AccountId = @AccountId;
    

    Spanner optimise ce groupe d'instructions LMD en exécutant la instructions en parallèle. Les écritures sont appliquées dans l'ordre des instructions dans par lot et conserve la sémantique LMD par lot si une instruction échoue l'exécution.