DynamoDB BatchGetItem in Python (boto3)
batch_get_item holt bis zu 100 Items per Primary Key in einer Anfrage. Das while request_items: im Block unten ist das ganze boto3-Idiom: DynamoDB gibt die Reste in einer erfolgreichen Antwort zurück, und ein leeres Dict ist falsy — die Schleife beendet sich also selbst. Die Limits und die Regeln für Teilergebnisse stehen in Batch-Operationen in DynamoDB; auf dieser Seite geht es um den boto3-Aufruf und die Fehler, die er auslöst.
Code
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")Erklärung
response["UnprocessedKeys"]ist immer vorhanden. Bei einem vollständig bedienten Batch existiert der Key und enthält{}—request_items = response["UnprocessedKeys"]ist also sicher zu indizieren, und das falsy leere Dict beendet daswhile. Vorsicht ist beiResponsesgeboten: Eine Tabelle, deren Keys alle ins Leere liefen, fehlt dort ganz, weshalb der Block.get("Music", [])verwendet.ConsistentReadundProjectionExpressiongehören in das Dict der jeweiligen Tabelle, neben"Keys", nicht nebenRequestItems. boto3 schickt einen falsch platzierten Key bereitwillig los und lässt den Dienst ihn ablehnen.- Das ist der Low-Level-Client, die Werte sind also DynamoDB-JSON (
{"S": ...},{"N": ...}). Die Resource-API hatbatch_get_itemauf der ServiceResource, nicht aufTable.boto3.resource("dynamodb").batch_get_item(...)nimmt native Python-Werte entgegen;table.batch_get_itemexistiert nicht. Diese Asymmetrie überrascht alle, die nachtable.batch_writer()danach greifen — denn das ist eineTable-Methode. - Backoff gilt nur für
UnprocessedKeys. EineValidationExceptionist ein Fehler in der Anfrage, und sie zu wiederholen verbrennt nur Laufzeit.
Die zwei Fehler, die dieser Aufruf auslöst, wortgetreu
Beide sind clientseitige Fehler, die kein Retry behebt, und beide erscheinen als schlichter botocore.exceptions.ClientError. Gegen DynamoDB Local 3.3.0 liefert 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 duplicatesDer erste sind 101 Keys, der zweite derselbe Key zweimal gelistet. Beachte, was du nicht schreiben kannst, um sie zu fangen:
except client.exceptions.ValidationException: # AttributeErrorbotocore modelliert 34 benannte Exception-Klassen auf dem DynamoDB-Client, und ValidationException ist keine davon. ConditionalCheckFailedException und ProvisionedThroughputExceededException schon — deshalb kann die Seite zum bedingten Schreiben nach Klasse fangen und diese hier nicht. Es gibt sogar eine modellierte DuplicateItemException, und sie ist nicht das, was ein doppelter Key in einem Batch liefert. Ein Batch-Read muss also über den Code verzweigen:
except ClientError as e:
if e.response["Error"]["Code"] == "ValidationException":
raise # a bug in the request; retrying will not helpDer Fall mit dem doppelten Key ist der, der in echtem Code beißt, denn eine aus einem Query-Ergebnis oder einer Join-Tabelle zusammengestellte Key-Liste enthält ganz natürlich Wiederholungen. Dedupliziere vor dem Senden und denk daran, dass zwei Dicts nur dann gleich sind, wenn jedes Key-Attribut übereinstimmt.
Die Größe ist der andere Grund, warum ein Batch von 100 kein Batch von 100 bleibt: Jedes Item wird für die Abrechnung auf 4 KB aufgerundet und gegen 16 MB Antwortgröße gezählt — 100 Items zu je 300 KB kommen also als rund 52 zurück, der Rest steht in UnprocessedKeys. Der Item-Size-Rechner liefert dir die Zahl pro Item zum Multiplizieren.
Um eine Menge Keys zurückzuholen und vor dem Schreiben der Schleife zu prüfen, was zurückkam, lade DynoTable herunter.
Verwandte Beispiele
- DynamoDB BatchGetItem in Node.js — derselbe Batch-Read mit AWS SDK v3.
- DynamoDB BatchGetItem mit der AWS CLI — derselbe Batch-Read aus der Shell.
- DynamoDB GetItem in Python — der Einzel-Item-Read, den dieser Aufruf bündelt.
- Batch-Operationen in DynamoDB — Limits, Teilfehler und wann sich Batching lohnt.
- "Too many items requested for the BatchGetItem call" — mehr als 100 Keys in einer Anfrage.
- "Provided list of item keys contains duplicates" — derselbe Key zweimal in einem Batch.
Referenzen
- BatchGetItem — Amazon DynamoDB API Reference
- DynamoDB.Client.batch_get_item — Boto3 documentation
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
Zuletzt verifiziert am 2026-07-28 gegen die oben verlinkte offizielle AWS-Dokumentation.