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 {}, quindi request_items = response["UnprocessedKeys"] è sicuro da indicizzare e il dizionario vuoto falsy è ciò che termina il while. 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", []).
  • ConsistentRead e ProjectionExpression vanno dentro il dizionario della singola tabella, accanto a "Keys", non accanto a RequestItems. 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 ha batch_get_item sul ServiceResource, non su Table. boto3.resource("dynamodb").batch_get_item(...) accetta valori Python nativi; table.batch_get_item non esiste. Quell'asimmetria sorprende chi ci arriva dopo aver usato table.batch_writer(), che è un metodo di Table.
  • Il backoff vale solo per UnprocessedKeys. Una ValidationException è 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 duplicates

Il primo sono 101 chiavi, il secondo è la stessa chiave elencata due volte. Nota cosa non puoi scrivere per intercettarli:

except client.exceptions.ValidationException:  # AttributeError

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

Il 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

Riferimenti

Ultima verifica 2026-07-28 rispetto alla documentazione ufficiale AWS collegata sopra.

Lavora con DynamoDB senza la Console

Un client desktop veloce per DynamoDB che esegue il vero SQL che DynamoDB non può — JOINs, GROUP BY, aggregazioni — con modifica visuale e un agente AI sulle tue chiavi Bedrock.

Prova gratuita di 30 giorni, senza carta di credito — poi il piano Free senza limiti di tempo.