

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Bonnes pratiques liées à l’utilisation d’opérations de données groupées dans DynamoDB
<a name="BestPractices_BulkDataOperations"></a>

DynamoDB prend en charge les opérations groupées, par exemple `BatchWriteItem`, grâce auxquelles vous pouvez effectuer jusqu’à 25 demandes `PutItem` et `DeleteItem` ensemble. Cependant, `BatchWriteItem` ne prend pas en charge les opérations `UpdateItem`. Lorsqu’il s’agit de mises à jour groupées, la distinction réside dans les exigences et la nature de la mise à jour. Vous pouvez utiliser d'autres DynamoDB APIs , par exemple pour une taille de lot `TransactWriteItems` allant jusqu'à 100. Lorsque d'autres éléments sont concernés, vous pouvez utiliser des services tels qu'Amazon EMR AWS Glue, AWS Step Functions ou utiliser des scripts et des outils personnalisés tels que DynamoDB-Shell pour les mises à jour groupées.

**Topics**
+ [Mise à jour de lot conditionnelle](BestPractices_ConditionalBatchUpdate.md)
+ [Opérations groupées efficaces](BestPractices_EfficientBulkOperations.md)

# Mise à jour de lot conditionnelle
<a name="BestPractices_ConditionalBatchUpdate"></a>

DynamoDB prend en charge les opérations groupées, par exemple `BatchWriteItem`, grâce auxquelles vous pouvez effectuer jusqu’à 25 demandes `PutItem` et `DeleteItem` en un seul lot. Cependant, `BatchWriteItem` ne prend pas en charge les opérations `UpdateItem` ni les expressions de condition. Pour contourner le problème, vous pouvez utiliser d'autres APIs DynamoDB, par exemple pour une taille de lot allant `TransactWriteItems` jusqu'à 100.

Lorsque d'autres éléments sont concernés et qu'une grande partie des données doit être modifiée, vous pouvez utiliser des services tels qu'Amazon EMR AWS Glue AWS Step Functions , ou utiliser des scripts et des outils personnalisés tels que DynamoDB-Shell pour des mises à jour groupées efficaces.

**Quand utiliser ce modèle**
+ DynamoDB-Shell n’est pas un cas d’utilisation pris en charge pour la production.
+ `TransactWriteItems` : jusqu’à 100 mises à jour individuelles avec ou sans conditions, exécutées sous la forme d’un bundle ACID « tout ou rien ». Les appels `TransactWriteItems` peuvent également être fournis avec un `ClientRequestToken` si votre application nécessite une idempotence, ce qui signifie que plusieurs appels identiques ont le même effet qu’un seul appel. Cela garantit que vous n’exécuterez pas la même transaction plusieurs fois et que vous n’obtiendrez pas un état de données incorrect.

  Compromis — Un débit supplémentaire est consommé. 2 WCUs par 1 Ko d'écriture au lieu de 1 WGU standard par 1 Ko d'écriture.
+ PartiQL `BatchExecuteStatement` : jusqu’à 25 mises à jour avec ou sans conditions. `BatchExecuteStatement` renvoie toujours une réponse positive à la demande globale et renvoie également une liste de réponses aux opérations individuelles qui préserve l’ordre.

  Compromis : pour les lots plus importants, une logique supplémentaire côté client est requise pour distribuer les demandes par lots de 25. Les réponses d’erreur individuelles doivent être prises en compte pour déterminer la stratégie de nouvelle tentative.

## Exemples de code
<a name="bp-conditional-code-examples"></a>

Ces exemples de code utilisent la bibliothèque boto3, qui est le AWS SDK pour Python. Cet exemple suppose que boto3 est installé et configuré avec les informations d’identification AWS appropriées.

Supposons une base de données d’inventaire pour un fournisseur d’appareils électriques qui possède plusieurs entrepôts dans des villes européennes. À l’approche de la fin de l’été, le vendeur aimerait se débarrasser des ventilateurs de bureau pour faire de la place pour d’autres stocks. Le vendeur souhaite offrir une réduction sur tous les ventilateurs de bureau fournis par des entrepôts en Italie, mais uniquement s’il dispose d’un stock de réserve de 20 ventilateurs de bureau. La table DynamoDB est appelée **inventaire**. Elle possède un schéma clé de partition **sku**, qui est un identifiant unique pour chaque produit, et un **entrepôt** de clé de tri, qui est un identifiant d’entrepôt.

Le code Python suivant montre comment effectuer cette mise à jour conditionnelle par lots à l’aide d’un appel d’API `BatchExecuteStatement`.

```
import boto3

client=boto3.client("dynamodb")

before_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("Before update: ", before_image['Items'])

response=client.batch_execute_statement(
        Statements=[
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITTUR1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM2'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM5'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN2'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN3'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
        ],
        ReturnConsumedCapacity='TOTAL'
    )

after_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("After update: ", after_image['Items'])
```

L’exécution produit le résultat ci-dessous sur des exemples de données :

```
Before update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}]
After update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '33'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '30'}, 'sku': {'S': 'F123'}}]
```

Comme il s’agit d’une opération limitée pour un système interne, les exigences d’idempotence n’ont pas été prises en compte. Il est possible de placer des barrières de protection supplémentaires, comme la mise à jour des prix uniquement si le prix est supérieur à 35 et inférieur à 40 pour rendre les mises à jour plus robustes.

Nous pouvons également effectuer la même opération de mise à jour groupée en utilisant `TransactWriteItems` en cas d’idempotence et d’exigences ACID plus strictes. Cependant, il est important de se rappeler que soit toutes les opérations du lot de transactions sont effectuées, soit l’ensemble du lot échoue.

Supposons qu’il y ait une vague de chaleur en Italie et que la demande de ventilateurs de bureau ait fortement augmenté. Le fournisseur souhaite augmenter de 20 euros le coût de ses ventilateurs de bureau sortant de tous ses entrepôts en Italie, mais l’organisme de réglementation n’autorise cette augmentation des coûts que si le coût actuel est inférieur à 70 euros pour l’ensemble de son inventaire. Il est essentiel que le prix soit mis à jour dans l’ensemble de l’inventaire en une seule fois et uniquement si le coût est inférieur à 70 euros dans chacun de ses entrepôts.

Le code Python suivant montre comment effectuer cette mise à jour groupée à l’aide d’un appel d’API `TransactWriteItems`.

```
import boto3

client=boto3.client("dynamodb")

before_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("Before update: ", before_image['Items'])

response=client.transact_write_items(
        ClientRequestToken='UUIDAWS124',
        TransactItems=[
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITTUR1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM2'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM5'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN2'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN3'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
        ],
        ReturnConsumedCapacity='TOTAL'
    )

after_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("After update: ", after_image['Items'])
```

L’exécution produit le résultat ci-dessous sur des exemples de données :

```
Before update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '60'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '55'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '53'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '55'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '58'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '58'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '50'}, 'sku': {'S': 'F123'}}]
After update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '80'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '75'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '73'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '75'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '78'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '78'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '70'}, 'sku': {'S': 'F123'}}]
```

Plusieurs approches permettent d’effectuer des mises à jour groupées dans DynamoDB. L'approche appropriée dépend de facteurs tels que les exigences d' and/or idempuissance de l'ACID, le nombre d'éléments à mettre à jour et la familiarité avec ceux-ci. APIs

# Opérations groupées efficaces
<a name="BestPractices_EfficientBulkOperations"></a>

**Quand utiliser ce modèle**

Ces modèles sont utiles pour effectuer efficacement des mises à jour groupées sur des éléments DynamoDB.
+ DynamoDB-Shell n’est pas un cas d’utilisation pris en charge pour la production.
+ `TransactWriteItems` : jusqu’à 100 mises à jour individuelles avec ou sans conditions, exécutées sous la forme d’un lot ACID « tout ou rien » 

  Compromis — Un débit supplémentaire est consommé, 2 WCUs par 1 Ko d'écriture.
+ PartiQL `BatchExecuteStatement` : jusqu’à 25 mises à jour avec ou sans conditions

  Compromis : une logique supplémentaire est requise pour distribuer les demandes par lots de 25.
+ AWS Step Functions — des opérations groupées à débit limité pour les développeurs qui les connaissent bien. AWS Lambda

  Compromis : le temps d’exécution est inversement proportionnel à la limite de débit. Limité par le délai d’expiration maximal de la fonction Lambda. Cette fonctionnalité implique que les modifications de données qui se produisent entre la lecture et l’écriture peuvent être remplacées. Pour plus d’informations, consultez [Backfilling an Amazon DynamoDB Time to Live attribute using Amazon EMR: Part 2](https://aws.amazon.com/blogs/database/part-2-backfilling-an-amazon-dynamodb-time-to-live-attribute-using-amazon-emr/).
+ AWS Glue et Amazon EMR : opération en masse à débit limité avec parallélisme géré. Pour les applications ou les mises à jour qui ne sont pas urgentes, ces options ne peuvent s’exécuter en arrière-plan qu’en consommant un faible pourcentage du débit. Les deux services utilisent le emr-dynamodb-connector pour effectuer des opérations DynamoDB. Ces services effectuent une lecture importante suivie d’une écriture importante d’éléments mis à jour avec une option de limitation de débit.

  Compromis : le temps d’exécution est inversement proportionnel à la limite de débit. Avec cette fonctionnalité, les modifications de données qui se produisent entre la lecture et l’écriture peuvent être remplacées. Vous ne pouvez pas lire à partir des index secondaires globaux (GSIs). Consultez [Remplissage d’un attribut de temps de vie Amazon DynamoDB à l’aide d’Amazon EMR : partie 2](https://aws.amazon.com/blogs/database/part-2-backfilling-an-amazon-dynamodb-time-to-live-attribute-using-amazon-emr/).
+ DynamoDB Shell : opérations groupées à débit limité utilisant des requêtes de type SQL. Vous pouvez lire ce qui suit GSIs pour une meilleure efficacité.

  Compromis : le temps d’exécution est inversement proportionnel à la limite de débit. Consultez [Opérations groupées limitées en débit dans DynamoDB Shell](https://aws.amazon.com/blogs/database/rate-limited-bulk-operations-in-dynamodb-shell/).

## Utilisation du motif
<a name="BestPractices_EfficientBulkOperations_UsingThePattern"></a>

Les mises à jour groupées peuvent avoir des implications financières importantes, en particulier si vous utilisez le mode débit à la demande. Il existe un compromis entre vitesse et coût si vous utilisez le mode de débit provisionné. Un réglage très strict du paramètre de limite de débit peut entraîner un temps de traitement très long. Vous pouvez déterminer approximativement la vitesse de mise à jour à l’aide de la taille moyenne des articles et de la limite de débit.

Vous pouvez également déterminer le débit nécessaire pour le processus en fonction de la durée prévue du processus de mise à jour et de la taille moyenne des éléments. Les références de blog partagées avec chaque modèle fournissent des détails sur la stratégie, la mise en œuvre et les limites de l’utilisation du modèle. Pour plus d’informations, consultez [Cost-effective bulk processing with Amazon DynamoDB](https://aws.amazon.com/blogs/database/cost-effective-bulk-processing-with-amazon-dynamodb/).

Il existe plusieurs approches pour effectuer des mises à jour groupées sur une table DynamoDB active. L'approche appropriée dépend de facteurs tels que les exigences en matière d' and/or idempuissance de l'ACID, le nombre d'éléments à mettre à jour et le niveau de familiarité avec celui-ci. APIs Il est important de prendre en compte le compromis entre le coût et le temps. La plupart des approches décrites ci-dessus offrent une option permettant de limiter le débit utilisé par la tâche de mise à jour groupée.