Wie DynamoDB-Storage-Internals funktionieren
DynamoDB ist eine Hashtabelle, deren Werte sortierte Bäume sind, verteilt über Maschinen in drei Availability Zones. Zwei Datenstrukturen leisten fast die ganze Arbeit: Ein Hash auf dem Partition Key wählt eine Maschine, ein B-Baum auf dem Sort Key ordnet Items darin.
Wie speichert DynamoDB Daten?
DynamoDB speichert deine Daten als riesige verteilte Hashtabelle, deren Werte sortierte B-Bäume sind. Ein Hash auf dem Partition Key wählt eine Storage-Node; ein B-Baum ordnet Items darin nach Sort Key. Jeder Write wird synchron auf drei Nodes in drei Availability Zones repliziert, bevor er bestätigt wird.
- Der Partition Key wird gehasht, nicht durchsucht. DynamoDB jagt eine
Hash-Funktion über deinen
PK, um die eine Storage-Node zu finden, die diese Partition hält — ein O(1)-Sprung, unabhängig von der Tabellengröße. - Der Sort Key lebt in einem B-Baum. Innerhalb einer Partition werden Items in
einem B-Baum gespeichert, lexikografisch nach
SKgeordnet, weshalb Bereichs-Reads (begins_with,between) billig sind undScannicht. - Jeder Write trifft drei Nodes, bevor er ackt. Ein Write geht an einen
Leader, der synchron zu zwei Peers in anderen AZs repliziert — Dauerhaftigkeit
ist gekauft, bevor dein
PutItemzurückkehrt. - Deshalb existieren die Access-Pattern-Regeln. Hash-dann-Baum ist nur schnell, wenn du nach Key liest. Kein Key, kein schneller Pfad — du fällst zurück aufs Scannen des Baums.
Beginne mit der Datenstruktur, nicht der API
Von SQL kommend stellst du dir eine Tabelle als Zeilen auf der Platte vor, mit einem Query-Planner, der Indizes wählt. DynamoDB hat keinen Planner. Das Storage-Layout ist der Vertrag — was schnell ist und was ein Footgun ist, fällt beides direkt aus zwei Strukturen.
Stell dir eine riesige verteilte Map vor. Der Key ist ein Hash deines Partition Keys. Der Wert ist kein einzelnes Item — er ist ein ganzer B-Baum von Items, die sich diesen Partition Key teilen, geordnet nach Sort Key.
Alles andere — Query-Semantik, die 10-GB-Warnungen, warum ein fehlender Key einen
Scan erzwingt — ist eine Konsequenz dieses einen Satzes.
Den Partition Key hashen, um die Node zu finden
Wenn ein Request ankommt, wendet DynamoDB eine interne Hash-Funktion auf den Partition-Key-Wert an. Der Hash bildet deterministisch auf eine Storage-Node ab — die physische Partition, die diese Items besitzt. AWS dokumentiert das als den Mechanismus hinter Key-Lookups in konstanter Zeit, unabhängig von der Tabellengröße.
Das ist der O(1)-Schritt. Eine 10-TB-Tabelle und eine 10-KB-Tabelle kosten gleich viel zum Lokalisieren: hashen, springen, fertig. Es gibt keinen Index-Scan, um die Node zu finden, keine Statistiken, keinen Plan.
Der Haken ist die Kehrseite. Wenn du den Partition Key nicht lieferst, hat
DynamoDB keine Node zum Springen — es muss jede Partition ablaufen. Das ist ein
Scan, und es ist der Unterschied zwischen O(1) und dem Lesen der ganzen Tabelle.
Der Request hasht auf genau eine Partition, dann steigt er den Sort-Key-B-Baum dieser Partition zum Item hinab — zwei billige Schritte statt eines Tabellendurchlaufs.
Items in einem Per-Partition-B-Baum ordnen
Innerhalb einer einzelnen Partition sind Items kein Heap. Sie werden in einem
B-Baum, verschlüsselt nach dem Sort Key, gehalten, lexikografisch geordnet.
Eine B-Baum-Suche ist O(log n), und entscheidend ist dieses n die Items in
einer Partition, nicht der ganzen Tabelle.
Das ist der ganze Grund, warum Sort-Key-Bereichs-Reads billig sind. Nimm eine Fleet-Telemetrie-Tabelle, wo die Messungen jedes Geräts unter einem Partition Key leben:
| PK | SK |
|---|---|
| PK = DEVICE#a91 | SK = READING#2026-06-23T08:00Z |
| PK = DEVICE#a91 | SK = READING#2026-06-23T08:05Z |
| PK = DEVICE#a91 | SK = READING#2026-06-23T08:10Z |
Weil der B-Baum sortiert ist, ist „alle Messungen zwischen 08:00 und 09:00" ein Baumabstieg zum Startwert plus ein sequenzieller Lauf — kein Filter über jede Messung, die das Gerät je gesendet hat. Du liest nur den gematchten Bereich.
Diese Ordnung ist auch, warum eine
begins_with(SK, "READING#2026-06-23")-Query schnell ist, während Filtern auf
einem Nicht-Key-Attribut es nicht ist. Der Baum kann nach SK seeken; er kann
nach nichts anderem seeken. Um diese Key-Bedingungen sicher zusammenzusetzen, baue
sie im DynamoDB Expression Builder, statt
Strings von Hand zu verketten:
KeyConditionExpression PK = :pk AND begins_with(SK, :day)
Jeden Write in drei AZs replizieren
Eine Partition ist nicht eine Maschine. Jede ist über drei Nodes in drei Availability Zones repliziert — eine Design-Abstammung, die bis zum Replikationsmodell des Amazon-Dynamo-Papers von 2007 zurückreicht.
Eine Node ist der Leader für die Partition. Ein Write geht an den Leader, der
lokal schreibt und zu seinen zwei Peers repliziert. Der Leader ackt den Write,
sobald ein dauerhaftes Quorum von Nodes ihn hat — sodass Dauerhaftigkeit über AZs
bezahlt ist, bevor dein PutItem zurückkehrt.
Reads haben eine Wahl. Ein stark konsistenter Read geht an den Leader und sieht den letzten committeten Write. Ein letztendlich konsistenter Read kann von jeder der drei Nodes bedient werden, von denen eine ein paar Millisekunden hinten sein kann — das ist die Verzögerung, die du gegen billigere, verfügbarere Reads tauschst.
| Letztendlich konsistent | Stark konsistent | |
|---|---|---|
| Bedient von | Jede der 3 Nodes | Nur Leader-Node |
| Sieht letzten Write | Vielleicht (kleine Verzögerung) | Immer |
| RCU-Kosten | Halbe | Volle |
| Verfügbarkeit | Höher | Niedriger (einzelne Node) |
Dieselbe Async-Propagationsidee ist, warum ein GSI-Read veraltet sein kann — siehe GSIs sind letztendlich konsistent.
Die Regeln aus der Struktur ablesen
Fast jede DynamoDB-„Regel" ist einfach Storage-Physik:
- Liefere immer den Partition Key. Kein Key, kein Hash-Ziel — du scannst die ganze Map. Das ist der Kern von Query vs Scan.
- Lokalisiere zusammen, was du zusammen liest unter einem Partition Key, sodass ein einzelner Hash + Baumlauf die ganze Item-Collection zurückgibt. Das ist die Grundlage von Single-Table-Design.
- Halte Partitionen begrenzt. Eine Partition ist ein B-Baum auf einer endlichen Menge von Nodes; ein außer Kontrolle geratener Hot Key oder die 10-GB-Grenze eines LSI sind beides Limits dieser physischen Partition.
Sobald du die Hash-dann-B-Baum-Form siehst, hört die Access-Pattern-Disziplin auf, sich willkürlich anzufühlen — du hältst einfach jeden Read auf dem schnellen Pfad.
Nächste Schritte
Modelliere deine Keys passend zur Struktur mit Sort-Key-Strategien und Single-Table-Design, dann stelle die tatsächlichen Expressions im DynamoDB Expression Builder zusammen. Probiere DynoTable aus, um diese Reads gegen deine eigenen Tabellen laufen zu sehen und genau zu sehen, welche Items eine Key-Bedingung zurückzieht.