Wenn’s langsam wird, fehlt meist ein Index

Abfragen brauchen Zeit.
Und wenn’s immer dieselbe Tabelle ist, dann liegt’s meist an den fehlenden Indizes.

Ohne passenden Index scannt SQL Server die komplette Tabelle.
Und das bei jeder Ausführung.

Gerade in KMU-Systemen sehe ich oft:
300.000 Zeilen, keine Indizes außer dem Primary Key.
Und dann wundert man sich, warum der Bericht 40 Sekunden braucht.

So finde ich fehlende Indizes – systematisch

SQL Server merkt sich, welche Spalten gerne gefiltert werden.
Und welche Spalten häufig gelesen werden.
Er schlägt Dir sogar Indizes vor. Du musst sie nur abholen.

Übersicht der empfohlenen Indizes

SELECT 
    migs.user_seeks + migs.user_scans AS anfragen,
    migs.avg_total_user_cost * (migs.user_seeks + migs.user_scans) AS gewichtung,
    mid.statement AS tabelle,
    mid.equality_columns,
    mid.inequality_columns,
    mid.included_columns
FROM sys.dm_db_missing_index_group_stats AS migs
JOIN sys.dm_db_missing_index_groups AS mig ON migs.group_handle = mig.index_group_handle
JOIN sys.dm_db_missing_index_details AS mid ON mig.index_handle = mid.index_handle
WHERE migs.user_seeks + migs.user_scans > 10
ORDER BY gewichtung DESC;

So bekommst Du:

  • welche Spalten fehlen im Index
  • wie oft wird danach gesucht
  • welche Spalten gelesen werden (für INCLUDE)
  • wie teuer ist die aktuelle Abfrage

Index-Vorschlag erzeugen

-- Beispiel:
CREATE NONCLUSTERED INDEX ix_kunde_plz_ort
ON dbo.kunde (plz, ort)
INCLUDE (name, telefon);

Achte auf die Reihenfolge:
Spalten mit Gleichheitsbedingung zuerst.
Dann Ungleichheitsbedingungen.
Dann INCLUDE.

Wichtige Faustregeln

ProblemLösungsidee
WHERE ohne IndexSpalte als Schlüssel in Index nehmen
JOIN wird gescanntJoin-Spalte indexieren
Sortierung zu langsamIndex auf ORDER BY-Spalte(n)
Spalten oft gelesenINCLUDE verwenden

Beispiel: Bericht mit Filtersuche

SELECT name, ort, plz 
FROM dbo.kunde
WHERE ort = 'Hamburg'
ORDER BY name;

Passender Index:

CREATE NONCLUSTERED INDEX ix_kunde_ort_name
ON dbo.kunde (ort)
INCLUDE (name, plz);

Ergebnis: kein Scan, keine Sortierung, direkter Zugriff.

Vorsicht: Keine Indexpest erzeugen

Zu viele Indizes = langsames INSERT/UPDATE
Deshalb:

  • nicht mehr als 4–6 Indizes pro Tabelle
  • nur das indexieren, was oft genutzt wird
  • überlappende Indizes zusammenfassen
  • alte, ungenutzte Indizes löschen
SELECT 
    OBJECT_NAME(s.object_id) AS tabelle,
    i.name AS indexname,
    i.type_desc,
    user_seeks, user_scans, user_lookups, user_updates
FROM sys.dm_db_index_usage_stats AS s
JOIN sys.indexes AS i ON s.object_id = i.object_id AND s.index_id = i.index_id
WHERE database_id = DB_ID()
AND user_seeks + user_scans + user_lookups = 0
AND user_updates > 0;

So findest Du Indizes, die nie genutzt, aber ständig aktualisiert werden.

Mein Fazit

Fehlende Indizes sind wie fehlende Wegweiser.
Du findest den Datensatz – aber nur mit Mühe.

Wenn Du regelmäßig langsame Queries hast, lohnt sich ein Blick in die DMVs.
SQL Server zeigt Dir den Weg – Du musst nur folgen.

Wenn Du willst, optimier ich mit Dir gemeinsam die zehn langsamsten Abfragen.
Meist genügen drei neue Indizes – und plötzlich läuft’s.

Tags:

No responses yet

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert