Physische Partitionen in DynamoDB
Eine physische Partition ist die Einheit, auf der DynamoDB deine Daten tatsächlich speichert: eine Scheibe SSD, über Availability Zones repliziert, die einen Ausschnitt deines Key-Space hält. Deine Tabelle ist ein logisches Konstrukt. In den Partitionen liegen die Bytes — und die Durchsatz-Limits.
Wie funktionieren DynamoDB-Partitionen?
DynamoDB verteilt deine Tabelle über physische Partitionen — SSD-Scheiben, die über Availability Zones repliziert werden. Jede ist bei ~10 GB, 3.000 Read Units/Sek. und 1.000 Write Units/Sek. gedeckelt. Der Hash deines entscheidet, auf welcher Partition ein Item landet, und DynamoDB teilt Partitionen automatisch, wenn sie wachsen oder heiß laufen.
- Jede Partition ist bei ~10 GB Speicher, 3.000 Read Units/Sek. und 1.000 Write Units/Sek. gedeckelt. Diese Obergrenzen gelten pro Partition, nicht pro Tabelle.
- Der Hash deines wählt die Partition. Items mit demselben Key landen zusammen; ein einzelnes heißes — oder ein monotoner Sort Key — nagelt eine Partition fest.
- DynamoDB teilt Partitionen für dich — nach Größe und nach anhaltender Last — und trennt dabei auch die Item Collection eines einzelnen Keys an einer Sort-Key-Grenze, sofern kein LSI oder ein immer weiter steigender Sort Key das blockiert.
- Drosselung mit Kapazität im Überfluss ist das verräterische Zeichen. Ein Fehler
ProvisionedThroughputExceeded, während deine Tabelle bei 5 % Auslastung liegt, heißt: Eine einzelne Partition ist am Anschlag.
Wie ein Item seine Partition findet
DynamoDB schickt den Wert deines Partition Keys durch eine interne Hash-Funktion. Die Hash-Ausgabe wählt die physische Partition. Gleicher Key rein, gleiche Partition raus — jedes Mal.
Aus der SQL-Welt gibt es dazu keine Entsprechung. Es gibt keinen B-Baum-Index, den du tunst, und keinen Shard-Key, den du von Hand vergibst. Die Platzierung ist ein Hash, den du weder steuerst noch je siehst.
Items mit demselben Partition Key bilden eine , gemeinsam gespeichert und
nach Sort Key sortiert. Genau das macht eine Query auf einen Key günstig — sie liest einen
zusammenhängenden Lauf auf einer Partition. (Siehe Query vs. Scan.)
Nimm einen Match-Event-Store für ein Spiel. Die Tabellen-Keys sind arenaId (Partition) und
eventKey (Sort):
# Item
arenaId = "ARENA#7f3a"
eventKey = "EVT#1719100800#a91c"
playerTag = "Nightjar"
dmgDealt = 412
Jedes Event für Arena 7f3a hasht auf dieselbe Partition und stapelt sich in Sort-Key-Reihenfolge.
Ideal für „lies die Timeline dieses Matches“. Ein Risiko, wenn genau diese eine Arena
den ganzen Traffic bekommt.
Die drei Obergrenzen, die jede Partition durchsetzt
Eine einzelne Partition ist dafür ausgelegt, höchstens Folgendes zu liefern:
| Limit | Pro Partition | Gezählt als |
|---|---|---|
| Speicher | ~10 GB | rohe Item-Bytes |
| Lesekapazität | 3.000 Read Units/Sek. | 1 RU = ein stark konsistenter Lesevorgang über 4 KB |
| Schreibkapazität | 1.000 Write Units/Sek. | 1 WU = ein Schreibvorgang über 1 KB |
Quelle: der AWS-Leitfaden Best practices for designing partition keys.
Die Item-Größe skaliert die Rechnung. Ein Item mit 20 KB kostet 5 Read Units pro stark konsistentem Lesevorgang, eine Partition bedient also ~600 solcher Lesevorgänge/Sek., bevor sie drosselt — nicht 3.000. Schreibkosten runden je 1 KB auf, Lesekosten je 4 KB.
Diese Deckel gelten pro Partition, nicht pro Tabelle. Deine Tabelle kann mit 40.000 WCU provisioniert sein und trotzdem drosseln, weil alle Schreibvorgänge auf eine Partition eindreschen, die bei 1.000 endet.
Wie Partitionen sich teilen
DynamoDB fügt in zwei Fällen automatisch Partitionen hinzu. Du führst nie einen Befehl aus.
Teilung nach Größe. Füllt sich eine Partition Richtung ~10 GB, halbiert DynamoDB ihren Key-Bereich und verschiebt die Hälfte der Items auf eine neue Partition. Der Speicher wächst transparent; deine Lese- und Schreibvorgänge laufen die ganze Zeit weiter.
Teilung nach Last. Nimmt eine Partition anhaltenden Traffic nahe ihrer Durchsatzgrenze auf, teilt DynamoDB den heißen Key-Bereich, sodass jede Hälfte auf einer eigenen Partition landet. AWS nennt das den Split-for-Heat-Mechanismus. Kurze Drosselungsschübe, die von selbst aufhören, bedeuten oft, dass Split-for-Heat gegriffen hat — kurze Spitzen können allerdings auch schlicht aufgebrauchte Burst-Kapazität sein.
Teilen schafft Luft über viele Keys hinweg, und Split-for-Heat kann sogar die Item Collection eines Keys an einem Sort-Key-Schnitt zerlegen. Was es nicht verteilen kann, ist ein einzelnes heißes Item, ein immer weiter steigender Sort Key oder eine Collection, die durch ein LSI festgenagelt ist.
Warum ein Hot Key den Splitter schlägt
Das Teilen verteilt Bereiche von Partition Keys neu. Konzentriert sich dein Traffic auf einen Key-Wert, hasht jede Anfrage auf dieselbe Partition, und es bleibt kein Bereich übrig, den man aufteilen könnte.
Ist Arena 7f3a ein Turnierfinale, das 4.000 Schreibvorgänge/Sek. zieht, während jede andere
Arena leer läuft, drosselst du bei 1.000 — und Split-for-Heat rettet dich hier nicht,
weil der zeitstempel-präfixierte eventKey monoton ist: Jeder neue Schreibvorgang landet an
der Vorderkante eines einzigen schmalen Sort-Key-Bereichs, von dem nichts abzutrennen ist. Der neuere
Drosselungsgrund KeyRangeThroughputExceeded benennt genau das: Der Key-Bereich einer Partition
ist über dem Limit, nicht die Tabelle.
Die Lösung steckt im Datenmodell, nicht im Kapazitätsregler. Write-Sharde den Hot Key: Häng ein kleines Suffix an, damit sich eine logische Arena über N physische Partitionen verteilt.
arenaId = "ARENA#7f3a#3" # shard 0..9, chosen per writeLesevorgänge fächern dann über die Shards auf und werden clientseitig zusammengeführt. Die Key-Formen und die
Query je Shard kannst du im
DynamoDB Expression Builder prototypisieren, bevor du eine
Zeile Anwendungscode anfasst.
Eine Feinheit: die LSI-Ausnahme
Es gibt einen Fall, in dem der Speicher doch pro Partition Key gedeckelt ist. Ohne einen verteilt sich eine Item Collection über so viele Partitionen, wie sie braucht, um ihre gespeicherten Bytes und ihren Durchsatz zu bedienen — Milliarden Sort-Key-Werte sind kein Problem.
Kommt ein LSI dazu, muss die gesamte Collection eines Partition Keys in eine einzige 10-GB-Partition passen, weil das LSI sie mitbenutzt. Das ist die Klippe pro PK, die GSI vs. LSI behandelt — ein weiterer Grund, warum die meisten Teams zu GSIs greifen.
So modellierst du, dass Partitionen kühl bleiben
Der Hebel, den du wirklich in der Hand hast, ist der Partition Key. Wähle einen mit vielen verschiedenen Werten im Verhältnis zur Zeilenzahl, damit sich der Traffic gleichmäßig verteilt. (Mehr Muster in Single-Table-Design.)
- Key mit hoher Kardinalität. Ein Key pro Nutzer oder pro Mandant schlägt einen Key pro Tag oder pro Status, auf den alle gleichzeitig eindreschen.
- Achte auf bekannte Hot Keys. Ein Wert wie „aktuelles Turnier“ oder „heute“ ist ein Konzentrationsrisiko, bevor du ausrollst, nicht danach.
- Sharde den unvermeidbaren Hot Key. Muss ein Key übergroßen Traffic aufnehmen, ist ein Suffix die übliche Notausfahrt.
Drosselung mit Kapazität im Überfluss ist dein Signal, dass eine Partition heiß ist. Inspiziere die schiefe Item Collection und probe ein geshardetes Key-Layout in DynoTable — richte es auf deine eigene Tabelle, gruppiere im SQL Workbench mit GROUP BY nach dem Partition Key, um zu sehen, welche Keys dominieren, und modelliere die Lösung, bevor sie dich nachts weckt.