Wann du KEIN Single-Table-Design in DynamoDB verwenden solltest
Single-Table-Design ist der Standardratschlag für DynamoDB, und es verdient ihn:
Ein Query gibt einen Elternteil und seine Kinder zurück, keine Joins, kein N+1.
Aber es ist ein Tausch — du erkaufst Lesegeschwindigkeit mit einem starren, undurchsichtigen Schema. Manche Workloads können sich diesen Preis nicht leisten, und ihnen eine Tabelle aufzuzwingen ist sein eigener Footgun.
Wann solltest du kein Single-Table-Design in DynamoDB verwenden?
Vermeide Single-Table-Design, wenn dein Workload heavy OLAP-Analytics, einfaches CRUD über eine Handvoll unabhängiger Entitäten oder Entitäten umfasst, die unabhängig skalieren und ausfallen. In diesen Fällen sind mehrere Tabellen lesbarer, kosten dasselbe und bleiben flexibel. Single-Table-Design gewinnt nur, wenn Zugriffsmuster bekannt, verwandt und hochvolumig sind.
- Heavy Analytics? Kein Single-Table. Überladene Keys sind OLAP-feindlich — exportiere in einen Columnar Store und frage dort ab.
- Einfaches CRUD mit einer Handvoll Zugriffsmuster? Eine Tabelle pro Entität ist in Ordnung, lesbar und kostet dich nichts an Performance.
- Entitäten, die unabhängig skalieren oder ausfallen? Getrennte Tabellen lassen dich sie eigenständig tunen, abrechnen und im Blast-Radius eingrenzen.
- Single-Table gewinnt trotzdem, wenn deine Muster bekannt, verwandt und hochvolumig sind — das ist der Fall, für den es gebaut wurde.
Wisse, was Single-Table tatsächlich kostet
Single-Table-Design ist nicht kostenlos; es verschiebt die Kosten nur vom Lesepfad weg auf alles andere. Du zahlst in Lesbarkeit und Flexibilität.
Eine Tabelle, die fünf Entitätstypen hinter PK/SK hält, ist schwer zu lesen,
schwer einzuarbeiten und schwer zu ändern. Ein neues Zugriffsmuster kann einen
Backfill über jeden Item-Typ in der Partition bedeuten.
Die Frage ist also nicht „ist Single-Table gut?" Sie ist „rechtfertigen meine Zugriffsmuster die Starrheit?" Wenn nicht, greife zu mehreren Tabellen.
Mach kein Single-Table bei einem Analytics-Workload
DynamoDB ist für OLTP gebaut — kleine, bekannte Point-and-Range-Lesevorgänge.
Analytics ist OLAP: GROUP BY, große Aggregate, Ad-hoc-Slicing über den ganzen
Datensatz. Die zwei ziehen in entgegengesetzte Richtungen.
Single-Table-Design macht OLAP schlechter, nicht besser. Überladene Keys und gemischte Entitätstypen bedeuten, dass ein Analytics-Job zuerst entwirren muss, welches Item welches ist, bevor er irgendetwas summieren kann — das Gegenteil eines sauberen Columnar Scan.
Aus SQL kommend ist der Reflex, das Aggregat gegen die Live-Tabelle zu schreiben. In
DynamoDB ist das ein vollständiger Scan — du zahlst für und liest jedes Item, was
der Scan-Footgun in voller Lautstärke ist.
Die Lösung ist kein cleverer Key. Es ist ein anderer Store. AWS' eigene Empfehlung ist, DynamoDB nach S3 zu exportieren und Analytics mit einer Query-Engine wie Athena auszuführen.
Halte OLTP und OLAP auf getrennten Engines (AWS DynamoDB Developer Guide,
S3DataExport.html).
Mach kein Single-Table bei einfachem CRUD
Wenn deine App ein paar unverwandte Entitäten nach ihrer eigenen ID liest und schreibt, und du vielleicht drei Zugriffsmuster hast, bringt Single-Table dir nichts.
Nimm eine Tenants-Tabelle und eine ApiKeys-Tabelle für ein kleines B2B-Tool:
| TenantId | Name | PlanTier |
|---|---|---|
| TNT-8842 | Northwind | pro |
| KeyId | TenantId | Scope |
|---|---|---|
| KEY-01H9... | TNT-8842 | read-write |
Jede Abfrage ist ein GetItem per ID oder ein Query auf einem GSI, der nach
TenantId verschlüsselt ist. Es gibt kein Eltern-und-Kinder-Fetch zu optimieren,
also gibt es nichts, das eine überladene Partition gewinnen könnte. Zwei klare
Tabellen lesen sich besser als eine trübe.
Die Falle ist, Single-Table zu cargo-culten, weil es „Best Practice" ist. Best Practice ist zugriffsmuster-zuerst. Wenn die Muster trivial sind, ist die einfache Form die richtige Form.
Teile Tabellen, die unabhängig skalieren oder ausfallen
Eine einzelne Tabelle teilt eine Durchsatzfläche, ein Backup, einen Blast-Radius. Wenn zwei Entitäten wild unterschiedliche Schreibraten oder Haltbarkeitsbedürfnisse haben, wird dieses geteilte Schicksal zur Belastung.
Stell dir ein Flotten-Tracking-System vor. Fahrzeuge ändern sich selten; ihre Telemetrie strömt jede Sekunde herein:
| VehicleId | Make | Model | Region |
|---|---|---|---|
| VEH-204 | Volvo | FH16 | eu-west |
| DeviceTs | VehicleId | SpeedKph | Fuel |
|---|---|---|---|
| 2026-06-23T10:00:01Z | VEH-204 | 88 | 0.61 |
Zwei Tabellen lassen dich Telemetrie für eine Feuerwehrschlauch-Last provisionieren, Fahrzeuge winzig und günstig halten, eine TTL allein auf Telemetrie setzen und einen Telemetrie-Schreibsturm davon abhalten, Lesevorgänge des Fahrzeugkatalogs zu throtteln. Eine Tabelle koppelt all das.
Gemäß dem Amazon-Dynamo-Paper von 2007 sind Partitionierung und Verfügbarkeit erstklassige Anliegen — unabhängige Tabellen geben dir unabhängige Kontrolle über beides.
Kartiere die Entscheidung, bevor du dich festlegst
Führe den Workload durch ein Gate: Sind die Entitäten verwandt, und sind die Muster bekannt und hochvolumig? Wenn nicht, mehrere Tabellen.
Hier ist die Entscheidung als Flow — starte oben und folge dem ersten Zweig, der passt:
Nur das Blatt unten rechts verdient Single-Table; jeder andere Pfad wird besser von mehr als einer Tabelle bedient.
Single vs. mehrere, direkt gegenübergestellt
| Faktor | Single-Table | Mehrere Tabellen |
|---|---|---|
| Verwandte Lesevorgänge | Ein Query, keine Joins | Clientseitiger Join oder extra Round-Trips |
| Lesbarkeit | Undurchsichtige überladene Keys | Eine Entität pro Tabelle, selbstdokumentierend |
| Neues Zugriffsmuster | Oft ein Backfill | Eine Tabelle oder einen GSI isoliert hinzufügen |
| Analytics / OLAP | Feindlich — entwirren vor dem Aggregieren | Trotzdem exportieren, aber sauberer pro Entität |
| Unabhängige Skalierung | Geteilter Durchsatz + Blast-Radius | Getrennt tunen, abrechnen, TTL und backuppen |
| Am besten wenn | Bekannte, verwandte, hochvolumige Muster | Unverwandt, sich entwickelnd oder analytisch |
Fallstricke + nächste Schritte
Der spiegelbildliche Fehler ist Überkorrektur — genuin verwandte, hochvolumige Entitäten in eine Tabelle-pro-Entität zu zersplittern und SQL-artige Joins in deiner App nachzubauen. Das ist die N+1-Falle, die Single-Table killt.
Wähle die Form, nach der die Zugriffsmuster fragen, nicht das Dogma.
Wenn du Beziehungen modellierst, stütze dich auf den richtigen Index-Typ — siehe GSI vs. LSI, bevor du einen hinzufügst.
Wenn du eine Abfrage gegen ein Multi-Table-Schema schreibst, skizziere die
KeyConditionExpression zuerst im
DynamoDB Expression Builder.
So erwischst du eine Full-Scan-Form, bevor sie die Produktion trifft.
Dann probiere DynoTable aus, um beide Formen gegen deine eigenen Tabellen zu durchsuchen und zu sehen, welche deine Zugriffsmuster tatsächlich wollen.