DynamoDB Scan in Python (boto3)

Ein scan in boto3 sind zwei Entscheidungen: der Request und wie du ihn blätterst. Das Snippet unten nutzt den eingebauten Paginator, der kein Wrapper ist, den jemand um deine Schleife geschrieben hat. Es sind fünf Zeilen botocore-Konfiguration, und diese fünf Zeilen entscheiden, ob dein Scan korrekt ist und was er kostet. (Ob du überhaupt scannen solltest, ist eine andere Frage.)

Code

import boto3

client = boto3.client("dynamodb")

paginator = client.get_paginator("scan")

items = []
for page in paginator.paginate(
    TableName="Music",
    FilterExpression="#filter0 >= :filterValue0",
    ExpressionAttributeNames={"#filter0": "Year"},
    ExpressionAttributeValues={":filterValue0": {"N": "2010"}},
):
    items.extend(page["Items"])

print(f"Matched {len(items)} items")

Erklärung

  • Der Paginator ist Daten, kein Code. botocore liefert einen Eintrag pro Operation in paginators-1.json; der von Scan liest {"input_token": "ExclusiveStartKey", "output_token": "LastEvaluatedKey", "limit_key": "Limit", "result_key": ["Items", "Count", "ScannedCount"], "non_aggregate_keys": ["ConsumedCapacity"]}. Alles Weitere folgt aus diesen Keys.
  • PaginationConfig={"PageSize": n} setzt Limit, weil Limit der limit_key ist. Limit begrenzt gelesene Items, nie zurückgegebene — mit einer FilterExpression kann eine Seite also leer sein und trotzdem kosten.
  • MaxItems zählt result_key-Items und gibt dir ein NextToken zurück, das du in einem späteren Prozess als StartingToken übergeben kannst. Es hindert den Request nicht daran, über deine Grenze hinaus zu lesen.
  • build_full_result() aggregiert nur die result_key-Felder. Items, Count und ScannedCount werden summiert; ConsumedCapacity ist ein non_aggregate_key, das zusammengeführte Ergebnis meldet also die Kapazität einer Seite, als wäre sie die des ganzen Scans. Summiere sie selbst, pro Seite, sonst untertreibst du um den Faktor der Seitenanzahl.
  • FilterExpression läuft serverseitig nach dem Lesen, du wirst also auf ScannedCount abgerechnet, nicht auf Count. #filter0 aliasiert Year, weil es ein reserviertes Wort ist; ohne den Alias scheitert der Request, bevor er irgendetwas liest.
  • Fehler kommen alle als botocore.exceptions.ClientError an. Verzweige über e.response["Error"]["Code"]; die Klassen pro Fehler existieren nur als Attribute, die auf dem Client generiert werden (client.exceptions.ProvisionedThroughputExceededException), nie als importierbare Symbole.
  • Die Resource-API ist die andere Ergonomie. Table.scan nimmt native Python-Typen, gibt Zahlen als decimal.Decimal zurück und baut Filter mit Attr("Year").gte(2010) statt Platzhalter-Maps.

Was eine gefilterte Seite tatsächlich kostet

60 Items von jeweils rund 2 KB, Year = 2024 trifft auf zwei davon zu, PageSize=10, ausgeführt gegen DynamoDB Local:

page 1: Count=0 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 2: Count=1 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 3: Count=0 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 4: Count=1 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 5: Count=0 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 6: Count=0 ScannedCount=10 CU=2.5 LastEvaluatedKey=yes
page 7: Count=0 ScannedCount=0 CU=0.0 LastEvaluatedKey=no
total CU across pages: 15.0

Vier der sechs echten Seiten gaben nichts zurück, zum vollen Preis. Das ist die Form des Bugs, den es zu verhindern gilt: eine selbstgebaute Schleife, die abbricht, wenn Items leer ist, hört auf Seite 1 auf und meldet zwei passende Songs als null.

Seite 7 ist die andere Hälfte. Seite 6 hat ihr Limit beim letzten Item der Tabelle erreicht, DynamoDB gab trotzdem einen LastEvaluatedKey zurück, und der Paginator hat einen weiteren Roundtrip aufgewendet, um zu erfahren, dass nichts mehr da war. Ein LastEvaluatedKey heißt „ich habe angehalten", nicht „es gibt mehr".

build_full_result() auf denselben Scan angewendet meldet CapacityUnits: 2.5. Die sechs Seiten haben 15,0 verbraucht.

Blättern, ohne die Schleife zu schreiben

Der DynamoDB Query Builder setzt den Filter, die Alias-Map und die Pagination-Schleife zu einem lauffähigen Programm zusammen, sodass die Limit-gegen-Count-Falle oben erledigt ist, bevor du es einfügst. Um eine echte Tabelle interaktiv statt aus einem Skript zu blättern, lade DynoTable herunter.

Verwandte Leitfäden

Referenzen

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

Diesen Request visuell bauen

Stelle diese Operation im kostenlosen DynamoDB Query Builder zusammen — Key-Bedingung, Filter, Index, Limit, Sortierreihenfolge und eine Paginierungsschleife — und kopiere sie als lauffähiges SDK-v3-, CLI- oder boto3-Programm zurück.

DynamoDB Query Builder öffnen

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.