Datenbanken für Einsteiger: Tabellen, Indizes und Migrationen
Wo die Daten deiner Seite wohnen - und wie du sie nicht aus Versehen mit einem Befehl plattmachst
Was eine Datenbank in einfachen Worten ist: Tabellen, Indizes, Migrationen und Spaltentypen. Wir nehmen die größten Stolperfallen für Vibecoder auseinander - und wie du sie vorab umgehst.
Was eine Datenbank in einfachen Worten ist
Stell dir einen riesigen Karteischrank aus einer alten Bibliothek vor. Drinnen - Schubladen (das sind die Tabellen). In jeder Schublade liegen Karten (das sind die Zeilen). Und auf jeder Karte sind dieselben Felder ausgefüllt: Name, Datum, Telefon (das sind die Spalten). Mehr nicht. Keine Magie.
Genau dieser schlaue Schrank ist die Datenbank Datenbank - der Ort, an dem die App alles Wertvolle speichert: Nutzer, Bestellungen, Posts. Verschwindet nicht nach einem Neustart, anders als das, was im Arbeitsspeicher des Programms hängt. . Alles, was deine App für immer behalten soll - wer sich registriert hat, was bestellt wurde, welcher Post geliked wurde - lebt genau hier. Seite zu, Server aus, über das Kabel gestolpert und dem halben Viertel den Strom gekappt - die Daten sind noch da.
Und die App redet mit dem Schrank nicht menschlich, sondern in einer eigenen Sprache - SQL. Das ist wie ein Zettel an die Bibliothekarin: „bring mir alle Karten, wo Stadt = Berlin“. SQL auswendig pauken musst du als Vibecoder nicht - das schreibt der Agent oder eine schlaue Zwischenschicht. Aber zu verstehen, was genau der Agent vom Schrank verlangt, ist brutal nützlich. Sonst sagt er irgendwann „trag einfach alles raus“ und du zuckst nicht mal mit der Wimper.
Warum ein Vibecoder die Datenbank verstehen sollte
Früher oder später hört deine Seite auf, nur ein hübsches Bild zu sein, und will sich etwas merken: eine Bestellliste, Accounts, Kommentare. Genau hier kommt die Datenbank ins Spiel. Und mit ihr ein ganzer Zoo an Fehlern, die deine Seite entweder langsam machen oder still Daten verlieren lassen. Still - das ist das Allerfieseste.
Verstehst du, wie der Schrank funktioniert, gewinnst du sofort vier Dinge:
- du gerätst nicht in Panik, wenn der Agent mit Wörtern wie „Migration“ und „Index“ um sich wirft;
- du lässt den Agenten nicht aus Unwissenheit die ganze Tabelle löschen mit einem einzigen Befehl;
- du bekommst eine schnelle Seite, und nicht eine, bei der die Liste 10 Sekunden lädt und der Nutzer derweil zur Konkurrenz abhaut;
- du stellst die Aufgabe so, dass der Agent es beim ersten Mal richtig macht.
Der ganze Unterschied zwischen „meine Seite verliert manchmal Bestellungen und lahmt“ und „alles fliegt und nichts geht verloren“ läuft auf drei Wörter hinaus: Spaltentyp, Index, Migration. Los geht’s.
Wie der Agent mit der Datenbank arbeitet: vier Säulen
1. Tabellen und Spaltentypen: die Form der Karte
Legst du eine Schublade (Tabelle) an - sag sofort für jedes Feld, was drinliegt: Text, Zahl, Datum, „ja/nein“. Das ist der Spaltentyp. Vergreifst du dich beim Typ, wird das spätere Umbauen lang und schmerzhaft.
Die Erfahrenen haben fertige Regeln, was womit gespeichert wird (das kommt direkt aus dem Skill postgres-patterns):
- Geld - als Typ numeric (exakte Zahl), damit aus 0.1 + 0.2 nicht 0.30000004 wird.
- Datum und Uhrzeit - timestamptz (mit Zeitzone), damit ein Kunde auf Bali und einer in Berlin die korrekte Zeit sehen.
- Text - einfach text, ohne künstliche Längenlimits.
- Häkchen ja/nein - boolean, und nicht der String „yes“/„no“.
- Geld über float - die Cent-Bruchteile verschwinden im Nebel, die Buchhaltung weint.
- Datum als normaler Text - danach kannst du weder sortieren noch vergleichen.
- „Ja/nein“ als Ziffer 1 und 0 oder als String - jedes Mal rätselst du, was das überhaupt heißen soll.
- Preis als String „1000 Euro“ - na, addier das mal mit „990 Euro“.
2. Was ein Index in der Datenbank ist
Stell dir ein Telefonbuch vor, in dem die Namen kreuz und quer stehen. Um „Petersen“ zu finden, liest du es komplett von der ersten Seite an. Tausend Seiten - tausend Seiten Lesen für einen einzigen Namen. Genau so arbeitet eine Datenbank ohne Index. Langsam und ärgerlich.
Index Index - ein internes Inhaltsverzeichnis für eine Spalte. Die DB baut es vorab und findet danach die passende Zeile sofort, ohne die ganze Tabelle von vorne durchzulesen. - das ist genau dieses alphabetische Register. Du sagst dem Schrank: „häng ein separates Inhaltsverzeichnis fürs Feld email an“ - und die Suche nach email wird blitzschnell. Ohne „lies eine Million Karten und schwitz dich nass“.
3. Was eine Datenbank-Migration ist
Die Seite wächst, und auf der Karte muss ein neues Feld dazu - sagen wir „Telefon“. Im laufenden Schrank mit den Händen herumzufummeln ist riskant: irgendwas erwischst du garantiert. Deshalb werden Struktur-Änderungen über Migrationen Migration - eine schrittweise Änderung der DB-Struktur nach gespeichertem Bauplan: Spalte hinzufügen, Tabelle anlegen, Index setzen. Liegt in Dateien, damit derselbe Umbau auf jedem Server wiederholbar ist. gemacht - in Schritten aufgeschriebene „Umbau-Baupläne“.
Und genau hier wohnt die GEFÄHRLICHSTE Stolperfalle des Vibecoders. Der Befehl, mit dem der Agent diese Baupläne normalerweise schiebt, heißt migrate dev. Unter bestimmten Bedingungen fragt er nach Erlaubnis, die ganze DB zu löschen: wenn die Daten „nicht zum Bauplan passen“, setzt er ganze Tabellen auf null (das kommt direkt aus dem Skill prisma-patterns). Ein Klick auf „ja“ - und tschüss.
4. Gefährliche Befehle: deleteMany und updateMany
Es gibt Befehle, die viele Karten auf einmal ändern oder löschen. Mächtig - und gerade deshalb heimtückisch. Die zwei Hauptfallen (beide aus prisma-patterns):
deleteManyohne Bedingung löscht ALLES. Du wolltest die Bestellungen eines Kunden löschen, hast aber vergessen, „welche genau“ dazuzuschreiben - und der Schrank trägt schweigend die ganze Schublade raus. Ohne Nachfrage. Ohne „sind Sie sich sicher?“. Ohne Papierkorb.updateManygibt eine Zahl zurück, keine Datensätze. Du änderst massenhaft etwas und denkst, du bekommst die aktualisierten Karten zurück. Bekommst aber die nüchterne Zahl „geändert: 5 Stück“. Wer diese fünf sind - das ermittelst du mit einer separaten Abfrage.
Beispiel aus dem echten Leben: wie ein Onlineshop kaputtgeht
Du baust mit dem Agenten einen kleinen Onlineshop. Anfangs alles wunderbar: fünf Produkte, drei Bestellungen, fliegt wie eine Rakete. Einen Monat später hast du tausend Bestellungen - und jetzt die Quittung:
- Die Seite „meine Bestellungen“ lädt 8 Sekunden - weil es keinen Index auf dem Feld „Käufer“ gibt und die DB jedes Mal die ganze Tabelle durchliest.
- Im Bericht steht die Bestellsumme „1499.9999998“ - weil der Preis als float gespeichert wurde und nicht als
numeric. - Du hast den Agenten gebeten „lösch die Testbestellungen“, er hat
deleteManyohne Bedingung gestartet - und alle Bestellungen abgeräumt, inklusive der echten.
Keine dieser Katastrophen ist ein „KI-Glitch“. Es sind drei nachvollziehbare Stolperfallen, und alle drei verschwinden mit einer einzigen sauberen Aufgabenstellung:
Entwirf eine Datenbank für einen Onlineshop. Halte dich an die Regeln:
- Speichere den Preis als exakte Geld-Zahl (numeric), NICHT als float.
Datum und Uhrzeit - mit Zeitzone.
- Setz einen Index auf jedes Feld, nach dem wir suchen oder
sortieren: Käufer, Erstellungsdatum, Bestellstatus.
- Jeden Massen-Befehl zum Löschen oder Aktualisieren mach NUR
mit einer Bedingung, über welche Datensätze wir arbeiten. Ohne Bedingung - Stopp.
- Den Befehl migrate dev nutz nur lokal. Für den Live-Server
bereite migrate deploy vor. Bevor du irgendwas löschst, zeig mir erst den Plan.
- Erklär in einfachen Worten, welche Tabellen du angelegt hast und wozu jede dient.
Speed-Trick: Cursor-Pagination
Wenn die Liste lang ist (Post-Feed, Bestellungen, Produkte), bitten Einsteiger „gib mir Seite 50“. Um sie auszuliefern, muss die DB die ersten 49 Seiten abzählen und durchblättern - umsonst. Je weiter hinten die Seite, desto mehr ächzt sie.
Die Erfahrenen machen Cursor-Pagination Cursor-Pagination - Blättern nach dem Prinzip „gib mir die nächsten 20 nach diesem Datensatz“, statt „gib mir Seite Nummer 50“. Die DB blättert nicht alles von vorne durch und ist auf jeder Tiefe gleich schnell. : „gib 20 Stück nach dem zuletzt gezeigten“. Die Geschwindigkeit ist gleich - egal ob auf der ersten oder der tausendsten Seite. Der Agent hat es von selbst nicht vorgeschlagen? Frag einfach: „mach das Blättern im Feed per Cursor, nicht über Seitennummern“.
Häufige Einsteigerfehler bei Datenbanken
- Du speicherst Geld über float. Du bekommst Cent-Bruchteile und schiefe Summen. Nur
numeric. - Du hast Indizes vergessen. Bei kleinen Daten unsichtbar, bei großen bleibt die Seite stehen wie ein Klotz. Indexier die Such- und Sortierfelder.
- Du hast
migrate devauf der Live-Seite gestartet. Kann die ganze DB löschen. Auf Prod - nurmigrate deploy. - Du löschst oder änderst massenhaft ohne Bedingung.
deleteManyohne Bedingung killt die ganze Tabelle. Gib immer „über wen“ an. - Du denkst,
updateManygibt die Datensätze zurück. Es gibt nur eine Zahl zurück. Die aktualisierten Karten selbst holst du mit einer separaten Abfrage. - Du machst kein Backup vor einer gefährlichen Operation. Eine Sicherungskopie ist deine Zeitmaschine. Rettet einmal das ganze Projekt.
TL;DR - если коротко
- Datenbank - ein schlauer Schrank mit Karteikasten. Tabellen sind Schubladen, Zeilen sind Karten, Spalten sind Felder.
- Index - das Inhaltsverzeichnis. Fehlt er, liest die DB die ganze Schublade für eine einzige Karte und wird brutal langsam.
- Migration - Schrankumbau nach Bauplan. `migrate dev` kann alles löschen - die gehört auf deinen Rechner, nicht auf Prod.
- `deleteMany` ohne Bedingung killt die ganze Tabelle. `updateMany` gibt eine Zahl zurück, nicht die Datensätze. Merk dir beides.
- Geld nur als exaktes `numeric`. Sonst landet eines Tages „99.99999999 Euro“ im Warenkorb.
- Sag dem Agenten nicht „bau die DB irgendwie“. Gib Typen, Indizes und Löschregeln vorher vor.