Wenn der Index nicht mehr weiß, wo oben ist

Indexe in SQL Server sind wie Karteikarten.
Wenn sie zu oft umsortiert, gelöscht und beschrieben werden,
stehen sie irgendwann kreuz und quer.

Das kostet Performance.
Vor allem bei großen Tabellen.
Und bei Joins.

Was bei Fragmentierung passiert

  • SQL Server muss mehr Seiten lesen
  • Mehr Leseoperationen = mehr I/O
  • Mehr CPU durch ungĂŒnstige PlĂ€ne
  • Langsame Abfragen, obwohl Index da ist

Ab 5 % Fragmentierung solltest Du aufrÀumen.
Ab 30 % wird’s Zeit fĂŒr einen Rebuild.

Unterschied: Reorganize vs. Rebuild

MaßnahmeFragmentierung abSperrt TabelleStatistiken neu?Logging
Reorganize5 %NeinNeinminimal
Rebuild30 %Ja (Offline)Jamehr Log

Online-Rebuild geht nur in der Enterprise Edition.
Sonst steht die Tabelle kurz still.

Beispiel: Manuelle Analyse und Pflege

-- Fragmentierung auslesen
SELECT 
    OBJECT_NAME(i.object_id) AS Tabelle,
    i.name AS Indexname,
    ips.avg_fragmentation_in_percent,
    ips.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE ips.page_count > 100
ORDER BY ips.avg_fragmentation_in_percent DESC;

Dann gezielt reorganisieren oder rebuilden:

-- Reorganize
ALTER INDEX [IX_Kunden_Name] ON dbo.Kunden REORGANIZE;

-- Rebuild
ALTER INDEX [IX_Kunden_Name] ON dbo.Kunden REBUILD WITH (FILLFACTOR = 90);

Automatisiert: Dynamisches Skript zur Pflege

DECLARE @Tabelle SYSNAME
DECLARE @Index SYSNAME
DECLARE @SQL NVARCHAR(MAX)

DECLARE cur CURSOR FOR
SELECT 
    OBJECT_NAME(i.object_id),
    i.name
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE ips.avg_fragmentation_in_percent > 5
AND ips.page_count > 100;

OPEN cur  
FETCH NEXT FROM cur INTO @Tabelle, @Index  

WHILE @@FETCH_STATUS = 0  
BEGIN  
    SET @SQL = '
    IF EXISTS (
        SELECT 1
        FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID(N''' + @Tabelle + '''), NULL, NULL, ''LIMITED'') ips
        JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
        WHERE i.name = ''' + @Index + ''' AND ips.avg_fragmentation_in_percent BETWEEN 5 AND 30
    )
        ALTER INDEX [' + @Index + '] ON [' + @Tabelle + '] REORGANIZE;
    ELSE
        ALTER INDEX [' + @Index + '] ON [' + @Tabelle + '] REBUILD WITH (FILLFACTOR = 90);'

    EXEC sp_executesql @SQL
    FETCH NEXT FROM cur INTO @Tabelle, @Index  
END  

CLOSE cur  
DEALLOCATE cur

LĂ€uft idealerweise nachts oder am Wochenende im SQL Agent.
Nur auf produktionsfernen Zeitfenstern.

Optional: Statistiken aktualisieren

Nach einem Rebuild sind die Statistiken frisch.
Nach Reorganize nicht.

Darum:

EXEC sp_updatestats;

Einmal pro Woche reicht bei den meisten KMU.

Monitoring: Letzte Indexpflege prĂŒfen

SELECT 
    OBJECT_NAME(i.object_id) AS Tabelle,
    i.name AS Indexname,
    s.last_user_update
FROM sys.dm_db_index_usage_stats s
JOIN sys.indexes i ON s.object_id = i.object_id AND s.index_id = i.index_id
WHERE database_id = DB_ID()
ORDER BY s.last_user_update DESC;

So erkennst Du, ob ein Index ĂŒberhaupt noch gebraucht wird.
Oder ob Du besser gleich ausmisten solltest.

Mein Setup in der Praxis

AufgabeIntervallWerkzeug
Fragmentierung prĂŒfenwöchentlichSQL Agent Job
Reorg/Rebuild startenautomatischper Cursor / Skript
Stats aktualisierenwöchentlichsp_updatestats
MonitoringmonatlichReporting via View
DokujÀhrlichExport aus sys.indexes

Ein Index ist kein Kunstwerk

Er muss funktionieren – nicht schön aussehen.

Aber wenn er fragmentiert ist, bringt er niemandem was.
Pflege ihn.
Automatisch. RegelmĂ€ĂŸig.
Dann lÀuft der Laden. Auch ohne Drama.

Tags:

No responses yet

Schreibe einen Kommentar

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