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à.
DynamoDB supporta operazioni in batch, ad BatchWriteItem
esempio utilizzando le quali è possibile eseguire fino a PutItem
25 richieste in un DeleteItem
unico batch. Tuttavia, BatchWriteItem
non supporta UpdateItem
le operazioni 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.TransactWriteItems
le chiamate possono essere fornite anche con aClientRequestToken
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à effettiva 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
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 appropriate. AWS
Supponiamo 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 scrivania 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 ventilatori da tavolo. La tabella DynamoDB si chiama inventory, ha uno schema chiave di Partition key sku che è un identificatore univoco per ogni prodotto e un warehouse Sort key 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ù robusti, è possibile inserire barriere aggiuntive, come ad esempio Price Update, solo se il prezzo è superiore a 35 e inferiore a 40.
In alternativa, possiamo eseguire la stessa operazione di aggiornamento in 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 fallisce.
Ipotizziamo un caso in cui si verifichi un'ondata di caldo in Italia e la domanda di ventilatori da tavolo sia aumentata notevolmente. Il fornitore vuole aumentare di 20 euro il costo dei ventilatori da tavolo che escono da ogni magazzino 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 in batch utilizzando TransactWriteItems
una chiamata API.
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 in batch in DynamoDB. L'approccio adatto dipende da fattori quali i requisiti ACID e/o di idempotenza, il numero di elementi da aggiornare e la familiarità con cui. APIs