PostgreSQL-Indizes: B-Tree, GIN und wann sie helfen
Kurz: Ein Index ist ein zusätzlicher Suchbaum, der Abfragen beschleunigt, aber Schreibvorgänge und Speicher kostet; man legt ihn gezielt für häufige Filter, Sortierungen und Verknüpfungen an.
Genauer: Ohne Index liest PostgreSQL bei einer Abfrage die ganze Tabelle (Seq Scan). Ein Index findet Zeilen schnell wie ein Stichwortverzeichnis im Buch.
Im Detail
Index-Arten
- B-Tree (Standard): Gleichheit, Bereiche (
<,>,BETWEEN), Sortierung (ORDER BY), Präfix-LIKE 'abc%'. - Hash: nur Gleichheit.
- GIN: Mehrfachwerte (Arrays, JSONB, Volltext
tsvector). - GiST/SP-GiST: Geodaten, Bereiche, Ähnlichkeit.
- BRIN: sehr große, nach Zeit sortierte Tabellen, winzig.
- pgvector (HNSW/IVFFlat): Vektorsuche.
CREATE INDEX idx_nutzer_email ON nutzer (email);
CREATE UNIQUE INDEX uq_nutzer_email ON nutzer (lower(email));
CREATE INDEX idx_best_kunde_datum ON bestellung (kunde_id, erstellt DESC);
CREATE INDEX idx_aktiv ON nutzer (id) WHERE aktiv; -- partiell
CREATE INDEX idx_tags ON artikel USING gin (tags);Wann lohnt ein Index?
- Spalten in WHERE, JOIN (Fremdschlüssel!), ORDER BY.
- Selektive Bedingungen (wenige Treffer).
- Zusammengesetzte Indizes: Reihenfolge wichtig;
(kunde_id, erstellt)hilft beiWHERE kunde_id = …und… AND erstellt …, nicht bei Filter nur auferstellt(Linkspräfix-Regel). - Kein Index bei winzigen Tabellen, bei Spalten mit wenigen Werten (Ja/Nein) allein, oder wenn die Tabelle ständig massiv beschrieben wird.
- Kosten: Jeder Index verlangsamt
INSERT/UPDATE/DELETE, belegt Speicher und Wartung.
Prüfen mit EXPLAIN
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM bestellung WHERE kunde_id = 42 ORDER BY erstellt DESC LIMIT 10;Seq Scan bei großer Tabelle = Verdacht; Index Scan/Index Only Scan/Bitmap Heap Scan = Index genutzt. Der Planer wählt nach Statistiken (ANALYZE); manchmal ist ein Seq Scan bei vielen Treffern schneller. pg_stat_user_indexes zeigt nie genutzte Indizes (löschen). CREATE INDEX CONCURRENTLY baut ohne lange Sperre.
Typische Fehler
Funktionen auf Spalten (WHERE lower(email) = …) verhindern normalen Index (→ Funktionsindex). Typ-Umwandlungen, führendes % bei LIKE, OR über verschiedene Spalten. Fehlender Index auf Fremdschlüssel macht Joins und Löschungen langsam. Zu viele Indizes. Bei serverlosen Datenbanken zählt außerdem Rechenzeit: weniger Seq Scans = weniger CPU-Stunden.
Siehe auch: PostgreSQL, Abfrageplaner und EXPLAIN, Abfragen optimieren mit EXPLAIN, N+1-Problem, Vektordatenbanken