Datenmodellierung ist ein Prozess, der Entitäten, Attribute und Beziehungen abbildet, bevor entschieden wird, wie eine Datenbank sie speichert. Die Entitäten sind der leichte Teil – jedes Produkt kennt seine Benutzer, Bestellungen und Beiträge. Das Handwerk steckt in den Beziehungen: welcher Datensatz auf welchen zeigt, wie viele, und wo diese Kante physisch liegt. Stimmen die Kanten, schreiben sich die Abfragen von selbst; stimmen sie nicht, kämpft jedes Feature gegen das Schema.
Das Wichtigste in Kürze
| Frage | Antwort |
|---|---|
| Die drei Ebenen | Konzeptionell (was) → logisch (Struktur) → physisch (Engine) |
| Die drei Kanten | Eins-zu-eins · Eins-zu-viele · Viele-zu-viele |
| Relationale Werkzeuge | Fremdschlüssel; Verknüpfungstabellen für Viele-zu-viele |
| Dokumentwerkzeuge | Einbetten, Pointers (Referenzen), Relations/ID-Arrays |
| Die moderne Regel | Für Zugriffsmuster modellieren – was zusammen gelesen wird, liegt zusammen |
Dieselben Beziehungen, beide Welten
Zuerst relational – der Fremdschlüssel trägt Eins-zu-viele, und Viele-zu-viele muss über eine Verknüpfung zerlegt werden:
-- 1:N — der Fremdschlüssel lebt auf der "viele"-Seite
CREATE TABLE books (
id bigint PRIMARY KEY,
title text NOT NULL,
author_id bigint NOT NULL REFERENCES authors(id) ON DELETE CASCADE
);
-- M:N — kein einzelner FK drückt das aus; eine Verknüpfungstabelle hält beide Schlüssel
CREATE TABLE book_genres (
book_id bigint REFERENCES books(id),
genre_id bigint REFERENCES genres(id),
added_at timestamptz DEFAULT now(), -- Verknüpfungen können Attribute tragen
PRIMARY KEY (book_id, genre_id) -- zusammengesetzter Schlüssel: eine Kante, einmal
);
Dokumentwelt, dasselbe Modell: Die Eins-zu-viele-Kante ist ein typisierter Pointer, die Viele-zu-viele-Kante eine Relation – keine Verknüpfungstabelle zu erfinden, und die Kante wird im Anwendungscode deklariert:
// JavaScript / Node.js — Back4app JS SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
const author = await new Parse.Query('Author').get(authorId);
const book = new Parse.Object('Book');
book.set('title', 'Dune');
book.set('author', author); // Pointer — typed one-to-many edge
await book.save();
const genres = book.relation('genres'); // Relation — many-to-many, unbounded
genres.add([sciFi, classics]);
await book.save(); // Flutter / Dart — Back4app Flutter SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
final book = ParseObject('Book')
..set('title', 'Dune')
..set('author', author.toPointer()); // Pointer — typed one-to-many edge
await book.save();
book.addRelation('genres', [sciFi, classics]); // Relation — many-to-many
await book.save(); // iOS / Swift — Back4app Swift SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
var book = Book()
book.title = "Dune"
book.author = try author.toPointer() // Pointer — typed one-to-many edge
let saved = try await book.save()
let relation = try saved.relation("genres")
try await relation.add([sciFi, classics]).save() // Relation — many-to-many // Android / Kotlin — Back4app Android SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
val book = ParseObject("Book").apply {
put("title", "Dune")
put("author", author) // Pointer — typed one-to-many edge
}
book.save()
val genres = book.getRelation<ParseObject>("genres") // Relation — many-to-many
genres.add(sciFi)
genres.add(classics)
book.save() Konzeptionell vs. logisch vs. physisch: die drei Ebenen
| Dimension | Konzeptionell | Logisch | Physisch |
|---|---|---|---|
| Beantwortete Frage | Was existiert, wie verbunden | Welche Felder, welche Schlüssel | Wie gespeichert, wie schnell |
| Zielgruppe | Alle | Entwerfende | Engineering + die Engine |
| Enthält | Entitäten, Beziehungen | + Attribute, Typen, Kardinalität | + Indizes, Constraints, Partitionen |
| Ändert sich, wenn | Das Geschäft sich ändert | Anforderungen sich schärfen | Engine oder Größenordnung sich ändert |
Die Disziplin, die diese Ebenen erzwingen: Streiten Sie nicht über Indizes, solange das Team noch uneins ist, was eine “Bestellung” überhaupt ist.
Jede Beziehung, jede Umsetzung
Die Tabelle, die in den Suchergebnissen nie gebaut wurde – jeder Kantentyp mit seiner Umsetzung in beiden Welten:
| Beziehung | Beispiel | Relationale Umsetzung | Dokument-Umsetzung |
|---|---|---|---|
| Eins-zu-eins | Benutzer ↔ Profil | FK mit UNIQUE, oder dieselbe Zeile | Einbetten – fast immer |
| Eins-zu-wenige | Person → Adressen | Kindtabelle + FK | Eingebettetes Array (begrenzt) |
| Eins-zu-viele | Autor → Bücher | FK auf der “viele”-Seite | Pointer auf der “viele”-Seite |
| Eins-zu-riesig | Gerät → Ereignisse | FK + Partitionierung | Pointer am Kind; niemals ein Array |
| Viele-zu-viele | Bücher ↔ Genres | Verknüpfungstabelle, zusammengesetzter PK | Relation oder Arrays von Pointers |
| Selbstbezüglich | Mitarbeiter → Vorgesetzte | FK auf die eigene Tabelle | Pointer auf die eigene Klasse |
Kardinalitätsnotation, zum Lesen von Diagrammen: Der Krähenfuß zeichnet einen Strich für “eins” und eine dreizinkige Gabel für “viele”; die ER-Tradition schreibt 1 und N an die Linien; UML schreibt Multiplizitäten wie 1 und *. Drei Dialekte, eine Grammatik.
Normalisieren, denormalisieren oder einbetten?
Relationale Modellierung beginnt bei der Normalisierung – Daten so aufteilen, dass jeder Fakt genau einmal existiert, was Schreibvorgänge vor Anomalien schützt. Analytische und dokumentorientierte Modellierung biegt das bewusst: Denormalisierung dupliziert lesestarke Felder, um Joins zu vermeiden, und Einbetten ist die dokumenteigene Verwandte der Denormalisierung. Die Checkliste Einbetten vs. Referenzieren verdichtet sich auf drei Fragen: Zusammen gelesen? Von einem Elternteil besessen? In der Größe begrenzt? Dreimal ja heißt einbetten; ein einziges Nein heißt referenzieren. Und über allem steht die moderne Regel, die allgemeine Ratgeber überspringen: Listen Sie zuerst die Abfragen auf. Ein Modell ist richtig, wenn die Zugriffsmuster, die es bedienen muss, billig sind – die Entitäten allein können Ihnen das nicht sagen.
Typische Anwendungsfälle
- Ein neues Backend entwerfen. Der klassische Durchgang: Entitäten benennen, Kanten zeichnen, Umsetzungen nach der Tabelle oben wählen – vor der ersten Zeile Code.
- Die Verknüpfung-mit-Attributen. Einschreibungen, Mitgliedschaften, Positionen – wenn die Kante selbst Daten trägt (Datum, Menge, Rolle), ist die Verknüpfung (oder eine Kantenklasse mit zwei Pointers) eine vollwertige Entität.
- Ein gewachsenes Schema entwirren. Symptome zeigen auf Kanten: duplizierte Zeilen verraten ein falsch modelliertes Viele-zu-viele; aufgeblähte Dokumente verraten ein unbegrenztes Einbetten.
- Zwischen den Welten migrieren. Relational→dokumentorientiert heißt, jeden FK neu zu entscheiden: einbetten oder Pointer; die Tabelle oben ist das Übersetzungswörterbuch.
- KI- und Analytik-Feeds. Data Warehouses wollen explizite, stabile Kanten – Modellierungsschulden tauchen an dem Tag auf, an dem Sie exportieren wollen.
Wie sollten Sie jede Kante modellieren? Eine Entscheidungsmatrix
| Wählen Sie… | Wenn… | Achten Sie auf… |
|---|---|---|
| Einbetten | Zusammen gelesen, besessen, begrenzt | Wachstum: die “wenigen” von heute sind die Tausenden von morgen |
| Pointer / FK | Unabhängiger Lebenszyklus, hohe Kardinalität | Indizieren Sie ihn – jedes Nachschlagen und jedes include zahlt |
| Relation / Verknüpfung | Viele-zu-viele, oder die Kante trägt Daten | Abfragerichtung: Wissen Sie, von welcher Seite Sie fragen |
| Duplizieren (denormalisieren) | Ein lesestarkes Feld über eine Kante hinweg | Update-Fan-out – Duplikation ist eine Schuld mit Zinsen |
Grenzen und Trade-offs
- Modelle frieren Annahmen ein. Kardinalitätsentscheidungen (“ein Benutzer hat eine Adresse”) werden zu Schema; auf dem Papier billig zu ändern, nach dem Start teuer – modellieren Sie für die Kardinalität von morgen.
- Beide Welten bestrafen die nicht indizierte Kante. FK-Spalten und Pointer-Felder sind Join-Pfade; ihre Indizes zu vergessen ist der häufigste stille Performance-Fehler.
- Einbetten tauscht Integrität gegen Lokalität. Keine Engine erzwingt, dass eine eingebettete Kopie mit ihrer Quelle konsistent bleibt – das ist jetzt Ihre Update-Logik.
- Verknüpfungen vervielfachen Joins; Relations verstecken sie. Jeder Viele-zu-viele-Lesevorgang überquert den Kantenspeicher – kalkulieren Sie den Abfragepfad ein, in welcher Welt Sie auch sind.
- Modellieren nach Zugriffsmustern kostet ebenfalls. Auf die Abfragen von heute zu optimieren kann das Schema an das Produkt von heute binden; behalten Sie das konzeptionelle Modell als neutrale Referenz.
Datenmodellierung mit Back4app
Back4app ist eine Open-Source-Plattform für Backend as a Service (BaaS), die eine verwaltete Datenbank, automatisch generierte REST- und GraphQL-APIs, Authentifizierung, Dateispeicher und Serverless-Funktionen mit Cloud Code kombiniert. Ihr Modellierungsvokabular ist die Dokumentspalte der Tabellen oben, zur ersten Klasse erhoben: Pointers sind typisierte Eins-zu-viele-Kanten, Relations tragen Viele-zu-viele ohne handgebaute Verknüpfungstabelle, und Arrays decken die begrenzten Wenigen ab. Jede Kante, die Sie deklarieren, ist sofort begehbar – include() folgt Pointers in einer Anfrage, GraphQL verschachtelt Relations in einer Abfrage – und das Schema bleibt im Dashboard sichtbar und bearbeitbar, sodass das physische Modell nie aus dem Blickfeld des Teams gerät, das das konzeptionelle entworfen hat.
Häufige Fragen
Was ist Datenmodellierung?
Der Prozess, die Information einer Anwendung – ihre Entitäten, deren Attribute und die Beziehungen dazwischen – in einen Entwurf zu übersetzen, den eine Datenbank speichern kann. Er durchläuft üblicherweise drei Detailstufen: ein konzeptionelles Modell, das die Entitäten benennt, ein logisches Modell, das Attribute und Schlüssel ergänzt, und ein physisches Modell, das sich auf Tabellen, Spalten und Indizes einer konkreten Engine festlegt.
Welche drei Arten von Datenmodellen gibt es?
Konzeptionell, logisch und physisch – derselbe Entwurf in wachsender Zoomstufe. Konzeptionell beantwortet "Was existiert und wie hängt es zusammen?" für die Fachseite. Logisch ergänzt Attribute, Typen und Schlüssel, bleibt aber technologieunabhängig. Physisch legt sich auf eine echte Engine fest: Tabellen oder Collections, Indizes, Constraints. Jede Ebene ist die vorherige plus Entscheidungen.
Was ist eine Eins-zu-viele-Beziehung?
Ein Elterndatensatz, der zu vielen Kindern in Beziehung steht, wobei jedes Kind zu genau einem Elternteil gehört – ein Kunde und seine Bestellungen, ein Autor und seine Bücher. Es ist die häufigste Beziehung in jedem Schema. Relationale Datenbanken setzen sie mit einem Fremdschlüssel auf der "viele"-Seite um; Dokumentdatenbanken nutzen ein eingebettetes Array für kleine, begrenzte Mengen oder einen Pointer auf das Elternobjekt für alles andere.
Was ist eine Viele-zu-viele-Beziehung und warum braucht sie eine Verknüpfungstabelle?
Beide Seiten stehen zu vielen Einträgen der anderen in Beziehung – Studierende und Kurse, Bücher und Genres. Eine einzelne Fremdschlüsselspalte kann nur auf eine Zeile zeigen, also zerlegen relationale Datenbanken Viele-zu-viele in zwei Eins-zu-viele-Beziehungen über eine Verknüpfungstabelle, die beide Schlüssel hält (und oft Attribute der Beziehung, etwa ein Einschreibedatum). Dokumentdatenbanken sparen sich die Verknüpfungstabelle: Arrays von Referenzen oder ein eigener Relation-Typ tragen die Kante direkt.
Woran erkenne ich, ob eine Beziehung Eins-zu-viele oder Viele-zu-viele ist?
Stellen Sie die Zugehörigkeitsfrage in beide Richtungen. "Kann ein Autor viele Bücher haben?" Ja. "Kann ein Buch viele Autoren haben?" Wenn nein – Eins-zu-viele, Fremdschlüssel am Buch. Wenn ja – Viele-zu-viele, Verknüpfungstabelle oder Relation. Hier falsch zu liegen ist der klassische Modellierungsfehler: Ein als Eins-zu-viele modelliertes Viele-zu-viele dupliziert entweder Zeilen oder verliert Kanten stillschweigend.
Was bedeutet Kardinalität in einem ER-Diagramm?
Wie viele Instanzen einer Entität mit Instanzen einer anderen in Beziehung stehen können – Eins-zu-eins, Eins-zu-viele, Viele-zu-viele. Diagramme drücken das in einer von drei Notationen aus: Zahlen und Buchstaben an den Verbindungslinien, Krähenfuß-Symbole (ein Strich für "eins", eine dreizinkige Gabel für "viele") oder Multiplizitätsbereiche wie 1 und Sternchen. Gleiche Semantik, unterschiedliche Zeichenkonventionen.
Wie modellieren Dokumentdatenbanken Beziehungen ohne Fremdschlüssel?
Mit drei Werkzeugen: Einbetten (die verwandten Daten im Elterndokument verschachteln – richtig, wenn sie zusammen gelesen werden, zu einem Elternteil gehören und in der Größe begrenzt sind), Pointers oder Referenzen (die ID des verwandten Dokuments in einem typisierten Feld ablegen – richtig für unabhängige Lebenszyklen und hohe Kardinalität) und Relation-Objekte oder ID-Arrays für Viele-zu-viele. Die Leitregel kippt von der Normalisierung zu den Zugriffsmustern: Was zusammen gelesen wird, sollte zusammen liegen.
Was sind die häufigsten Fehler bei der Datenmodellierung?
Eine stabile Top Five: Viele-zu-viele als Eins-zu-viele modellieren; Indizes auf Fremdschlüssel- und Pointer-Feldern vergessen (jeder Join und jedes Nachschlagen zahlt dafür); unbegrenzte eingebettete Arrays in Dokumentschemas; verfrühte Denormalisierung, bevor sich überhaupt eine Abfrage als langsam erwiesen hat; und aus den Entitäten allein heraus modellieren, ohne die Abfragen – die Zugriffsmuster – aufzulisten, die das Modell bedienen muss.