DynamoDB Hot Partitions: finden und beheben
DynamoDB verteilt deine Daten über viele physische Partitionen, jede mit ihrem eigenen Durchsatzanteil. Eine Hot Partition liegt vor, wenn ein Schlüssel weit mehr Reads oder Writes anzieht, als sein Anteil bedienen kann — Requests auf diesen Schlüssel drosseln also, während der Rest der Tabelle Däumchen dreht.
Was ist eine Hot Partition in DynamoDB?
Eine Hot Partition in DynamoDB liegt vor, wenn ein weit mehr Reads oder Writes abbekommt, als sein Durchsatzanteil bedienen kann, sodass Requests auf diesen Schlüssel drosseln, während der Rest der Tabelle nichts zu tun hat. Die Ursache ist das Schlüsseldesign — ein Promi-Item, ein Schlüssel mit niedriger Kardinalität, das heutige Datum — nicht die Tabellengröße. Die Kur ist, die Writes zu verteilen.
- Die Ursache ist das Schlüsseldesign, nicht die Tabellengröße. Ein ,
der Traffic bündelt — ein prominenter Nutzer, ein
status="OPEN"-Flag, das heutige Datum —, ist die Falle. - Adaptive Capacity hilft, ist aber keine Lösung. DynamoDB verteilt Hitze automatisch um, doch ein einzelnes Item oder ein einzelner Schlüssel kann trotzdem mehr verlangen, als eine Partition bedienen kann.
- Die Kur ist, Writes zu verteilen. Bring Entropie in den Schlüssel (Write Sharding) oder verlager den heißen Lesepfad auf ein besser verteiltes Zugriffsmuster.
- Aus SQL kommend gibt es dafür keine Entsprechung. Eine relationale Tabelle kennt kein „der Indexwert einer Zeile ist zu beliebt" — DynamoDBs flaches Modell aus Durchsatz pro Schlüssel schon.
Warum es überhaupt Partitionen gibt
DynamoDB ist der produktive Erbe des Amazon-Dynamo-Papers von 2007, das das Einzelknoten-SQL-Modell gegen ein partitioniertes, horizontal skalierendes eintauschte. Daten werden über einen Hash des Partitionsschlüssels auf physische Storage-Knoten geshardet.
Jede Partition hält eine begrenzte Datenmenge und bedient einen begrenzten Durchsatz. AWS
dokumentiert eine harte Obergrenze von 3.000 RCU und 1.000 WCU pro Partition und Sekunde —
dieselbe weiche Grenze bei Provisioned wie bei On-Demand in
us-east-1
(AWS — partition behavior).
Der Abrechnungsmodus hebt die physikalische Grenze nicht an; er ändert nur, wie die Ausgaben
auf Tabellenebene gemessen werden. Nimm den Preisrechner
für die Kosten auf Tabellenebene und Contributor Insights, um zu sehen, ob die Drosselung
partitions- oder tabellenbedingt ist.
Diese Obergrenze ist die ganze Geschichte. Der Durchsatz deiner Tabelle ist die Summe über alle Partitionen. Die Item Collection eines Schlüssels beginnt auf einer Partition, und Split-for-Heat kann sie an Sortierschlüsselgrenzen über mehrere verteilen — außer die Tabelle hat einen LSI oder der Sortierschlüssel wächst monoton, was sie auf eine festnagelt.
Die Falle benennen: Traffic, der sich auf einem Schlüssel staut
Der Durchsatz wird nur dann gleichmäßig geteilt, wenn dein Zugriff gleichmäßig über die Schlüssel streut. Sobald ein Schlüssel überproportionalen Traffic bekommt, drosselt er allein, während die Gesamtkapazität der Tabelle brachliegt.
Klassische Hot-Key-Formen:
- Ein Promi-Item — ein Nutzer, Produkt oder Mandant, den alle lesen.
- Ein Partitionsschlüssel mit niedriger Kardinalität —
status,country,type. Wenige verschiedene Werte heißt: wenige Partitionen machen die ganze Arbeit. - Ein zeitgebucketeter Schlüssel —
PK = "2026-06-23". Jeder Write von heute hämmert auf eine Partition; die von gestern ist für immer kalt.
Aus SQL kommend wäre nichts davon relevant. Ein B-Tree-Index auf einem beliebten Wert ist unproblematisch. In DynamoDB ist der beliebte Wert die Einheit der physischen Platzierung, Beliebtheit wird also zur Durchsatzklippe.
Ein durchgerechnetes Beispiel: das Promi-Leaderboard
Sagen wir, du betreibst ein globales Gaming-Leaderboard. Die Punktestände liegen in einer Tabelle mit diesen Schlüsseln:
PK = "BOARD#global"
SK = "PLAYER#<playerId>"
Reads holen die Top N nach Punktzahl; Writes erhöhen nach jedem Match den currentScore eines
Spielers. Jede Zeile des globalen Boards teilt sich einen Partitionsschlüssel —
BOARD#global —, jeder Read und jeder Write landet also auf einer einzigen Partition.
Nimm einen Streamer mit zwei Millionen Live-Zuschauern dazu, die den Refresh-Knopf auf seinem
Rang malträtieren, und diese eine Partition kippt über 3.000 Leseeinheiten. Du bekommst eine
ProvisionedThroughputExceededException auf dem globalen Board, während jedes andere Board in
der Tabelle Leerlauf hat.
Der Fallstrick ist der BOARD#global-Kollaps: Du hast ein einziges logisches Board als einen
einzigen physischen Schlüssel modelliert.
Die Writes verteilen: den Schlüssel sharden
Die Lösung besteht darin, Kardinalität zu fabrizieren. Häng ein Shard-Suffix an den Partitionsschlüssel, damit ein logisches Board über N physische Partitionen auffächert:
PK = "BOARD#global#<shard>" -- shard = playerId mod 10
SK = "PLAYER#<playerId>"
Writes streuen jetzt über zehn Partitionen statt einer — zehnmal so viel Schreib-Spielraum. Der
Preis: Ein Read des ganzen Boards muss alle zehn Shards treffen und zusammenführen, denn kein
einzelnes Query überspannt Shard-Grenzen. Du tauschst Lese-Einfachheit gegen
Schreibverteilung.
Sieh dir den Unterschied selbst an. Füg unten einen einzelnen, wiederholten Schlüssel in den
Visualizer ein, und jeder Write landet in einem Bucket — der Hot Partition. Ergänz ein
Shard-Suffix (BOARD#global#0 … #9), und dieselben Writes fächern gleichmäßig auf:
Das ist ein Lehr-Hash zur Veranschaulichung, nicht der echte interne Hash von DynamoDB — die tatsächliche Funktion und die Partitionsgrenzen sind AWS-Interna. Lies es als „gleichmäßige Verteilung vs. Schieflage", nicht als Vorhersage, auf welcher physischen Partition ein Schlüssel landet.
AWS nennt das Write Sharding und empfiehlt es genau für Schlüssel mit hoher Frequenz und niedriger Kardinalität (AWS — using write sharding).
Es ist derselbe -Reflex, der hinter Single-Table Design steckt — du formst den Schlüssel für das Zugriffsmuster, nicht danach, wie die Daten „natürlich" liegen.
Lass Adaptive Capacity den einfachen Teil erledigen
DynamoDB liefert Adaptive Capacity mit, behandelt in der re:Invent-Session 2018 „Amazon DynamoDB Under the Hood" (DAT401). Sie verteilt den Durchsatz einer Tabelle laufend zu den Partitionen um, die Hitze abbekommen, und isoliert einen dauerhaft heißen Schlüssel auf eine eigene Partition (Key-Level-Isolation, AWS — bursting & adaptive capacity).
Das passiert sofort und kostenlos — ist aber von der Physik begrenzt (wie Adaptive Capacity funktioniert). Adaptive Capacity kann Hitze zwischen Schlüsseln verschieben, und Split-for-Heat kann eine heiße Item Collection sogar an einer Sortierschlüsselgrenze aufteilen. Absolut bleibt die Grenze pro Partition nur für ein einzelnes heißes Item, einen monoton wachsenden Sortierschlüssel oder eine Tabelle mit LSI — dort drosselt ein Promi-Schlüssel weiterhin. Sharding ist die deterministische Lösung; Split-for-Heat ist langsam und opportunistisch, warte also nicht darauf.
Entscheidungspfad, sobald du Drosselung auf einem stark genutzten Schlüssel siehst:
Die meisten Hot Partitions lösen sich entweder in „Schlüssel sharden" oder „Adaptive Capacity fängt es ab" auf — das Diagramm sagt dir nur, in welchem Zweig du bist.
Diagnostizieren, bevor du umbaust
Was du nicht siehst, kannst du nicht reparieren. Drosselung zeigt sich als
ProvisionedThroughputExceededException (bei Provisioned) oder als
ThrottledRequests, ReadThrottleEvents/WriteThrottleEvents und
ReadThrottleEventsForKeyRange/WriteThrottleEventsForKeyRange — den
partitionsspezifischen Zählern — in CloudWatch
(AWS — CloudWatch metrics).
Kombiniere das mit CloudWatch Contributor Insights für DynamoDB, das deine meistgenutzten Schlüssel direkt sortiert — der schnellste Weg, einen Promi-Schlüssel beim Namen zu bestätigen (AWS — Contributor Insights). Und wenn du noch gar nicht sicher bist, dass ein heißer Schlüssel überhaupt die Ursache ist — DynamoDB drosselt aus vier verschiedenen Gründen —, fang beim Throttling-Guide an und lass die Metriken benennen, welche Grenze du wirklich gerissen hast.
Wenn du den geshardeten Lesepfad testest, baust du für jeden Shard die
KeyConditionExpression von Hand. Erzeug sie ohne Tippfehler im
DynamoDB Expression Builder — er gibt pro Shard genau die
Form PK = :pk AND begins_with(SK, :sk) aus.
Fallstricke, die du vermeiden solltest
- Monoton wachsende Sortierschlüssel. Ein monotoner Sortierschlüssel (ein Zeitstempel, eine Sequenznummer) zwingt jeden neuen Write ans selbe Ende einer Item Collection, und Split-for-Heat kann nicht helfen — die Collection bleibt bei 1.000 Schreibeinheiten gedeckelt. Bring Entropie in den Sortierschlüssel oder sharde den Partitionsschlüssel.
- Den leselastigen Pfad unnötig sharden. Wenn Reads dominieren und das Item klein ist, schlägt ein Cache oder ein GSI mit besser verteiltem Schlüssel oft die Scatter-Gather-Lesekosten des Shardings.
- Eine Hot Partition mit einem langsamen
Scanverwechseln. EinScanist langsam, weil er alles liest; eine Hot Partition drosselt, weil ein Schlüssel überlastet ist. Verschiedene Probleme — siehe Query vs. Scan.
Nächste Schritte
Skizzier die geshardeten Schlüssel und weise den Lesepfad dann an echten Daten nach. Bau die Bedingungen pro Shard im DynamoDB Expression Builder und lade DynoTable herunter, um sie gegen deine eigenen Tabellen laufen zu lassen und zu sehen, welche Partitionen die Hitze tatsächlich abbekommen.