Profi6 Min. Lesezeit

Parallele Scans in DynamoDB

Ein paralleler Scan teilt einen Scan in N unabhängige Scan-Requests auf. Jeder beansprucht ein Segment der Tabelle, sodass mehrere Worker gleichzeitig lesen. Das ist der einzige Weg, den die Scan-API bietet, um eine ganze Tabelle schneller zu lesen, als der Throughput einer einzelnen Partition erlaubt.

Was ist ein paralleler Scan in DynamoDB?

Ein paralleler Scan in DynamoDB teilt einen Scan in N unabhängige Requests auf. Jeder beansprucht über Segment und TotalSegments ein Segment der Tabelle, sodass mehrere Worker parallel lesen. Es ist der einzige Weg der Scan-API, eine ganze Tabelle schneller zu lesen, als der Throughput einer einzelnen Partition erlaubt — aber es bleibt ein vollständiger Read, also zahlst du für jedes gescannte Item.

  • Ein sequenzieller Scan liest eine Partition nach der anderen — seine Geschwindigkeit ist auf den Throughput einer einzelnen Partition begrenzt, egal wie groß die Tabelle ist.
  • Segment + TotalSegments sharden den Read über TotalSegments Worker; jeder Worker scannt seinen eigenen Slice parallel.
  • DynamoDB hasht den , um Segmente zuzuweisen, deshalb können Slices schief sein — mehr Worker bedeuten nicht immer mehr Tempo.
  • Es bleibt ein Scan: du zahlst, jedes Item zu lesen, und ein fetter paralleler Scan kann den Throughput der Tabelle unter dem Live-Traffic wegsaufen.

Warum ein sequenzieller Scan langsam ist

Aus SQL kommend fühlt sich ein Full-Table-Read wie eine Streaming-Operation an. In DynamoDB nicht. Die Daten der Tabelle leben über viele physische Partitionen, aber ein einzelner Scan läuft sie nacheinander ab, 1 MB pro Seite.

Das heißt: ein einfacher Scan kann in einem Moment nur aus dem Throughput- Budget einer Partition ziehen — selbst wenn die Tabelle über Dutzende Partitionen mit Idle-Capacity verteilt ist. Je größer die Tabelle, desto länger kriecht er. (AWS: Parallel scan)

Den Read mit Segment und TotalSegments aufteilen

Ein paralleler Scan behebt den Engpass. Du wählst eine Worker-Anzahl, setzt TotalSegments auf diese Zahl und gibst jedem Worker ein eindeutiges nullbasiertes Segment. Jeder Worker stellt seinen eigenen Scan; DynamoDB bedient sie parallel.

Worker 0Scan  Segment=0  TotalSegments=4
Worker 1Scan  Segment=1  TotalSegments=4
Worker 2Scan  Segment=2  TotalSegments=4
Worker 3Scan  Segment=3  TotalSegments=4

Jeder Worker paginiert weiterhin unabhängig mit LastEvaluatedKey — er besitzt sein Segment von der ersten bis zur letzten Seite. Die Anwendung fügt die vier Streams wieder zusammen. Du liest jetzt Throughput von vier Partitionen auf einmal statt von einer.

Praxisbeispiel: der nächtliche Export

Angenommen, du betreibst eine Telemetrie-Tabelle sensor-readings. Jedes Item ist eine Messung eines Feldgeräts:

PK = "DEVICE#a83f"          (partition key — the device id)
SK = "TS#2026-06-22T03:14"  (sort key — ISO timestamp)
batteryMv  = 3120
tempC      = 41.8
firmwareTag = "fw-7.2.1"

Jede Nacht dumppt ein Cron-Job die gesamte Tabelle nach S3 für das Analytics- Warehouse. Ein sequenzieller Scan von 80 GB dauert Stunden und knabbert kaum an deiner provisionierten Read Capacity. Also fächerst du ihn über acht Worker auf:

Scan  sensor-readings  Segment=0  TotalSegments=8  ConsistentRead=falseScan  sensor-readings  Segment=7  TotalSegments=8  ConsistentRead=false

Acht Worker, acht Segmente, ein Table-Read grob achtmal schneller. Wenn du nur aktuelle Readings brauchst, füge eine FilterExpression hinzu, die alte Timestamps verwirft, bevor die Zeilen über die Leitung gehen — baue und prüfe diesen Ausdruck im Expression Builder:

FilterExpression:  begins_with(SK, :today)

Wie DynamoDB Items Segmenten zuweist

DynamoDB weist jedes Item einem Segment zu, indem es seinen Partition Key hasht — nicht nach Zeilenanzahl, nicht nach Byte-Anzahl.

Jedes Item mit demselben PK landet also im selben Segment. In sensor-readings gehen alle Readings für DEVICE#a83f an einen Worker, unabhängig davon, wie viele Timestamps das Gerät hat oder wie groß seine ist. (AWS: Parallel scan)

Tabelle sensor-readingsHash-PartitionsschlüsselSegment 0DEVICE#a83fDEVICE#1c20Segment 1DEVICE#9be4Segment 2 (leer)

Segmente werden ungleich. Ein Worker kann drei gesprächige Geräte mit Millionen Readings besitzen; ein anderer zieht einen leeren Slice. TotalSegments höher zu drehen hilft nicht, wenn deine Partition Keys klumpen — du fügst nur idle Worker hinzu, die auf den heißen warten. Gleichmäßige Key-Verteilung macht den Fan-out erst lohnenswert.

Die Read-Kosten sehen, bevor du startest

Ein paralleler Scan ist ein Throughput-Ereignis, kein Free Lunch. Die ehrliche Frage lautet: „Wie viel von dieser ganzen Tabelle lese ich gerade?“ — und bevor DynoTable einen Full-Table-Read ausführt, stoppt dich ein Confirm-Dialog mit ungefährer Tabellengröße und Item-Anzahl plus Read-Capacity-Warnung, streamt dann live den Items-scanned-Fortschritt, damit der nächtliche Job dich nicht überrascht.

Fallstricke und wann es sich nicht lohnt

  • Die Throughput-Klippe. Ein Scan mit hohem TotalSegments kann die gesamte Read Capacity der Tabelle in Sekunden auffressen und Live-Traffic aushungern. Auf einer Tabelle mit Nutzern drossele jeden Worker mit dem Limit-Parameter oder scanne außerhalb der Peak-Zeit. (AWS: Parallel scan)
  • Es bleibt das falsche Werkzeug für ein Access Pattern. Parallele Scans sind für bewusste Full-Table-Jobs — Exports, Backfills, Migrationen. Greifst du zu einem, um eine wiederkehrende Query zu beantworten, ist das ein Modeling-Signal: füge einen GSI hinzu und mach daraus eine Query.
  • SELECT * in PartiQL ist derselbe Scan in Verkleidung. Es kompiliert zu einem sequenziellen Scan. Wenn du wirklich Cross-Item-Analytics brauchst — ein GROUP BY, ein JOIN, ein Aggregat — führt DynoTables SQL Workbench das clientseitig über ein begrenztes Resultset aus, statt die Tabelle zu hämmern.
  • Starke Konsistenz verdoppelt die Rechnung. Ein Scan defaultet zu Reads. Für einen Export lass ConsistentRead=false, außer jede Seite muss die allerneuesten Writes widerspiegeln — und beachte: selbst ein stark konsistenter Scan dauert Minuten, ist also kein Point-in-Time-Snapshot (nutze dafür PITR/Export).

Nächste Schritte

Modelliere deine Keys so, dass Alltags-Reads nie einen Scan brauchen — starte mit Single-Table Design und Query vs Scan. Wenn ein Full-Table-Job wirklich der richtige Call ist, probier DynoTable, um Full-Table-Reads mit Größen- und Kostenwarnung vorab und live Scan-Fortschritt zu fahren.

Aktualisiert