Profi6 Min. Lesezeit

DynamoDB-Parallel-Scans

Ein Parallel-Scan teilt einen Scan in N unabhängige Scan-Requests, von denen jeder ein Segment der Tabelle beansprucht, sodass mehrere Worker sie gleichzeitig lesen. Es ist der einzige Weg, eine ganze Tabelle schneller zu lesen, als es der Throughput einer Partition erlaubt.

Was ist ein DynamoDB-Parallel-Scan?

Ein DynamoDB-Parallel-Scan teilt einen Scan in N unabhängige Requests, von denen jeder über Segment und TotalSegments ein Segment der Tabelle beansprucht, sodass mehrere Worker ihn gleichzeitig lesen. Es ist der einzige Weg, eine ganze Tabelle schneller zu lesen, als der Throughput einer einzelnen Partition erlaubt – aber es ist immer noch ein vollständiger Read, du zahlst also für jedes gescannte Item.

  • Ein sequenzieller Scan liest eine Partition nach der anderen — seine Geschwindigkeit ist auf den Throughput einer einzelnen Partition gedeckelt, egal wie groß die Tabelle ist.
  • Segment + TotalSegments sharden den Read über TotalSegments Worker; jeder Worker scannt seine eigene Scheibe parallel.
  • DynamoDB hasht den Partition Key, um Segmente zuzuweisen, sodass Scheiben schief sein können — mehr Worker bedeutet nicht immer schneller.
  • Es ist immer noch ein Scan: Du zahlst, um jedes Item zu lesen, und ein fetter Parallel-Scan kann den Throughput der Tabelle unter deinem Live-Traffic wegziehen.

Warum ein sequenzieller Scan langsam ist

Von SQL kommend fühlt sich ein Volltabellen-Read wie eine streamende Operation an. In DynamoDB ist er das nicht. Die Daten der Tabelle leben über viele physische Partitionen, aber ein einzelner Scan läuft sie eine nach der anderen ab, 1 MB pro Page.

Das bedeutet, ein einfacher Scan kann zu einem Zeitpunkt immer nur aus dem Throughput-Budget einer Partition ziehen — selbst wenn die Tabelle über Dutzende Partitionen mit ungenutzter Kapazität verteilt ist. Je größer die Tabelle, desto länger kriecht er. (AWS: Parallel Scan)

Den Read mit Segment und TotalSegments aufteilen

Ein Parallel-Scan behebt den Bottleneck. 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 nebenläufig.

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 Page bis zur letzten. Die Anwendung näht die vier Streams wieder zusammen. Du liest jetzt den Throughput von vier Partitionen auf einmal statt von einer.

Ein durchgearbeitetes Beispiel: der nächtliche Export

Sagen wir, du betreibst eine Telemetrie-Tabelle, sensor-readings. Jedes Item ist eine Messung von einem Feldgerät:

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 kippt ein Cron-Job die ganze Tabelle nach S3 für das Analytics-Warehouse. Ein sequenzieller Scan von 80 GB dauert Stunden und kratzt kaum an deiner provisionierten Read-Kapazität. 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 Tabellen-Read etwa achtmal schneller. Wenn du nur aktuelle Messungen brauchst, füge eine FilterExpression hinzu, um alte Timestamps zu verwerfen, bevor die Zeilen über die Leitung gehen — baue und inspiziere diese Expression im Expression Builder:

FilterExpression:  begins_with(SK, :today)

Wie DynamoDB Items zu Segmenten zuweist

Hier ist der Teil, über den Leute stolpern. DynamoDB weist jedes Item einem Segment zu, indem es seinen Partition Key hasht — nicht nach Zeilenanzahl, nicht nach Byte-Anzahl.

Also landet jedes Item, das sich einen PK teilt, im selben Segment. In sensor-readings gehen alle Messungen für DEVICE#a83f an einen Worker, egal wie viele Timestamps dieses Gerät hat oder wie groß seine Item-Collection ist. (AWS: Parallel Scan)

sensor-readings tablePartition Key hashenSegment 0DEVICE#a83fDEVICE#1c20Segment 1DEVICE#9be4Segment 2 (leer)

Die Konsequenz: Segmente sind ungleich. Ein Worker könnte drei geschwätzige Geräte mit Millionen von Messungen besitzen; ein anderer könnte eine leere Scheibe ziehen. TotalSegments hochzukurbeln hilft nicht, wenn deine Partition Keys klumpen — du fügst nur untätige Worker hinzu, die auf den heißen warten. Gleiche Key-Verteilung ist das, was das Auffächern lohnenswert macht.

Die Read-Kosten sehen, bevor du läufst

Ein Parallel-Scan ist ein Throughput-Event, kein kostenloses Mittagessen. Die ehrliche Frage ist „wie viele Read Units kostet das Lesen dieser ganzen Tabelle?" — und DynoTable zeigt dir die gemessenen Read-Kosten eines Scans gegen deine echte Tabelle, Segment für Segment, sodass der nächtliche Job dich nicht auf der Rechnung überrascht.

Fallstricke und wann es sich nicht lohnt

  • Die Throughput-Klippe. Ein Scan mit hohem TotalSegments kann die gesamte Read-Kapazität der Tabelle in Sekunden verbrauchen und Live-Traffic aushungern. Auf einer Tabelle, die Nutzer bedient, drossle jeden Worker mit dem Limit-Parameter oder scanne außerhalb der Spitzenzeiten. (AWS: Parallel Scan)
  • Es ist immer noch das falsche Werkzeug für ein Access Pattern. Parallel-Scans sind für bewusste Volltabellen-Jobs — Exporte, Backfills, Migrationen. Wenn du zu einem greifst, um eine wiederkehrende Query zu beantworten, ist das ein Modellierungssignal: Füge einen GSI hinzu und mach eine Query daraus.
  • SELECT * in PartiQL ist derselbe Scan in Verkleidung. Es kompiliert zu einem sequenziellen Scan. Wenn du tatsächlich Cross-Item-Analytics brauchst — ein GROUP BY, einen JOIN, ein Aggregat — führt die SQL-Workbench von DynoTable diese client-seitig über eine begrenzte Ergebnismenge aus, statt die Tabelle zu hämmern.
  • Starke Konsistenz verdoppelt die Rechnung. Ein Scan ist standardmäßig letztendlich konsistent. Für einen Export lass ConsistentRead=false, es sei denn, du brauchst wirklich einen Point-in-Time-Snapshot.

Nächste Schritte

Modelliere deine Keys so, dass Reads im Alltag nie einen Scan brauchen — beginne mit Single-Table-Design und Query vs Scan. Wenn ein Volltabellen-Job wirklich die richtige Wahl ist, probiere DynoTable aus, um einen Parallel-Scan gegen deine eigenen Tabellen zu fahren und die Read-Kosten in Echtzeit zu beobachten.

Aktualisiert