Ein Datenbank-Index ist eine zusätzliche Datenstruktur, die die Zeilen einer Tabelle nach einer bestimmten Spalte oder Spaltengruppe sortiert hält — ähnlich dem Stichwortverzeichnis am Ende eines Buches lässt er dich direkt zum gesuchten Wert springen, statt jede Seite durchzublättern. Wenn deine Anwendung wächst, lautet die Antwort auf "warum wurde diese Abfrage langsam?" sehr oft: ein fehlender oder schlecht entworfener Index. In diesem Artikel erkläre ich, wie Indexe Abfragen beschleunigen, was sie kosten und wann man sie wirklich einsetzen sollte — mit konkreten Beispielen.
Ohne Index: der vollständige Tabellenscan
Wenn du auf einer Spalte ohne Index suchst, ist die Datenbank gezwungen, einen vollständigen Tabellenscan (full table scan) durchzuführen: Sie liest jede Zeile von Anfang bis Ende und behält die passenden. Bei einer Tabelle mit 1.000 Zeilen merkst du das nie, aber bei 5 Millionen Zeilen bedeutet jede Abfrage, Millionen Zeilen von der Festplatte zu lesen.
SELECT * FROM users WHERE email = 'aslain@example.com';
Gibt es keinen Index auf email, durchläuft die Engine die gesamte Tabelle, nur um eine einzige Zeile zu finden. Die Komplexität ist etwa O(n): Die Zeit wächst linear mit der Zeilenzahl. Mit einem Index sinkt die Suche auf O(log n) — ein riesiger Unterschied bei Millionen Zeilen.
Wie ein Index wirklich funktioniert: der B-Tree
Der klassische Index in relationalen Datenbanken ist ein B-Tree (genauer ein B+Tree). Werte werden in sortierter Reihenfolge in Zweigen abgelegt; jede Suche steigt von der Wurzel zu den Blättern ab und eliminiert bei jedem Schritt mehr als die Hälfte der verbleibenden Kandidaten. Deshalb erreichst du deinen Zielwert in nur wenigen Schritten, selbst unter Millionen Datensätzen.
- Gleichheitssuchen (
=) und Bereichssuchen (<,>,BETWEEN) sind auf einem B-Tree schnell. - Sortieren (
ORDER BY) und Gruppieren können fast kostenlos sein, weil der Index bereits sortiert ist. - Präfixsuchen wie
LIKE 'aslain%'profitieren vom Index, aberLIKE '%aslain'(führender Platzhalter) nicht.
Für die Suche innerhalb von Text (Volltext) oder für geografische Abfragen werden andere Indextypen als ein einfacher B-Tree verwendet — zum Beispiel FULLTEXT-Indexe für Text.
Einen Index anlegen und seine Wirkung messen
Einen Index auf einer einzelnen Spalte anzulegen ist einfach:
CREATE INDEX idx_users_email ON users (email);
Rate nicht, ob er tatsächlich wirkt — miss es. In MySQL und PostgreSQL zeigt der Befehl EXPLAIN den Abfrageplan:
EXPLAIN SELECT * FROM users WHERE email = 'aslain@example.com';
In der MySQL-Ausgabe bedeutet ein type von ALL einen vollständigen Scan (schlecht); ref oder const bedeutet, dass ein Index genutzt wird (gut). Der Wert rows schätzt, wie viele Zeilen die Engine zu scannen erwartet; mit dem richtigen Index sinkt diese Zahl drastisch.
Zusammengesetzte Indexe und die "ganz linke" Regel
Wenn du mehrere Spalten gemeinsam abfragst, verwende einen zusammengesetzten (composite) Index. Die Spaltenreihenfolge ist entscheidend, weil der B-Tree die Werte in der von dir angegebenen Reihenfolge sortiert:
CREATE INDEX idx_orders_user_status
ON orders (user_id, status);
Dieser Index beschleunigt WHERE user_id = 5 und WHERE user_id = 5 AND status = 'paid'. Aber er beschleunigt WHERE status = 'paid' allein nicht — das ist die Regel des ganz linken Präfixes (leftmost prefix). Stell dir ein Telefonbuch vor, sortiert nach Nachname und dann Vorname: Nur den Vornamen zu kennen erlaubt keine schnelle Suche.
Tipp: Setze die selektivste, mit Gleichheit abgefragte Spalte nach links und die Bereichsbedingungen nach rechts.
Die Kosten: Indexe sind nicht kostenlos
Ein Index ist kein Zauberknopf, der jedes Problem löst; er hat reale Kosten:
- Schreibvorgänge werden langsamer: Jedes
INSERT,UPDATEundDELETEmuss auch die betroffenen Indexe aktualisieren. Hat eine Tabelle 10 Indexe, bedeutet jedes Einfügen 10 zusätzliche zu pflegende Strukturen. - Sie verbrauchen Festplatte und Speicher: Indexe belegen eigenen Platz; viele unnötige Indexe blähen die Datenbank auf und verschmutzen den Cache.
- Bei geringer Selektivität helfen sie nicht: Auf einer Spalte mit nur zwei Werten (z. B.
is_active) bringt ein Index meist keinen Vorteil; die Engine wählt ohnehin einen vollständigen Scan.
Die Regel ist also einfach: Sind Lesezugriffe häufig und die Bedingung selektiv, indexiere; füge nicht blind jeder Spalte einen Index hinzu.
Praktische Empfehlungen
- Primärschlüssel (
PRIMARY KEY) und Unique-Constraints sind bereits indexiert; reindexiere sie nicht. - Indexiere die Fremdschlüsselspalten, die oft in
JOIN- undWHERE-Bedingungen genutzt werden. - Ziehe Spalten, nach denen du ständig mit
ORDER BYsortierst, als Indexkandidaten in Betracht. - Aktiviere das Slow Query Log, um langsame Abfragen zu finden, und prüfe danach mit
EXPLAIN. - Identifiziere ungenutzte Indexe und entferne sie; Wartung ist ebenfalls Teil der Optimierung.
Häufige Fragen
Ist es eine gute Idee, jeder Spalte einen Index hinzuzufügen?
Nein. Unnötige Indexe verlangsamen Schreibvorgänge, verbrauchen Speicherplatz und können den Abfrageplaner verwirren. Indexiere nur die Spalten, die tatsächlich abgefragt werden und hohe Selektivität haben, und bestätige deine Entscheidung mit EXPLAIN.
Warum hat der Index meine Abfrage nicht beschleunigt?
Häufige Ursachen: Du hast die Spalte in eine Funktion verpackt (WHERE YEAR(created_at) = 2026 deaktiviert den Index), du hast die Ganz-links-Regel bei einem zusammengesetzten Index verletzt, oder die Selektivität der Spalte ist zu gering. Die EXPLAIN-Ausgabe verrät meist den Grund.
Sind ein Primärschlüssel und ein Index dasselbe?
Ein Primärschlüssel ist ein spezieller Index: Er ist sowohl eindeutig als auch nicht nullbar (kein NULL) und definiert in den meisten Engines die physische Ordnung der Tabelle (den Clustered Index). Also ist jeder Primärschlüssel ein Index, aber nicht jeder Index ein Primärschlüssel.
Wird deine Datenbank langsam und du findest den Grund nicht? Ich kann deine Abfragen analysieren, die richtige Indexstrategie entwerfen und schlecht laufende Abfragen umschreiben. Kontaktiere mich für Hilfe.