SQL Indexe erklärt – B-Tree, Hash und GIN
Deine Datenbank fühlt sich langsam an, obwohl die Hardware passt. Oft fehlt das richtige Indexdesign. SQL Indexe beschleunigen Abfragen, indem sie Treffer gezielt finden, statt ganze Tabellen zu scannen. In diesem Einsteiger-Guide erkläre ich verständlich, was B-Tree, Hash und GIN leisten, wann welcher Index die beste Wahl ist und wie du sie praxisnah einsetzt.
Was ein Index ist – in einfachen Worten
Ein Index ist wie das Inhaltsverzeichnis eines Buchs: Statt jede Seite zu lesen, springst du direkt zur gesuchten Stelle. In Datenbanken verweist ein Index von Sortierschlüsseln auf Tabellenzeilen. Das spart Zeit, besonders bei großen Tabellen. Wichtig: Jeder Index kostet Speicher und macht Schreibvorgänge etwas teurer. Ziel ist daher so wenige Indexe wie nötig, so wirksam wie möglich.
B-Tree, Hash, GIN – die Unterschiede auf den Punkt
B-Tree – der Allrounder
Der Standardindex in vielen Systemen ist B-Tree. Er hält Schlüssel sortiert und unterstützt Bereiche und Vergleiche wie =, <, <=, >, BETWEEN, ORDER BY. Perfekt für Primärschlüssel, Fremdschlüssel, Datumsfelder und Sortierungen.
Stärken: Schnell bei exakten Treffern und Range Queries, kann Mehrspalten sinnvoll abbilden.
Grenzen: Bei extrem niedriger Selektivität (z. B. Feld hat nur wenige unterschiedliche Werte) bringt er wenig.
Hash – der Spezialist für Gleichheit
Hash-Indexe beschleunigen exakte Gleichheitsvergleiche (WHERE code = ‚ABC123‘). Sie speichern Hashwerte statt sortierter Schlüssel.
Stärken: Sehr schnell für = auf hoch selektiven Feldern.
Grenzen: Keine Ranges, keine Sortierung, je nach DB weniger Features als B-Tree. In vielen Workloads ist ein B-Tree ausreichend und flexibler.
GIN – Generalized Inverted Index
GIN eignet sich für Sammlungen in einer Spalte: Arrays, JSONB, Textsuche. Er indexiert Elemente statt ganzer Zeilen.
Stärken: Sehr gut für Enthält-Abfragen wie @> bei JSONB, ANY bei Arrays, Volltextsuche mit to_tsvector.
Grenzen: Teurer im Schreiben und größer als B-Tree. Lohnt sich, wenn du häufig auf Feldelemente oder Wörter suchst.
Praxis – so setzt du die Indexe ein
B-Tree richtig nutzen
Wenn du oft nach E-Mail suchst oder zeitliche Bereiche filterst, ist B-Tree die erste Wahl.
-- Eindeutige E-Mail
CREATE UNIQUE INDEX idx_users_email ON users (email);
-- Abfragen nach Zeiträumen
CREATE INDEX idx_orders_created_at ON orders (created_at);
Tipp: Bei Mehrspaltenindexen zählt die Reihenfolge. Setze das selektivere Feld nach vorn. Für Sortierungen kann (created_at, id) sinnvoll sein.
Hash gezielt einsetzen
Bei reinen Gleichheitsvergleichen auf kurzen Codes kann Hash eine Option sein.
CREATE INDEX idx_coupons_code_hash ON coupons USING hash (code);
Merke: Prüfe, ob B-Tree nicht bereits schnell genug ist. Hash ist spezialisiert, B-Tree bleibt flexibel.
GIN für JSONB, Arrays und Textsuche
Wenn du in JSONB nach Schlüsseln oder Teilstrukturen suchst, bringt GIN große Vorteile.
-- JSONB Teilabgleich
CREATE INDEX idx_products_data_gin ON products USING gin (data);
-- Arrays: Enthält Element
CREATE INDEX idx_tags_gin ON articles USING gin (tags);
-- Volltextsuche
CREATE INDEX idx_posts_search_gin
ON posts USING gin (to_tsvector('simple', title || ' ' || content));
Abfragen:
- JSONB:
WHERE data @> '{"brand":"Acme"}'
- Arrays:
WHERE tags @> ARRAY['excel']
oderWHERE 'excel' = ANY(tags)
- Textsuche:
WHERE to_tsvector('simple', title || ' ' || content) @@ plainto_tsquery('excel tipps')
Welche Index-Art wählst du wann
Wenn du Bereiche oder Sortierung brauchst
Nimm B-Tree. Er unterstützt Range Queries und ORDER BY direkt und stabil.
Wenn du nur Gleichheit auf einen hoch selektiven Key hast
Prüfe B-Tree zuerst. Bringt er nicht genug, teste Hash.
Wenn du in Feldern nach Elementen suchst
Bei Arrays, JSONB oder Volltext wähle GIN. Er ist für Elementsuche gemacht.
Best Practices für Einsteiger
Indexe messen statt raten
Nutze EXPLAIN ANALYZE, um zu sehen, ob der Planner den Index verwendet. Achte auf Index Scan statt Seq Scan und miss die Laufzeit.
Über-Indexierung vermeiden
Jeder Index kostet Platz und verlangsamt INSERT/UPDATE/DELETE. Entferne Indexe, die nie genutzt werden. Eine Query-Statistik oder Monitoring hilft bei der Entscheidung.
Selektivität und Kardinalität verstehen
Indexe wirken, wenn ein Prädikat viele Zeilen ausschließt. Felder mit wenigen unterschiedlichen Werten bringen selten Gewinn. Halte Statistiken aktuell (ANALYZE), damit der Planner gute Entscheidungen trifft.
Partielle und Ausdrucksindexe
Mit partiellen Indexen beschleunigst du häufige Teilmengen:
CREATE INDEX idx_orders_open ON orders (customer_id) WHERE status = 'open';
Mit Ausdrucksindexen deckst du berechnete Felder ab:
CREATE INDEX idx_users_lower_email ON users (lower(email));
-- Abfrage: WHERE lower(email) = 'a@b.de'
Covering Indexe
Bei Systemen wie PostgreSQL kannst du INCLUDE-Spalten nutzen, damit die Abfrage nur im Index liest:
CREATE INDEX idx_orders_lookup ON orders (customer_id) INCLUDE (created_at, total);
Wartung nicht vergessen
Halte Autovacuum/Analyze aktiv, beobachte Index-Bloat, halte Füllstand schlau und aktualisiere Statistiken nach großen Datenänderungen.
Häufige Fragen kurz beantwortet
Bringt ein Index auf einer kleinen Tabelle etwas
Meist nein. Der Overhead lohnt selten. Ab einer gewissen Tabellengröße gewinnt der Index klar.
Warum greift mein Index nicht
Oft stimmt die Bedingung nicht zum Index, die Statistiken sind alt oder die Abfrage holt zu viele Zeilen, sodass ein Seq Scan günstiger ist.
Hilft ein Index bei LIKE
B-Tree hilft bei prefix LIKE wie LIKE 'abc%'
. Für Teilstrings ohne Präfix ist Volltext oder ein spezieller Trigram-Index sinnvoll. Für JSONB und Arrays ist GIN das bessere Werkzeug.
Fazit
B-Tree, Hash und GIN lösen unterschiedliche Probleme. B-Tree ist dein Allrounder für Gleichheit, Bereiche und Sortierung. Hash punktet bei reiner Gleichheit auf hoch selektiven Feldern. GIN glänzt, wenn du in Arrays, JSONB oder Text nach Elementen suchst. Miss mit EXPLAIN ANALYZE, halte Statistiken frisch und setze nur die Indexe, die wirklich gebraucht werden – dann werden deine Abfragen spürbar schneller.
Hinterlasse einen Kommentar
An der Diskussion beteiligen?Hinterlasse uns deinen Kommentar!