

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Best practice per l’utilizzo di operazioni sui dati in blocco in DynamoDB
<a name="BestPractices_BulkDataOperations"></a>

DynamoDB supporta operazioni batch, ad esempio `BatchWriteItem`, con le quali è possibile eseguire fino a 25 richieste `PutItem` e `DeleteItem` contemporaneamente. Tuttavia, `BatchWriteItem` non supporta le operazioni `UpdateItem`. Per gli aggiornamenti in blocco, la differenza sta nei requisiti e nella natura dell’aggiornamento. È possibile utilizzare altri DynamoDB APIs , ad esempio per batch di dimensioni `TransactWriteItems` fino a 100. Quando sono coinvolti più articoli, puoi utilizzare servizi come AWS Glue Amazon EMR AWS Step Functions o utilizzare script e strumenti personalizzati come DynamoDB-Shell per aggiornamenti di massa.

**Topics**
+ [Aggiornamento batch condizionale](BestPractices_ConditionalBatchUpdate.md)
+ [Operazioni in blocco efficienti](BestPractices_EfficientBulkOperations.md)

# Aggiornamento batch condizionale
<a name="BestPractices_ConditionalBatchUpdate"></a>

DynamoDB supporta operazioni batch, ad esempio `BatchWriteItem`, con le quali è possibile eseguire fino a 25 richieste `PutItem` e `DeleteItem` in un unico batch. Tuttavia, `BatchWriteItem` non supporta le operazioni `UpdateItem` e non supporta le espressioni condizionali. Come soluzione alternativa, puoi utilizzare altri APIs DynamoDB, ad esempio per batch di dimensioni `TransactWriteItems` fino a 100.

Quando sono coinvolti più elementi ed è necessario modificare una parte importante dei dati, è possibile utilizzare servizi come Amazon EMR AWS Step Functions o utilizzare script e strumenti personalizzati come AWS Glue DynamoDB-Shell per aggiornamenti di massa efficienti.

**Quando usare questo modello**
+ DynamoDB-Shell non è un caso d’uso supportato per la produzione.
+ `TransactWriteItems`: fino a 100 aggiornamenti singoli con o senza condizioni, eseguiti come un pacchetto ACID “tutto o niente”. Le chiamate `TransactWriteItems` possono essere fornite anche con un `ClientRequestToken` se l’applicazione richiede idempotenza, il che significa che più chiamate identiche hanno lo stesso effetto di una singola chiamata. In questo modo non si esegue la stessa transazione più volte e si ottiene uno stato dei dati errato.

  Compromesso: viene consumata una velocità di trasmissione aggiuntiva. 2 WCUs per 1 KB di scrittura anziché 1 WGU standard per 1 KB di scrittura.
+ PartiQL`BatchExecuteStatement`: fino a 25 aggiornamenti con o senza condizioni. `BatchExecuteStatement` restituisce sempre una risposta corretta alla richiesta complessiva e restituisce anche un elenco di risposte operative individuali che preserva l’ordine.

  Compromesso: per batch più grandi, è necessaria una logica aggiuntiva lato client per distribuire le richieste in batch da 25. È necessario prendere in considerazione le risposte di errore individuali per determinare la strategia dei nuovi tentativi.

## Esempi di codice
<a name="bp-conditional-code-examples"></a>

Questi esempi di codice utilizzano la libreria boto3, che è l' AWS SDK per Python. Gli esempi presuppongono che boto3 sia installato e configurato con le credenziali AWS appropriate.

Si supponga un database di inventario per un fornitore di elettrodomestici che ha più magazzini in diverse città europee. Poiché è la fine dell’estate, il venditore vorrebbe eliminare i ventilatori da tavolo per fare spazio ad altre scorte. Il venditore desidera offrire uno sconto sul prezzo per tutti i ventilatori da tavolo forniti dai magazzini in Italia, ma solo se hanno una scorta di riserva di 20 unità. La tabella DynamoDB è denominata **inventory**, ha uno schema di chiave di partizione **sku** che è un identificatore univoco per ogni prodotto e una chiave di ordinamento **warehouse** che è un identificatore per un magazzino.

Il seguente codice Python dimostra come eseguire questo aggiornamento batch condizionale utilizzando una chiamata 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’esecuzione produce l’output seguente su dati di esempio:

```
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'}}]
```

Poiché si tratta di un’operazione limitata per un sistema interno, i requisiti di idempotenza non sono stati presi in considerazione. Per rendere gli aggiornamenti più solidi, è possibile inserire guardrail aggiuntivi, come ad esempio l’aggiornamento del prezzo, solo se il prezzo è superiore a 35 e inferiore a 40.

In alternativa, è possibile eseguire la stessa operazione di aggiornamento batch utilizzando `TransactWriteItems` in caso di requisiti di idempotenza e ACID più rigorosi. Tuttavia, è importante ricordare che o tutte le operazioni del pacchetto di transazioni vengono eseguite o l’intero pacchetto genera un errore.

Ipotizziamo un caso in cui si verifichi un’ondata di caldo in Italia e la domanda di ventilatori da tavolo aumenti notevolmente. Il fornitore vuole aumentare di 20 euro il costo dei ventilatori da tavolo in uscita da tutti i magazzini in Italia, ma l’organismo di regolamentazione consente questo aumento solo se il costo attuale è inferiore a 70 euro per l’intero inventario. È essenziale che il prezzo venga aggiornato in tutto l’inventario contemporaneamente e solo una volta e solo se il costo è inferiore a 70 euro in ogni magazzino.

Il seguente codice Python dimostra come eseguire questo aggiornamento batch utilizzando una chiamata 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’esecuzione produce l’output seguente su dati di esempio:

```
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'}}]
```

Esistono diversi approcci per eseguire aggiornamenti batch in DynamoDB. L'approccio adatto dipende da fattori quali i requisiti di and/or idempotenza ACID, il numero di elementi da aggiornare e la familiarità con cui. APIs

# Operazioni in blocco efficienti
<a name="BestPractices_EfficientBulkOperations"></a>

**Quando usare questo modello**

Questi modelli sono utili per eseguire in modo efficiente aggiornamenti in blocco sugli elementi di DynamoDB.
+ DynamoDB-Shell non è un caso d’uso supportato per la produzione.
+ `TransactWriteItems`: fino a 100 aggiornamenti singoli con o senza condizioni, eseguiti come un pacchetto ACID “tutto o niente” 

  Compromesso: viene consumata una velocità effettiva aggiuntiva, 2 per 1 KB di scrittura. WCUs 
+ PartiQL`BatchExecuteStatement`: fino a 25 aggiornamenti con o senza condizioni

  Compromesso: è necessaria una logica aggiuntiva per distribuire le richieste in batch da 25.
+ AWS Step Functions — operazioni di massa a velocità limitata per gli sviluppatori che hanno dimestichezza con. AWS Lambda

  Compromesso: il tempo di esecuzione è inversamente proporzionale al limite di velocità. Limitazione data dal timeout massimo della funzione Lambda. La funzionalità prevede che le modifiche ai dati che si verificano tra la lettura e la scrittura possano essere sovrascritte. Per ulteriori informazioni, consulta [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 e Amazon EMR: operazioni di massa a velocità limitata con parallelismo gestito. Per le applicazioni o gli aggiornamenti non sensibili al fattore temporale, queste opzioni possono essere eseguite in background consumando solo una piccola percentuale del throughput. Entrambi i servizi utilizzano il emr-dynamodb-connector per eseguire operazioni DynamoDB. Questi servizi eseguono una lettura approfondita seguita da una scrittura approfondita degli elementi aggiornati con un’opzione per limitare la velocità.

  Compromesso: il tempo di esecuzione è inversamente proporzionale al limite di velocità. La funzionalità prevede che le modifiche ai dati che si verificano tra la lettura e la scrittura possano essere sovrascritte. Non è possibile leggere da Global Secondary Indexes (). GSIs Consulta [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/).
+ DynamoDB Shell: operazioni in blocco a velocità limitata attraverso query di tipo SQL. Puoi leggere da GSIs per una migliore efficienza.

  Compromesso: il tempo di esecuzione è inversamente proporzionale al limite di velocità. Consulta [Rate limited bulk operations in DynamoDB Shell](https://aws.amazon.com/blogs/database/rate-limited-bulk-operations-in-dynamodb-shell/).

## Utilizzo del modello
<a name="BestPractices_EfficientBulkOperations_UsingThePattern"></a>

Gli aggiornamenti in blocco possono avere implicazioni significative in termini di costi, soprattutto se si utilizza la modalità di throughput on demand. Esiste un compromesso tra velocità e costi se si utilizza la modalità di throughput allocato. L’impostazione molto rigorosa del parametro del limite di velocità può portare a tempi di elaborazione molto lunghi. È possibile determinare approssimativamente la velocità di aggiornamento utilizzando la dimensione media dell’elemento e il limite di velocità.

In alternativa, è possibile determinare la quantità di throughput necessaria per il processo in base alla durata prevista del processo di aggiornamento e alla dimensione media degli elementi. I riferimenti del blog condivisi con ogni modello forniscono dettagli sulla strategia, l’implementazione e i limiti dell’utilizzo del modello. Per ulteriori informazioni, consulta [Cost-effective bulk processing with Amazon DynamoDB](https://aws.amazon.com/blogs/database/cost-effective-bulk-processing-with-amazon-dynamodb/).

Esistono diversi approcci per eseguire aggiornamenti in blocco su una tabella DynamoDB attiva. L'approccio adatto dipende da fattori quali i requisiti di and/or idempotenza ACID, il numero di elementi da aggiornare e la familiarità con cui si è in possesso. APIs È importante considerare il rapporto tra costi e tempi: la maggior parte degli approcci sopra descritti prevede un’opzione per limitare il throughput utilizzato dal processo di aggiornamento in blocco.