Dieses Blog durchsuchen

Mittwoch, 1. Juli 2015

Index Rebuild

Im Laufe der Zeit steigt automatisch auch die Fragmentierung von vielen Indizes stetig an.
Je mehr sich in der betroffenen Tabelle ändert, desto höher wird die Fragmentierung. Dies wirkt sich natürlich auch auf die Durchführungszeit von unzähligen Queries aus.
Daher ist es ratsam regelmäßig die Indizes zu reorganisieren oder überhaupt neu aufzubauen.
Dies ist mit dem unten angeführten Skript einfach realisierbar. 


Mit der derzeitigen Einstellungen, werden alle Indizes, welche eine Fragmentierung über 10% aufweisen neu aufgebaut (rebuild oder reorg). Der Index Neuaufbau verbraucht mehr CPU, als ein Index-Reorg. In meinem konkreten Fall ist dies vernachlässigbar, da eine Beladung nur einmal täglich durchgeführt wird und danach auf diesem Beladeserver nicht viel los ist. 

Empfehlung:
Es gibt viele Einstellungsmöglichkeiten, jeder sollte ausprobieren, welche für seinen konkreten Fall, die ideale Lösung darstellt.
Grundsätzlich sollten Indizes, welche eine Fragmentierung über 30% aufweisen, mit einem REBUILD und Indizes mit einer Framentierung zwischen 10% und 30% mit einem REORG bereinigt werden.

Zusätzlich gibt es in der SQL Server Development Version und Enterprise Version die ONLINE-Option. Durch diese bleibt der Fragmentierte Index während der REBUILD-Phase weiterhin verfügbar.

/*
Dieses Skript überprüft in der angegebenen Datenbank alle Indizes bezüglich Fragmentierung.
Ist der Index zu fragmentiert - Schwellwert in % überschritten - wird ein Rebuild auf ebendiesen abgesetzt.
*/


USE MyDatabase -- $$change - Hier den Datenbanknamen einfügen
GO

BEGIN TRY
BEGIN TRAN

SET NOCOUNT ON;

DECLARE @objectid int;
DECLARE @indexid int;
DECLARE @partitioncount bigint;
DECLARE @schemaname nvarchar(130);
DECLARE @objectname nvarchar(130);
DECLARE @indexname nvarchar(130);
DECLARE @partitionnum bigint;
DECLARE @partitions bigint;
DECLARE @frag float;
DECLARE @pagecount int;
DECLARE @command nvarchar(4000);

DECLARE @page_count_minimum smallint
SET @page_count_minimum   = 500 -- $$change - Hier Mindestwert für Pageanzahl der zu prüfenden Indizes angeben

DECLARE @fragmentation_minimum float
SET @fragmentation_minimum   = 10.0 -- $$change - Hier den Schwellwert der Fragmentierung in Prozent angeben

SELECT object_id AS objectid,
index_id AS indexid,
partition_number AS partitionnum,
avg_fragmentation_in_percent AS frag,
page_count AS page_count
INTO #work_to_do
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')
WHERE avg_fragmentation_in_percent > @fragmentation_minimum
AND index_id > 0
AND page_count > @page_count_minimum;

-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;

-- Open the cursor.
OPEN partitions;

-- Loop through the partitions.
WHILE (1=1)
BEGIN;
FETCH NEXT
FROM partitions
INTO @objectid, @indexid, @partitionnum, @frag, @pagecount;

IF @@FETCH_STATUS < 0 BREAK;

SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
FROM sys.objects AS o
JOIN sys.schemas as s ON s.schema_id = o.schema_id
WHERE o.object_id = @objectid;

SELECT @indexname = QUOTENAME(name)
FROM sys.indexes
WHERE  object_id = @objectid AND index_id = @indexid;

SELECT @partitioncount = count (*)
FROM sys.partitions
WHERE object_id = @objectid AND index_id = @indexid;

SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname;
IF @frag > 30
 SET @command = @command + + N' REBUILD';
ELSE IF @frag <= 30
 SET @command = @command + + N' REORG';
IF @partitioncount > 1
SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10));
PRINT @command
EXEC (@command);

IF @frag > 30
 PRINT N'Rebuilding index ' + @indexname + ' on table ' + @objectname;
ELSE IF @frag <= 30
 PRINT N'Reorganizing index ' + @indexname + ' on table ' + @objectname;
PRINT N'  Fragmentation: ' + CAST(@frag AS varchar(15));
PRINT N'  Page Count:    ' + CAST(@pagecount AS varchar(15));
PRINT N' ';
END;

-- Close and deallocate the cursor.
CLOSE partitions;
DEALLOCATE partitions;

-- Drop the temporary table.
DROP TABLE #work_to_do;
COMMIT TRAN

END TRY
BEGIN CATCH
ROLLBACK TRAN
PRINT 'ERROR ENCOUNTERED'
END CATCH

Keine Kommentare:

Kommentar veröffentlichen