DynamoDB BatchGetItem in Python (boto3)
batch_get_item recupera fino a 100 Item per chiave primaria in una sola richiesta. Il while request_items: nel blocco qui sotto è tutto l'idioma boto3: DynamoDB restituisce i resti in una risposta andata a buon fine, e un dizionario vuoto è falsy, quindi il loop si chiude da solo. I limiti e le regole sui risultati parziali stanno in operazioni batch in DynamoDB; questa pagina parla della chiamata boto3 e degli errori che solleva.
Codice
import time
import boto3
client = boto3.client("dynamodb")
request_items = {
"Music": {
"Keys": [
{"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
{"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "A Mis Abuelos"}},
{"Artist": {"S": "Ella Fitzgerald"}, "SongTitle": {"S": "Misty"}},
]
}
}
items = []
attempt = 0
while request_items:
response = client.batch_get_item(RequestItems=request_items)
items.extend(response["Responses"].get("Music", []))
# A partial result is NOT an error: throttling, a >16 MB response, or an
# internal failure returns the leftovers in UnprocessedKeys. Retry them
# with exponential backoff.
request_items = response["UnprocessedKeys"]
if request_items:
attempt += 1
time.sleep(min(0.1 * 2**attempt, 5))
print(f"Fetched {len(items)} items")Spiegazione
response["UnprocessedKeys"]c'è sempre. Su un batch servito per intero la chiave esiste e contiene{}, quindirequest_items = response["UnprocessedKeys"]è sicuro da indicizzare e il dizionario vuoto falsy è ciò che termina ilwhile.Responsesè quello con cui stare attenti: una tabella le cui chiavi non hanno trovato nulla è assente da lì, ed è il motivo per cui il blocco usa.get("Music", []).ConsistentReadeProjectionExpressionvanno dentro il dizionario della singola tabella, accanto a"Keys", non accanto aRequestItems. boto3 invierà senza obiezioni una chiave fuori posto e lascerà che sia il servizio a rifiutarla.- Questo è il client di basso livello, quindi i valori sono JSON DynamoDB (
{"S": ...},{"N": ...}). L'API resource habatch_get_itemsul ServiceResource, non suTable.boto3.resource("dynamodb").batch_get_item(...)accetta valori Python nativi;table.batch_get_itemnon esiste. Quell'asimmetria sorprende chi ci arriva dopo aver usatotable.batch_writer(), che è un metodo diTable. - Il backoff vale solo per
UnprocessedKeys. UnaValidationExceptionè un bug nella richiesta, e riprovarla brucia solo tempo.
I due errori che questa chiamata solleva, alla lettera
Entrambi sono errori lato client che nessun retry risolve, ed entrambi emergono come un semplice botocore.exceptions.ClientError. Su DynamoDB Local 3.3.0, str(e):
An error occurred (ValidationException) when calling the BatchGetItem operation: Too many items requested for the BatchGetItem call
An error occurred (ValidationException) when calling the BatchGetItem operation: Provided list of item keys contains duplicatesIl primo sono 101 chiavi, il secondo è la stessa chiave elencata due volte. Nota cosa non puoi scrivere per intercettarli:
except client.exceptions.ValidationException: # AttributeErrorbotocore modella 34 classi di eccezione con nome sul client DynamoDB, e ValidationException non è tra queste. ConditionalCheckFailedException e ProvisionedThroughputExceededException lo sono, ed è il motivo per cui la pagina sulla scrittura condizionale può intercettare per classe e questa no. Esiste perfino una DuplicateItemException modellata, e non è quello che ti dà una chiave duplicata in un batch. Quindi una lettura batch deve ramificare sul codice:
except ClientError as e:
if e.response["Error"]["Code"] == "ValidationException":
raise # a bug in the request; retrying will not helpIl caso della chiave duplicata è quello che morde nel codice reale, perché una lista di chiavi assemblata dal risultato di una Query o da una tabella di join si ripete naturalmente. Deduplica prima di inviare, ricordando che due dizionari sono uguali solo se combaciano tutti gli attributi di chiave.
La dimensione è l'altro motivo per cui un batch di 100 non resta un batch di 100: ogni Item viene arrotondato a 4 KB per la fatturazione e conteggiato sui 16 MB della risposta, quindi 100 Item da 300 KB tornano indietro all'incirca in 52, con il resto in UnprocessedKeys. Il calcolatore delle dimensioni degli Item ti dà la cifra per Item da moltiplicare.
Per rileggere un insieme di chiavi e ispezionare cosa è tornato prima di scrivere il loop, scarica DynoTable.
Esempi correlati
- DynamoDB BatchGetItem in Node.js — la stessa lettura batch con AWS SDK v3.
- DynamoDB BatchGetItem con la AWS CLI — la stessa lettura batch dalla shell.
- DynamoDB GetItem in Python — la lettura del singolo Item che questa raggruppa.
- Operazioni batch in DynamoDB — limiti, fallimento parziale e quando il batching conviene.
- "Too many items requested for the BatchGetItem call" — più di 100 chiavi in una sola richiesta.
- "Provided list of item keys contains duplicates" — la stessa chiave due volte in un batch.
Riferimenti
- BatchGetItem — Amazon DynamoDB API Reference
- DynamoDB.Client.batch_get_item — Boto3 documentation
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
Ultima verifica 2026-07-28 rispetto alla documentazione ufficiale AWS collegata sopra.