CodeGym /Kurse /SQL SELF /Typische Probleme beim Arbeiten mit Indizes

Typische Probleme beim Arbeiten mit Indizes

SQL SELF
Level 38 , Lektion 4
Verfügbar

Selbst die modernste Maschine bleibt stehen, wenn du statt Benzin Limonade reinkippst. Genau so ist es mit Indizes in PostgreSQL. Sie sind ein richtig starkes Werkzeug, aber du solltest sie mit Köpfchen einsetzen. Lass uns mal ein paar typische Probleme anschauen, die mit Indizes zusammenhängen.

Problem 1: Zu viele Indizes

Zur Erinnerung an das Thema aus der vor-vorherigen Vorlesung: Wenn du zu viele Indizes auf einer Tabelle hast, muss PostgreSQL jeden einzelnen davon aktuell halten. Das wirkt sich direkt auf Insert-, Update- und Delete-Operationen aus. Jeder Index muss nicht nur aktualisiert, sondern auch synchronisiert werden!

Angenommen, wir haben eine Tabelle students:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(255) UNIQUE,
    age INTEGER,
    grade INTEGER
);

Und du entscheidest dich, auf jede Spalte einen Index zu legen – einfach so, für alle Fälle:

CREATE INDEX idx_students_name ON students(name);
CREATE INDEX idx_students_age ON students(age);
CREATE INDEX idx_students_grade ON students(grade);

Stell dir jetzt vor, du fügst 10.000 neue Datensätze ein. PostgreSQL muss nicht nur die Daten in die Tabelle schreiben, sondern auch alle drei Indizes aktualisieren. Wenn es viele Daten sind, wird das Einfügen langsamer und die Performance leidet.

Wie kann man das vermeiden? Bevor du einen Index anlegst, stell dir zwei Fragen:

  1. Wie oft wird diese Spalte für Filter (WHERE), Sortierung (ORDER BY) oder Gruppierung (GROUP BY) verwendet?
  2. Wird die Abfrage diesen Index wirklich nutzen oder trotzdem ein Full Table Scan machen?

Wenn die Antwort auf beide Fragen „selten“ oder „nie“ ist, brauchst du den Index nicht.

Problem 2: Falsche Spalten für Indizes gewählt

Einen Index auf Daten mit wenig Varianz zu legen ist wie zu versuchen, Tee in eine Tasse mit festem Deckel zu gießen: Das Ergebnis ist praktisch nutzlos. Wenn eine Spalte nur 2-3 einzigartige Werte hat, macht PostgreSQL meistens trotzdem einen Full Table Scan statt den Index zu nutzen.

Angenommen, wir haben eine Tabelle courses:

CREATE TABLE courses (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255),
    level VARCHAR(10) -- Kann nur 'Beginner', 'Intermediate' oder 'Advanced' sein
);

Und du legst einen Index auf die Spalte level an:

CREATE INDEX idx_courses_level ON courses(level);

Aber die Abfrage:

SELECT * FROM courses WHERE level = 'Beginner';

wird den Index vielleicht gar nicht nutzen, weil PostgreSQL einfach entscheidet, dass es schneller ist, die ganze Tabelle zu scannen, als in den Index zu schauen. Das gilt besonders für kleine Tabellen und Spalten mit wenig unterschiedlichen Werten.

Deshalb machen Indizes vor allem auf Spalten mit hoher Kardinalität (also vielen einzigartigen Werten) Sinn. Für Spalten mit wenig Varianz solltest du lieber andere Optimierungsmethoden nutzen, zum Beispiel Table Partitioning.

Problem 3: Veraltete Indizes

Manchmal werden Indizes angelegt und dann vergessen, auch wenn sie gar nicht mehr gebraucht werden. Das ist wie Dateien auf dem Desktop: Erst sind es nur zwei, drei, fünf. Und plötzlich erwischst du dich dabei, wie du ewig suchst, um das Richtige zu finden... Kennst du das?

Angenommen, wir haben einen Index für ein altes Feature angelegt, dann die Abfragen geändert und einen neuen Index hinzugefügt. Der alte Index wird nicht mehr gebraucht, bleibt aber bestehen, belegt Platz und verlangsamt Inserts.

Um das zu vermeiden, check regelmäßig deine Indizes. PostgreSQL hat dafür eine praktische Metrik:

SELECT
    relname AS table_name,
    indexrelname AS index_name,
    idx_scan AS total_scans
FROM
    pg_stat_user_indexes
WHERE
    idx_scan = 0;

Hier zeigt idx_scan an, wie oft ein Index benutzt wurde. Wenn der Wert 0 ist, wird der Index nicht genutzt und kann gelöscht werden:

DROP INDEX idx_courses_level;

Problem 4: Indizes auf Spalten mit häufigen Updates

Wenn du einen Index auf einer Spalte hast, die oft geändert wird, muss PostgreSQL den Index bei jeder Änderung neu aufbauen. Das kann die Performance ordentlich runterziehen.

Stell dir eine Tabelle mit Bestellungen vor:

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    status VARCHAR(20), -- Kann sich mehrmals ändern (z.B. "neu", "in bearbeitung", "abgeschlossen")
    total NUMERIC(10, 2)
);

Du legst einen Index auf die Spalte status, um nach Status zu filtern:

CREATE INDEX idx_orders_status ON orders(status);

Aber wenn sich der Status für jeden Datensatz zigmal ändert, wird der Index zur Performance-Bremse.

Um das zu vermeiden, leg keine Indizes auf Spalten mit häufigen Änderungen. Wenn du trotzdem einen Index brauchst, denk über partielle Indizes nach:

CREATE INDEX idx_orders_status_partial
ON orders(status) 
WHERE status = 'in bearbeitung';

So wird der Index nur für Datensätze mit diesem Wert aktualisiert.

Problem 5: UNIQUE-Constraints auf unnötigen Spalten

Unique Indizes (UNIQUE) werden automatisch angelegt, um die Einzigartigkeit der Daten zu sichern. Aber wenn die Einzigartigkeit nicht wirklich nötig ist, verursachen diese Indizes nur unnötige Last.

Angenommen, wir haben eine Tabelle mit Logs:

CREATE TABLE logs (
    id SERIAL PRIMARY KEY,
    message TEXT,
    created_at TIMESTAMP UNIQUE
);

Wenn jede Sekunde tausende Einträge in die Tabelle kommen, sorgt die Einzigartigkeit auf created_at für richtig viel Overhead.

Damit alles rund läuft, setz UNIQUE-Constraints nur da, wo sie wirklich gebraucht werden. In unserem Beispiel: Wenn die Einzigartigkeit auf created_at nicht nötig ist, ersetz den Index durch einen normalen:

CREATE INDEX idx_logs_created_at ON logs(created_at);

Problem 6: Falscher Einsatz von kombinierten Indizes

Kombinierte Indizes (multi-column indexes) sind praktisch, wenn Abfragen nach mehreren Spalten gleichzeitig filtern oder sortieren. Aber solche Indizes müssen richtig angelegt werden, sonst werden sie nicht genutzt.

Angenommen, wir haben diesen Index:

CREATE INDEX idx_students_name_grade ON students(name, grade);

Dieser Index wird genutzt, wenn die Abfrage nach beiden Spalten filtert oder sortiert:

SELECT * FROM students WHERE name = 'Alice' AND grade = 90;

Aber die Abfrage:

SELECT * FROM students WHERE grade = 90;

nutzt diesen Index nicht, weil das Feld name zuerst kommt.

Um das zu vermeiden, leg kombinierte Indizes nur in der Reihenfolge an, wie sie in den Abfragen am häufigsten gebraucht werden. Wenn du oft nur nach einer Spalte filterst, leg dafür einen eigenen Index an.

Nützliche Tipps

Überwache die Nutzung deiner Indizes. In PostgreSQL gibt es die System-View pg_stat_user_indexes, wo du sehen kannst, welche Indizes genutzt werden und welche nicht.

Optimiere deine Abfragen zusammen mit den Indizes. Schlechte Abfragen bleiben auch mit Indizes schlecht.

Vergiss das Löschen nicht. Veraltete Indizes nehmen nur Platz weg und machen Inserts langsamer.

Das war’s, Leute! Indizes sind ein mächtiges Werkzeug, aber denk immer dran: Mit großer Macht kommt große Verantwortung. Setz Indizes mit Bedacht ein, dann läuft deine Datenbank wie eine SpaceX-Rakete!

1
Umfrage/Quiz
Probleme durch übermäßiges Indexieren, Level 38, Lektion 4
Nicht verfügbar
Probleme durch übermäßiges Indexieren
Probleme durch übermäßiges Indexieren
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION