Single-Table-Design in DynamoDB
Aus SQL kommend ist der Instinkt eine Tabelle pro Entität: customers, orders,
order_items. In DynamoDB ist dieser Instinkt meist falsch. Eine einzelne Tabelle, die
jede Entität speichert, unterschieden durch überladene Key-Präfixe, lässt dich ein
Elternteil und seine Kinder in einem Query holen — keine Joins, kein N+1.
Was ist Single-Table-Design in DynamoDB?
Single-Table-Design speichert jede Entität — Kunden, Bestellungen, Bestellpositionen — in einer
DynamoDB-Tabelle, unterschieden durch überladene - und
Sort-Key-Präfixe. Weil die Keys um deine Zugriffsmuster herum entworfen sind
statt um deine Entitäten, leben ein Elternteil und all seine Kinder in einer
und kommen in einem einzigen Query zurück — keine Joins,
keine N+1-Reads.
Die Idee
Wähle generische Key-Namen (PK, SK) und kodiere den Entitätstyp im Wert:
| PK | SK | attributes |
|---|---|---|
| CUSTOMER#42 | PROFILE | name, email, plan |
| CUSTOMER#42 | ORDER#2026-001 | total, status |
| CUSTOMER#42 | ORDER#2026-002 | total, status |
Nun gibt ein Query PK = "CUSTOMER#42" das Profil und jede Bestellung in einem
abgerechneten Read zurück. SK begins_with "ORDER#" grenzt es auf nur die Bestellungen ein.
Visuell stapeln sich die überladenen Items unter einem als eine einzige :
Ein Read der Partition reicht den Kunden und jede Bestellung zusammen zurück.
Überladene GSIs
Derselbe Trick funktioniert auf Indizes. Setze einen generischen GSI1PK/GSI1SK auf
Items, und ein einzelner bedient mehrere Zugriffsmuster, je nachdem, was jedes Item
in diese Attribute schreibt:
| PK | SK | GSI1PK | GSI1SK |
|---|---|---|---|
| ORDER#001 | METADATA | STATUS#OPEN | 2026-01-04 |
| ORDER#002 | METADATA | STATUS#OPEN | 2026-01-05 |
Nun listet Query GSI1 WHERE GSI1PK = "STATUS#OPEN" offene Bestellungen nach Datum — ein
Muster, das die Basistabelle nicht beantworten kann. Eine andere Entität kann GSI1 mit
ihrer eigenen Bedeutung wiederverwenden (z. B. CATEGORY#books). Ein Index, viele Abfragen.
Many-to-many: die Adjazenzliste
Für Beziehungen (ein Benutzer in vielen Teams, ein Team mit vielen Benutzern) schreibe die
Kante zweimal mit vertauschten IDs: PK=USER#1, SK=TEAM#9 und PK=TEAM#9, SK=USER#1.
Eine Abfrage jeder Seite listet die andere — der DynamoDB-Ersatz für eine Join-Tabelle.
Wann nicht Single-Table
Es ist nicht umsonst. Eine überladene Tabelle ist schwerer zu durchdenken, schwerer weiter- zuentwickeln und analytik-feindlich. Wenn deine Zugriffsmuster wirklich unbekannt sind oder sich ständig ändern, oder die Daten überwiegend analytisch sind, können getrennte Tabellen (oder ein anderer Store) die vernünftigere Wahl sein. Single-Table gewinnt, wenn die Muster bekannt und hochvolumig sind.
Kosten der falschen Form
Als getrennte Tabellen zu modellieren erzwingt einen Scan oder clientseitigen Join, um
einen Kunden wieder zusammenzusetzen, und das ist die Scan-Falle.
Modelliere die Zugriffsmuster zuerst, entwirf dann Keys, um jedes zu einem Query zu machen.
(Für die spontane entitätsübergreifende Frage, für die du nie modelliert hast, führt
DynoTables SQL Workbench den JOIN client-seitig aus —
Exploration muss nicht auf ein Re-Modelling warten.)
Skizziere das Design selbst mit dem kostenlosen Single-Table-Design-Tool — es verwandelt deine Zugriffsmuster-Liste in einen PK/SK/GSI-Plan mit Beispiel-Items und Kosten-Hinweisen. Schätze, was diese Items pro Read kosten, mit dem Item-Größen- & Kapazitätsrechner und probiere DynoTable, um ein Single-Table-Schema zu durchsuchen und die überladenen Collections nebeneinander zu sehen.