Blog

Amazon DynamoDB - Entwurf einer einzelnen Tabelle

Marek Jędraszewski

Aktualisiert Oktober 20, 2025
14 Minuten

DynamoDB ist eine vollständig verwaltete NoSQL-Schlüsselwertdatenbank, die bei jeder Skalierung eine Leistung im einstelligen Bereich liefert. Um diese Leistung für nicht-triviale Anwendungsfälle mit großem Umfang und Datenverkehr zu erreichen, müssen Sie Ihre Daten jedoch sorgfältig modellieren. In dieser Hinsicht unterscheidet sich DynamoDB nicht von anderen NoSQL-Datenbanken, bei denen Sie in der Regel Ihr RDBMS-Training (z.B. Normalisierung) "vergessen" und anders vorgehen müssen. Eine Sache, die bei DynamoDB hervorsticht, ist die Konzentration auf so wenige Tabellen wie möglich. In den AWS DynamoDB Docs(hier) heißt es wiederholt

“In der Regel sollten Sie in einer DynamoDB-Anwendung so wenige Tabellen wie möglich verwalten.”

Um besser zu verstehen, warum das so ist (Beibehaltung weniger Tabellen, idealerweise nur eine) und warum dies von Vorteil sein könnte, lassen Sie uns kurz das DynamoDB-Datenmodell betrachten.

DynamoDB-Komponenten

Tabelle - DynamoDB leiht sich die Nomenklatur von RDBMS und speichert, ähnlich wie andere Datenbanksysteme, Daten in Tabellen. Abgesehen vom obligatorischen Primärschlüssel ist sie jedoch im Grunde schemalos und Sie können in ein und derselben Tabelle eine Sammlung heterogener Elemente speichern.

Element - ein Element ist eine identifizierbare Gruppe von Attributen (denken Sie an Zeilen oder Datensätze in anderen Datenbanksystemen).

Attribut - ein Attribut ist ein grundlegender, benannter Block von Daten. Daten können primitiv sein, z.B. eine Zahl oder eine Zeichenkette, oder ein komplexes Objekt, z.B. eine Karte oder eine Liste (denken Sie an Spalten oder Felder in anderen Datenbanksystemen).

Primärschlüssel

Das einzige obligatorische Attribut in einem Artikel ist ein Primärschlüssel, den es in zwei Varianten gibt

  • Partitionsschlüssel - ein einzelnes, einfaches Wertattribut.
  • Partitionsschlüssel + Sortierschlüssel - ein zusammengesetzter Primärschlüssel, der aus einem Partitionsschlüssel und einem zusätzlichen Sortierschlüssel besteht, der Elemente innerhalb der gegebenen Partition sortieren kann. Wie wir noch sehen werden, spielen Sortierschlüssel neben der offensichtlichen Sortierfunktion eine wichtige Rolle, um Ihre Datenabfragen flexibler zu gestalten.

Unabhängig davon, welches Primärschlüsselschema Sie verwenden, ist es sehr wichtig, einen guten Partitionsschlüssel zu wählen, d.h. die Werte sollten in Bezug auf die Anzahl der Zeilen eindeutig sein und idealerweise sollte der Zugriff gleichmäßig erfolgen. Sie sollten "heiße Partitionen" vermeiden, d.h. Partitionen, auf die übermäßig häufig zugegriffen wird. DynamoDB verwendet, wie der Name schon sagt, Partitionsschlüssel, um Ihre Daten physisch zu partitionieren, und um die beste Leistung zu erzielen, sollte die Arbeitslast auf alle bzw. die meisten Partitionen verteilt werden. Andernfalls könnte die Leistung darunter leiden.

Kurz gesagt spielen die Komponenten des Primärschlüssels die folgenden Rollen

  • Partitionsschlüssel - bestimmt die Datenaufteilung und ermöglicht einfache Schlüssel-Wert-Zugriffsmuster
  • Sortierschlüssel - ermöglicht die Sortierung. Er wird häufig bei der Modellierung von 1:N-Beziehungen und Hierarchien verwendet. Und er ermöglicht selektive Muster und Bereichsabfragen.

Neben der Basistabelle können Sie zusätzliche sekundäre Indizes einrichten, um die Abfrageleistung zu erhöhen. Sie haben zwei Möglichkeiten - einen lokalen sekundären Index (LSI) und einen globalen sekundären Index (GSI).


Zusammengefasst sieht die Tabellenstruktur von DynamoDB wie folgt aus (verschiedene Attributsprojektionstypen, d.h. alle, einschließlich, nur Schlüssel, für sekundäre Indizes, die nicht im Bild enthalten sind).


Modellierung einer DynamoDB-Datenbank

Bei der Modellierung einer DynamoDB-Datenbank können Sie einen der beiden folgenden Ansätze wählen. Ein Multi-Tabellen-Design, das der RDBMS-Modellierung ähnelt (nur mit mehr Einschränkungen), bei dem Entitäten in separaten Tabellen gespeichert werden, oder ein Einzeltabellen-Design, bei dem alle Entitäten in einer gemeinsamen Tabelle gespeichert werden.

Multi-Tisch-Design

Der einfachste Weg, Ihr DynamoDB-Datenmodell zu entwerfen, besteht darin, die in der RDBMS-Welt verwendeten Best Practices zu befolgen, d.h. Entität pro Tabelle und ein gewisses Maß an Normalisierung (die schemalose Natur von DynamoDB und die Unterstützung komplexer Attribute gibt Ihnen mehr Möglichkeiten, 1-to*-Beziehungen auszudrücken, denken Sie z.B. an Postgresql mit Json-Datentypen). Die unveränderte Übertragung eines RDBMS-Modells auf NoSQL würde ebenfalls zu vielen Tabellen führen. Nicht existierende Tabellen-Joins in DynamoDB müssten jedoch in mehrere Anfragen an die Datenbank übersetzt werden. Dieser Ansatz verursacht im großen Maßstab mehrere Kosten, d.h.

  • Betriebskosten - viele zu verwaltende und zu pflegende Tabellen (Metriken, Überwachung, Alarmierung)
  • Betriebskosten (Sie müssen für jede Tabelle mindestens 1 WCU und 1 RCU bereitstellen, selbst für einige wörterbuchartige, selten genutzte Tabellen). Sie können dies jedoch abmildern, indem Sie den On-Demand-Kapazitätsmodus verwenden, bei dem Sie WCUs und RCUs "nicht mehr sehen".
  • mehrere Netzwerkreisen/-anfragen zum Abrufen von verbundenen Einheiten

Die wichtigsten und größten Kosten, die Sie mit dem Multi-Tabellen-Design bezahlen, sind mehrere Netzwerkaufrufe, um verbundene Entitäten abzurufen. Dies kann sich natürlich auf die Leistung auswirken und kann oft nicht durch parallele Aufrufe gemildert werden. Mehrere serielle Anfragen lassen sich nicht skalieren, und wenn Sie skalieren, wird Ihre Anwendung langsamer. Lassen Sie uns sehen, wie Sie dies mit einem ganz anderen Ansatz beheben können - mit nur einer Tabelle.

Einzeltisch-Design

Der Hauptvorteil von Joins in relationalen Datenbanken ist die Möglichkeit, heterogene Elemente mit einer einzigen Anfrage abzurufen. Joins sind jedoch bekanntermaßen schwer zu skalieren und DynamoDB bietet absichtlich keine Möglichkeit, Tabellen zu verbinden. Um eine schnelle und konsistente Leistung zu erzielen, fordert DynamoDB die Entwickler stattdessen auf, die Daten einfach in Objektsammlungen zu verknüpfen, die Sie mit einer einzigen Anfrage abrufen können.

Eine Elementsammlung ist eine Gruppe von Elementen in einer Tabelle oder in einem Index, die denselben Partitionsschlüssel haben. Angesichts des flexiblen Datenmodells einer DynamoDB-Tabelle kann eine Elementsammlung aus mehreren heterogenen Elementen bestehen. Mit diesem einfachen Konzept sowie mit zusammengesetzten Schlüsseln und sekundären Indizes können Sie alle typischen Entitätsbeziehungen modellieren, d.h. one-to-one, one-to-many, many-to-one und many-to-many. Ein einfaches Beispiel soll dies verdeutlichen.

Ziel ist es, das Konzept vorzustellen und nicht auf einen bestimmten Anwendungsfall einzugehen, also konzentrieren wir uns auf ein einfaches IMDB-ähnliches Szenario. Wir haben Listen von Filmen und Schauspielern. Es handelt sich um eine Beziehung von vielen zu vielen: Filme besetzen viele Schauspieler, Schauspieler spielen in vielen Filmen mit. Wir beginnen zunächst mit einem standardmäßigen ER-Diagramm (Entity-Relationship), bevor wir es mit einem bestimmten Datenbankschema abgleichen. In unserem vereinfachten Beispiel haben wir nur zwei Entitäten: Schauspieler und Filme, und das ERD ist sehr einfach.


Das Design einer einzelnen Tabelle ist von Zugriffsmustern abhängig. Sobald Sie Entitäten und Beziehungen gefunden haben, müssen Sie über Zugriffsmuster nachdenken, welche Aggregationen es gibt, was Sie lesen oder schreiben und welche Anwendungsfälle Sie optimieren wollen (aber hüten Sie sich vor verfrühter Optimierung. Denken Sie auch daran, dass es manchmal einfacher ist, Dinge auf der Client-/Anwendungsseite zu aggregieren oder herauszufiltern, so dass es nicht immer der beste Ansatz ist, die Dinge in der Datenbank-Engine zu verkomplizieren - ein guter Kandidat für diese Methode ist, wenn das Filtern schwierig und der Datensatz klein ist).

Lassen Sie uns einige grundlegende, beliebige Zugriffsmuster auflisten, die wir gerne unterstützen würden

  • Film nach Film-ID abrufen
  • Liste der Besetzung eines Films
  • Filme von einem Schauspieler bekommen
  • Schauspieler nach Schauspieler-ID abrufen

Um die Sache noch ein wenig interessanter und komplizierter zu machen, nehmen wir an, dass wir auch die am häufigsten gestreamten Filme anzeigen möchten.

  • Liste der Top 10 der meistgestreamten Filme nach Monat
  • Gesamtanzahl der gestreamten Filme nach Film-ID und Monat ermitteln

Anhand der oben aufgeführten Zugriffsmuster können wir sehen, dass einige recht trivial sind, z.B. die Abfrage einer Entität anhand der ID-Anforderung ist ein Standard-Schlüsselwert-Zugriffsmuster, bei dem sich NoSQL-Datenbanken auszeichnen. Andere erfordern mehr Überlegung, z.B. die Auflistung der Besetzung eines Films ist eine Eins-zu-Viel-Beziehung und könnte leicht mit einem Partitionsschlüssel + Sortierschlüssel-Duo erledigt werden. Aber wie würden wir die Beziehung wieder in dieselbe Tabelle einfügen (Filme nach einem Schauspieler auflisten)?

Ein mögliches Design wird im Folgenden vorgestellt:


Das obige Design lässt sich wie folgt auf die Zugriffsmuster übertragen:


Um die Dinge relativ einfach und kurz zu halten, ist die Anzahl der Zugriffsmuster nicht sehr groß. In realen Anwendungen ist es nicht ungewöhnlich, Dutzende oder sogar ein paar Dutzend Zugriffsmuster nur mit der Basistabelle und ein paar sekundären Indizes zu verarbeiten. Aber auch bei diesem kleinen Design gibt es ein paar Dinge, die erwähnenswert sind.

Zuallererst verwenden wir bei der Abfrage nach der Besetzung eines Films nur den Partitionsschlüsselteil des Primärschlüssels. Auf diese Weise holen wir alle Daten zu einem bestimmten Film mit einer einzigen Anfrage an die Datenbank ab (Objektsammlung). So erhalten wir nicht nur die Schauspieler, sondern auch Filmdetails, Streaming-Gesamtzahlen pro Monat und einzelne Streams (natürlich könnten wir auch eine Bedingung für den Sortierschlüssel hinzufügen, z.B.begins_with(sk, ‘act#’), um nur Schauspieler zu erhalten).


Das Abrufen mehrerer, heterogener Elemente in einer einzigen Anfrage ist der wichtigste Vorteil des Single Table Design und der Hauptgrund, warum Sie es in leistungsrelevanten Anwendungsfällen einsetzen sollten! Im Gegensatz zu einer relationalen Datenbank mit vielen Entitäten und Verknüpfungen zwischen ihnen ermöglicht dieses Pre-Join-Zugriffsmuster einen Datenabruf in konstanter Zeit und in großem Umfang.

Zweitens sehen Sie, dass Attribute, die Primärschlüssel bezeichnen, sehr allgemeine Namen haben, z.B. pk, sk. Das ist nur eine Konvention, aber spezifische Attributnamen, z.B. MovieId,, wären nicht sehr sinnvoll. Schließlich speichern wir verschiedene Objekte in derselben Tabelle. Die Speicherung heterogener Elemente in einer Tabelle ist ein Beispiel für Partitionsüberladung (eine gängige Praxis ist die Erstellung eines Attributs, z.B. entityType, mit menschenlesbaren Werten wie movie, actor. Es erleichtert das Verständnis Ihrer PKs und SKs und kann auch bei der Implementierung verwendet werden, um diese Entitäten zu identifizieren und zu verarbeiten). In ähnlicher Weise können Sie Ihre sekundären Indizes mit dem Überladungsansatz entwerfen. Obwohl es derzeit nur einen Anwendungsfall für gsi2pk und gsi2sk gibt, wird es in Zukunft weniger verwirrend sein, wenn Sie diesen Index mit verschiedenen Elementen wiederverwenden und auf diese Weise die Vorteile der Indexüberladung nutzen können.

Sie können auch sehen, dass den Schlüsselwerten einige Konstanten vorangestellt sind, z.B. mov#, act# usw. So können Sie Entitätstypen unterscheiden und herausfiltern.

Hinweis: Eine weitere gängige Praxis ist die Verwendung hierarchischer Sortierschlüssel, z.B. können Sie mit dem folgenden Formular country#region#city#zipCode#street Entitäten auf jeder Ebene der Hierarchie abfragen.

Drittens haben wir einen umgekehrten sekundären Index, GSI-1, verwendet, um die Viele-zu-Viele-Beziehung zwischen Filmen und Schauspielern zu modellieren. Die eine Seite dieser Beziehung wird durch den Partitionsschlüssel und den Sortierschlüssel der Basistabelle hergestellt. Die Rückbeziehung verwendet die gleichen Attribute, nur in umgekehrter Reihenfolge.

Viertens: Der zweite sekundäre Index, GSI-2, ist ein Beispiel für einen Sparse-Index, d.h. einen Index, bei dem der Sortierschlüssel nicht in jedem Element vorkommt. Sparse-Indizes werden verwendet, um eine kleine Teilmenge der Haupttabelle abzufragen (in unserem Beispiel nur die Gesamtzahlen). Sie können diese Indizes mit einem geringeren Schreibdurchsatz als die Basistabelle versehen, ohne dass dies die Leistung beeinträchtigt.


Ein typischer Anwendungsfall für Sparse-Indizes ist die Auflistung nur einiger gekennzeichneter Entitäten, z.B. aller Entwürfe. In unserem Beispiel könnten wir unsere Anforderungen wie folgt erweitern

  • Liste oscarprämierter Schauspieler

Eine Möglichkeit wäre die Einführung eines dritten sekundären Indexes mit dem Partitionsschlüssel auf pk und dem Sortierschlüssel auf einem neuen Schauspielerattribut, z.B. oscar. Das Attribut oscar könnte einfach nur ein Boolescher Wert sein, aber wir könnten auch von den Sortierfunktionen des Sortierschlüssels profitieren und dort das Datum speichern, an dem der Schauspieler ausgezeichnet wurde, so dass die Liste nach dem Datum der Auszeichnung sortiert wäre.

Eine weitere interessante Tatsache über GSI-2 ist, dass sie Aggregationen enthält. DynamoDB bietet nicht viel, wenn es um Aggregationen geht. Wenn Sie Konstrukte wie group by oder ein einfaches count(*) erwarten, werden Sie mit leeren Händen dastehen. DynamoDB bietet jedoch eine sehr schöne Funktion, nämlich DynamoDB Streams. Wenn Sie diese Funktion aktivieren und eine Lambda-Funktion an den Stream anhängen, lösen Einfügungen, Aktualisierungen und Löschungen in der Tabelle die Lambda-Funktion aus, die ihrerseits neue Daten aggregieren, gruppieren oder berechnen und ein Element in die Tabelle einfügen oder aktualisieren kann.

Einzelne Tabelle Design - Rezept

Lassen Sie uns noch einmal die Schritte wiederholen, die Sie bei der Modellierung einer einzelnen Tabelle für Ihre Anwendung durchführen sollten (dies sollte Ihnen eigentlich ziemlich vertraut sein, wenn Sie mit NoSQL-Datenbanken gearbeitet haben)

  • den Anwendungsfall verstehen
  • Entitäten und Beziehungen finden (ERD)
  • Zugriffsmuster identifizieren
    • was sind Aggregationen
    • was Sie gerade lesen/schreiben
  • wenn der Index auf Tabellenebene nicht ausreicht, fügen Sie sekundäre Indizes hinzu (unterschiedliche Partitionierung/Sortierung = mehr Zugriffsmuster)

Profis

Die Notwendigkeit, die Komplexität und der ganze Aufwand, der für das Single Table Design erforderlich ist, haben einen Grund: die Verringerung der Anzahl der Anfragen für ein Zugriffsmuster, was sich in der Regel in einer besseren Leistung bei der Skalierung niederschlägt. Das ist das Hauptziel von Single Table Design (vor dem On-Demand-Kapazitätsmodus in DynamoDB konnten Sie mit nur einer einzigen Tabelle auch einige WCUs und RCUs, also Geld, sparen. Aber die Einsparungen wären marginal und der neue On-Demand-Kapazitätsmodus macht sie ohnehin zunichte).

Nachteile

Würden Sie Single Table Design überall und für jeden Anwendungsfall verwenden? Definitiv nicht. Single Table Design ist natürlich kein Allheilmittel. Sie tauschen unglaubliche Skalierbarkeit und Leistung gegen andere Eigenschaften ein, die für viele Anwendungsfälle wichtiger sein könnten.

Komplexität des Modells

Einer der impliziten Kosten, die Sie mit dem Entwurf einer einzigen Tabelle bezahlen, ist die Komplexität dieses Modells in allen nicht-trivialen Anwendungen. Auf den ersten Blick mag das widersprüchlich erscheinen. Müssen Sie sich nicht nur um eine Tabelle kümmern, statt um mehrere Tabellen? Nun, ja, es gibt nur eine Tabelle. Die Überladung von Indizes/Partitionen, heterogene Elemente, vorangestellte Schlüsselwerte und die Verbreitung von generischen Namen für Primärschlüssel (z.B. pk und sk) in der Basistabelle und sekundären Indizes (z.B. gs2pk, gs2sk usw.) verlangen von den Entwicklern jedoch eine enorme kognitive Belastung (und es wird noch schlimmer, wenn neue Indizes hinzugefügt werden). Sie tauschen die Lesbarkeit/Wartbarkeit des Codes gegen die Leistung.

Das resultierende Datenmodell lautet

  • informell (z.B. Beziehungen zwischen Entitäten auf der Grundlage von Namenskonventionen wie Präfixen)
  • schwer zu lesen und zu verstehen - Entwickler sind nicht in der Lage, die Bedeutung bestimmter Spalten einfach anhand des Namens zu erraten

Es erfordert

  • Pflege einer guten Dokumentation (generische Namen, hierarchische Schlüssel)
  • die Einführung einer Abstraktionsschicht - Sie möchten in der Regel datenbank-/indexbezogene Dinge wie die Verkettung von Präfixen oder das Mapping von Spaltennamen isolieren. Sie müssen eine solche Abstraktionsschicht selbst schreiben oder eine vorhandene verwenden (z.B. dynamodb-toolbox).

Unflexibles Datenmodell

Dieses Problem ist nicht spezifisch für DynamoDB oder das Design einer einzelnen Tabelle. Es handelt sich um ein allgemeineres Problem, wenn Sie in der NoSQL-Welt den Ansatz "Access Patterns First" verfolgen. Anwendungsfälle und Anforderungen ändern sich und es ist sehr wahrscheinlich, dass Ihr sorgfältig ausgearbeitetes Modell nicht mehr passt, wenn neue Anforderungen hinzukommen. Das soll nicht heißen, dass das Single Table Design statisch ist - es entwickelt und verändert sich mit der Anwendung, wie jedes andere Modell auch. Manchmal kann es erforderlich sein, Daten zu migrieren oder einen weiteren sekundären Index einzuführen. Das ist machbar, aber bei einer einzelnen Tabelle ist es schwieriger, neue Zugriffsmuster zu berücksichtigen.

Daten exportieren

Eine allgemeine Empfehlung für komplexe Aggregationen ist die Verwendung von DynamoDB Streams und einer Lambda-Funktion. Diese Lambda-Funktion könnte die Tabelle in DynamoDB zurückschreiben oder aktualisieren oder die Daten an einen anderen Speicher, z.B. Data Lake, für erweiterte Analysen senden. Das Design einer einzelnen Tabelle macht es etwas komplizierter, einige gängige Anwendungsfälle wie Change Data Capture (CDC) oder Datenexport für Analysen zu implementieren. Es gibt zwar einige gebrauchsfertige Tools und Bibliotheken für diese Zwecke, aber diese erwarten in der Regel den Empfang einer Sammlung homogener Entitäten. Bei einer einzelnen Tabelle müssen Sie die Datensätze in der Regel filtern und entpacken und dabei die Attribute umbenennen.

Wann Sie das Single Table Design nicht verwenden sollten

Es gibt einige Fälle, in denen Sie definitiv nicht mit dem Einzeltischdesign beginnen sollten.

  • Projekt auf der grünen Wiese - Als Faustregel gilt, dass jedes Projekt auf der grünen Wiese kein guter Kandidat für ein solches Design ist. Wenn Sie ein brandneues Projekt beginnen, verstehen Sie in der Regel weder die Domäne noch die Zugriffsmuster vollständig (beides sind Voraussetzungen für die Entwicklung eines Einzeltabellenmodells). Noch wichtiger ist, dass Flexibilität und schnelle Iterationen wichtiger sind als Leistungsüberlegungen
  • Zeitreihendaten - aufgrund der Natur von Zeitreihen (Sie sind in der Regel hauptsächlich an der letzten Periode interessiert) können Sie diese oft am besten handhaben, indem Sie eine Tabelle pro Anwendung und Periode verwenden(hier).

DynamoDB - Zusammenfassung

Single Table Design ist ein interessanter Ansatz. Er eignet sich besonders für große, leistungsintensive Anwendungen. Sie sollten aber auch bedenken, dass der Leistungsgewinn nicht zum Nulltarif zu haben ist. Verbesserungen bei bestimmten Zugriffsmustern könnten sich nachteilig auf andere Anwendungsfälle auswirken und die Komplexität der Anwendung und die Wartungskosten erhöhen. Sie müssen sich auch nicht zu 100% auf diesen Ansatz einlassen. Das Design einer einzelnen Tabelle und das Design mehrerer Tabellen schließen sich nicht gegenseitig aus. Sie können z.B. mehrere Tabellen haben und die Techniken des Einzeltabellendesigns nur in leistungsrelevanten Teilen der Anwendung anwenden.

Verfasst von

Marek Jędraszewski

Contact

Let’s discuss how we can support your journey.