Indizes über mehrere Spalten
Kurz gesagt: Ein zusammengesetzter Index ist ein Index auf mehreren Spalten, der hilft, wenn die Abfrage seine Spalten von links nach rechts verwendet.
Problem
Die letzten zehn
Die Seite „Zuletzt angesehen“ zeigt die letzten 10 Besuche des Kunden, beginnend mit dem neuesten. Der Index auf customer_id ist schon angelegt. Sieh dir den Plan an:
Der Index findet die 60 Besuche, liefert sie aber nicht nach Datum sortiert. Die Datenbank sortiert sie selbst (USE TEMP B-TREE). Bei einem Kunden mit Tausenden Besuchen ist das der langsamste Teil, und gebraucht werden nur 10 davon.
Die Idee
Zwei Spalten in einem Index
Ein Index kann mehrere Spalten umfassen: CREATE INDEX name ON tabelle(spalte1, spalte2). Das ist ein zusammengesetzter Index. Er ist sortiert wie ein Telefonbuch: zuerst nach Nachnamen, und bei gleichem Nachnamen nach Vornamen.
Der Index auf (customer_id, seen_at) ist zuerst nach Kunden sortiert, und die Besuche eines Kunden sind nach Datum sortiert. Die Datenbank findet den Kunden und liest seine Daten vom Ende rückwärts. Sortieren ist nicht nötig:
Derselbe Index hilft auch, wenn die Bedingung beide Spalten betrifft. Die Datenbank geht zum Kunden und sucht in dessen Bereich ab dem Datum:
Und bei der ersten Spalte allein, als wäre es ein Index nur auf customer_id:
Probier es aus
Besuche in einem Zeitraum
Der Kundendienst fragt oft, wie oft ein Kunde ab einem bestimmten Datum Produkte angesehen hat. Lege einen Index genau auf diese beiden Spalten an, damit die Abfrage sowohl beim Kunden als auch beim Datum ein SEARCH ist.
Lösung
CREATE INDEX idx_visits_customer_seen ON visits(customer_id, seen_at);CREATE INDEX idx_visits_customer_seen ON visits(customer_id, seen_at); Auf die Reihenfolge der Spalten kommt es an: zuerst die mit =, dann die mit >=. Die Prüfung schaut, welche Spalten in den Indizes von visits stehen und in welcher Reihenfolge, der Name ist also deine Sache.
Sieh es dir an
Von links nach rechts
Mit demselben Index fragt der Bericht „pro Tag“ nur nach dem Datum:
Der Plan ist ein SCAN. Er sagt USING COVERING INDEX, weil COUNT(*) aus dem Index berechnet wird, aber die Datenbank liest trotzdem alle 300 000 Einträge darin. Führe die Abfrage selbst aus und sieh dir die Zeit an:
In einem Telefonbuch findest du nicht alle, die „Maria“ heißen, ohne das ganze Buch zu lesen. Die Vornamen sind nur innerhalb jedes Nachnamens sortiert.
Das ist die Regel von links nach rechts: Ein Index auf (a, b) hilft bei Bedingungen auf a, auf a und b und bei ORDER BY b, wenn a mit = vorgegeben ist. Bei einer Bedingung nur auf b hilft er nicht. Wenn du unsicher bist, prüfe es mit EXPLAIN QUERY PLAN.
Die Idee
Was ein Index kostet
Indizes sind nicht umsonst. Jede neue Zeile muss in jedem Index der Tabelle an ihren Platz geschrieben werden. Die beiden Felder unten fügen je 100 000 Besuche hinzu. Das erste hat keine Indizes, das zweite vier. Führe sie aus und vergleiche die Zeiten:
Dasselbe gilt für ein UPDATE einer indizierten Spalte und für DELETE.
Indizes belegen auch Platz. SQLite speichert die Datenbank in Seiten zu 4 096 Byte, und pragma_page_count() sagt, wie viele Seiten es gibt. Hier ist die Datenbank ohne Indizes und mit den vier:
Mit den vier Indizes ist die Datenbank mehr als dreimal so groß. Darum legst du Indizes für die Abfragen an, die du wirklich hast, und nicht für jede Spalte „zur Sicherheit“.
Genauer, für Neugierige
Der zweite der vier Indizes, (customer_id, seen_at), macht den ersten, (customer_id), überflüssig: Nach der Regel von links nach rechts erledigt er auch dessen Aufgabe. Solche Paare sind häufig und fallen selten auf. PostgreSQL zählt mit, wie oft jeder Index benutzt wurde (pg_stat_user_indexes), sodass sich die ungenutzten finden lassen.
Übung
Zwei Aufgaben
1. Die Datenbank hat einen Index auf (customer_id) und einen auf (customer_id, seen_at). Entferne den überflüssigen.
Entferne den Index, dessen Aufgabe der andere miterledigt:
Lösung
DROP INDEX idx_visits_customer;DROP INDEX idx_visits_customer; Der Index auf (customer_id, seen_at) übernimmt auch die Suche allein nach dem Kunden. Umgekehrt gilt das nicht: Der Index nur auf dem Kunden hilft nicht beim Sortieren nach Datum.
2. Der Index auf (customer_id, seen_at) ist angelegt. Zeige die Daten der letzten 3 Besuche von Kunde 1234, beginnend mit dem neuesten.
Die letzten 3 Besuchsdaten von Kunde 1234:
Lösung
SELECT seen_at FROM visits
WHERE customer_id = 1234
ORDER BY seen_at DESC LIMIT 3;WHERE customer_id = 1234 ORDER BY seen_at DESC LIMIT 3. Du bekommst 2026-10-10 und zweimal 2026-09-20: An diesem Tag hat der Kunde die Seite zweimal geöffnet. Mit dem Index findet die Datenbank den Kunden, liest drei Einträge vom Ende und hört auf.
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Aggregatfunktionen: COUNT, SUM, AVG · INSERT: Zeilen einfügen · Indizes · EXPLAIN: der Abfrageplan
- Geht weiter in: Langsame Abfragen
- Aufgaben zum Thema: Indizes und Geschwindigkeit