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 das while. Vorsicht ist bei Responses geboten: Eine Tabelle, deren Keys alle ins Leere liefen, fehlt dort ganz, weshalb der Block .get("Music", []) verwendet.
  • ConsistentRead und ProjectionExpression gehören in das Dict der jeweiligen Tabelle, neben "Keys", nicht neben RequestItems. 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 hat batch_get_item auf der ServiceResource, nicht auf Table. boto3.resource("dynamodb").batch_get_item(...) nimmt native Python-Werte entgegen; table.batch_get_item existiert nicht. Diese Asymmetrie überrascht alle, die nach table.batch_writer() danach greifen — denn das ist eine Table-Methode.
  • Backoff gilt nur für UnprocessedKeys. Eine ValidationException ist 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 duplicates

Der erste sind 101 Keys, der zweite derselbe Key zweimal gelistet. Beachte, was du nicht schreiben kannst, um sie zu fangen:

except client.exceptions.ValidationException:  # AttributeError

botocore 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 help

Der 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

Referenzen

Zuletzt verifiziert am 2026-07-28 gegen die oben verlinkte offizielle AWS-Dokumentation.

Mit DynamoDB ohne die Console arbeiten

Ein schneller DynamoDB-Desktop-Client, der das echte SQL ausführt, das DynamoDB nicht kann — JOINs, GROUP BY, Aggregationen — mit visueller Bearbeitung und einem KI-Agenten auf deinen eigenen Bedrock-Schlüsseln.

30 Tage kostenlos testen, keine Kreditkarte — danach der Kostenlos-Tarif ohne Zeitlimit.