Intermédiaire8 min de lecture

Opérations par lots DynamoDB

Quand tu dois lire ou écrire beaucoup d'éléments d'un coup, déclencher un GetItem ou un PutItem par élément signifie un aller-retour réseau par élément — lent et bavard. Les API par lots de DynamoDB regroupent de nombreuses opérations d'éléments en une seule requête : BatchGetItem pour les lectures, BatchWriteItem pour les écritures.

C'est un gain de débit et de latence, pas une garantie de cohérence — et cette distinction est là où les gens se brûlent. Un lot n'est pas une transaction.

Qu'est-ce que les opérations par lots DynamoDB ?

Les opérations par lots DynamoDB regroupent de nombreuses lectures ou écritures d'éléments en une seule requête : BatchGetItem récupère jusqu'à 100 éléments, BatchWriteItem insère ou supprime jusqu'à 25, chacune plafonnée à 16 Mo. Elles économisent des allers-retours, pas de la capacité. Point crucial : un lot n'est pas une transaction — les éléments réussissent ou échouent indépendamment, sans rollback.

  • BatchGetItem — récupère jusqu'à 100 éléments (ou 16 Mo) sur une ou plusieurs tables en un appel.
  • BatchWriteItem — jusqu'à 25 opérations put/delete (ou 16 Mo) en un appel. Pas de mise à jour — puts et deletes uniquement.
  • Pas atomique. Des éléments individuels peuvent réussir pendant que d'autres échouent. Il n'y a pas de rollback.
  • L'échec partiel est normal. Les éléments throttlés reviennent dans UnprocessedItems / UnprocessedKeys — tu dois les réessayer toi-même, avec backoff.
  • Même coût de capacité que les appels individuels — le regroupement économise des allers-retours, pas des unités de capacité.

Le problème : beaucoup d'éléments, un aller-retour

Disons que tu exploites un support desk. Un tableau de bord doit charger 50 tickets par ID pour afficher une file ; un job nocturne archive 1 000 tickets résolus. Faire ça un élément à la fois représente 50 (ou 1 000) allers-retours séquentiels — la latence s'empile et le job traîne.

Le regroupement condense ça en une poignée d'appels. La lecture de 50 tickets devient un seul BatchGetItem ; le job d'archivage devient un flux d'appels BatchWriteItem de 25 suppressions chacun. Bien moins d'allers-retours, la même quantité de données déplacée.

Comment fonctionnent les API par lots

BatchGetItem prend un ensemble de clés primaires (sur une ou plusieurs tables) et renvoie les éléments correspondants. Tu peux demander des lectures fortement cohérentes par table. Tout ce qu'il n'a pas pu lire — généralement parce que la requête a effleuré une limite de débit — revient dans UnprocessedKeys plutôt que de faire échouer tout l'appel.

BatchWriteItem prend une liste d'opérations PutRequest / DeleteRequest. Note ce qui manque : il n'y a pas de mise à jour. Une écriture par lot remplace soit un élément entier (put) soit le supprime (delete) — pour modifier des attributs spécifiques, tu as toujours besoin d'UpdateItem. Les éléments qu'il n'a pas pu écrire reviennent dans UnprocessedItems.

réussithrottléréessai avec backoffBatchWriteItem : 25 puts/deletesTraitement par itemÉcritUnprocessedItems

Le modèle mental clé : un lot est un paquet d'opérations indépendantes, chacune réussissant ou échouant pour son propre compte — pas une unité tout-ou-rien.

Les lots ne sont pas des transactions

C'est le piège. Si le lot de ton job d'archivage atteint une limite de débit à mi-chemin, certains tickets sont supprimés et d'autres non — et DynamoDB n'annule pas ceux qui sont passés. Il n'y a pas de rollback, pas d'isolation, pas de « les 25 ou aucun ».

Si tu as besoin de sémantique tout-ou-rien — « déplacer le ticket vers archivé et décrémenter le compteur de tickets ouverts, ou ne rien faire » — c'est TransactWriteItems, pas un lot. Les transactions coûtent plus cher (chaque opération est facturée double) et plafonnent à 100 éléments, mais elles te donnent l'atomicité que les lots ne délivrent délibérément pas.

Gérer les éléments non traités

Un appelant de lot correct vérifie toujours l'ensemble non traité et le réessaie. DynamoDB renvoie UnprocessedItems/UnprocessedKeys chaque fois que la requête dans son ensemble a été acceptée mais que certains éléments n'ont pas pu être servis — typiquement du throttling transitoire.

Resoumets uniquement les éléments non traités, avec backoff exponentiel et jitter. Traiter un lot comme du « lance et oublie » abandonne silencieusement des écritures — le genre de bug qui refait surface des mois plus tard sous forme de données manquantes.

Écritures par lots dans DynoTable

Estime d'abord ce que coûtera un job en masse avec le calculateur de tarifs DynamoDB — un lot consomme la même capacité que les écritures individuelles qu'il regroupe, juste en moins de requêtes.

Dans DynoTable, tu prépares tes modifications localement et les passes en revue avant de les valider — les changements en masse sur de nombreuses lignes partent en requêtes groupées plutôt qu'en un appel API chacun. Les suppressions en masse partent en écritures par lots, avec le réessai des éléments non traités géré pour toi.

Revue des modifications préparées avant de les valider en lot dans DynoTable.
Revue des modifications préparées avant de les valider en lot dans DynoTable.

Pièges + étapes suivantes

  • Réessaie toujours UnprocessedItems/UnprocessedKeys avec backoff — ils sont attendus, pas exceptionnels.
  • Pas de rollback en cas d'échec partiel. Besoin d'atomicité ? Utilise les transactions.
  • Pas de mise à jour dans une écriture par lotBatchWriteItem est put/delete uniquement ; recours à UpdateItem pour modifier des attributs.
  • Attention aux plafonds par appel — 25 écritures / 100 lectures / 16 Mo. Les dépasser fait échouer tout l'appel avec une ValidationException (trop d'éléments dans BatchGetItem, dans BatchWriteItem). Pagine pour les jobs plus gros ; voir pagination.

Envie de lancer des lectures et écritures en masse sans scripter la boucle de réessai ? Télécharge DynoTable et édite tes tables directement.

Math des allers-retours

Les appels GetItem en série paient la latence à chaque saut. BatchGetItem regroupe jusqu'à 100 clés ou 16 Mo par requête — selon la limite atteinte en premier.

MotifClésAllers-retours approx. @ 50 clésNotes
GetItem en série5050Code le plus simple ; pire latence de queue
Un BatchGetItem501Même total RCU que 50 Gets
Deux lots1202Le second lot porte 20 clés

Le coût de capacité ne change pas — le regroupement économise le temps horloge et le CPU client, pas les RCU. Pour les écritures, 1 000 suppressions à 25 par lot font 40 appels BatchWriteItem au lieu de 1 000 deletes individuels.

Lectures par lots fortement cohérentes

BatchGetItem accepte ConsistentRead: true par table dans la map de requête. Les lectures fortes coûtent toujours 2× les RCU des lectures à cohérence à terme pour les mêmes items. Mélanger tables cohérentes et à terme dans un même appel de lot est possible — chaque entrée de table porte son propre drapeau.

Découper les gros jobs

Quand tu archives 1 000 items d'environ 3 Ko chacun, une seule lecture par lot reste sous le plafond de 100 items mais peut dépasser 16 Mo (100 × 3 Ko = 300 Ko — sûr). Archive des items de 50 Ko et tu touches le plafond mégaoctets vers 320 items par appel alors que la limite de nombre est 100.

Pagine les écritures avec des boucles explicites :

for each chunk of 25 keys:
  BatchWriteItem
  retry UnprocessedItems with backoff until empty

Le commit préparé de DynoTable regroupe les écritures éligibles et réessaie les items non traités automatiquement — le motif que tu scripterais sinon avec un sleep jitteré.

Décision lot vs transaction

BesoinAPIMax itemsEn cas d'échec partiel
Charge en masse best-effortBatchWriteItem25 opsRéessayer les non traités
Mouvement de ledger tout-ou-rienTransactWriteItems100 opsToute la txn rollback
Lire beaucoup de clés connuesBatchGetItem100 clésRéessayer les clés non traitées
Lire + écrire atomiquementTransactWriteItems25 ops transaction (limites documentées)Tout ou rien

Génère des payloads put/delete depuis du JSON ordinaire avec le convertisseur DynamoDB JSON quand tu seeds des charges par lots depuis des fixtures.

Inspecter la capacité consommée

Les réponses de lot peuvent inclure ConsumedCapacity par table quand tu le demandes. Journalise-la pendant les backfills — un taux de throttle qui monte apparaît comme des ensembles non traités qui grossissent avant que les jobs ne calent complètement. Recoupe les WCU soutenues avec le calculateur de tarifs si les lots tournent selon un planning.

Mis à jour