Gespeicherte Prozedur zum Wiederherstellen oder Reorganisieren fragmentierter Datenbankindizes
Eine wiederverwendbare gespeicherte Prozedur, die Sie aufrufen können, um eine Datenbank neu zu indizieren, indem Sie den Namen der Datenbank eingeben.
Ziel
Dies ist eine praktische gespeicherte Prozedur, die Sie buchstäblich kopieren und in Ihre Master- oder Dienstprogrammdatenbank einfügen können, um alle Tabellen in einer bestimmten Datenbank neu zu indizieren.
Der nützlichste Teil davon ist, dass Sie den Datenbanknamen eingeben, wenn Sie die Prozedur aufrufen. Dies bedeutet, dass Sie alle Ihre Datenbanken auf einmal durchlaufen können, indem Sie dieselbe Prozedur wie folgt aufrufen. Wenn Sie Verbindungsserver haben, können Sie sie auch aufrufen ein anderer Server, wenn er richtig aufgerufen wird.
Multiple call SQL
EXEC [utilities].[maint].DatabaseReIndex 'YourDatabaseName'
EXEC [utilities].[maint].DatabaseReIndex 'YourDatabaseName2'
Ziel
Während es möglich ist, dies während der Arbeitszeit auszuführen, ist es immer sinnvoller, dies auszuführen, wenn auf dem Server nur sehr wenig Arbeit geleistet wird.
SQL
USE [utilities]
GO
CREATE PROC [maint].DatabaseReIndex(@Database VARCHAR(100)) AS BEGIN
DECLARE @DbID SMALLINT=DB_ID(@Database)--Get Database ID
DECLARE @I TABLE (IndexTempID INT IDENTITY(1,1),SchemaName NVARCHAR(128),TableName NVARCHAR(128),IndexName NVARCHAR(128),IndexFrag FLOAT)
INSERT INTO @I
EXEC ('USE '+@Database+';
SELECT sch.name,OBJECT_NAME(ind.OBJECT_ID) AS TableName,ind.name IndexName,indexstats.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats('+@DbID+', NULL, NULL, NULL, NULL) indexstats
INNER JOIN sys.indexes ind ON ind.object_id = indexstats.object_id AND ind.index_id = indexstats.index_id
INNER JOIN sys.objects obj on obj.object_id=indexstats.object_id
INNER JOIN sys.schemas as sch ON sch.schema_id = obj.schema_id
WHERE indexstats.avg_fragmentation_in_percent > 10 AND indexstats.index_type_desc<>''HEAP''
ORDER BY indexstats.avg_fragmentation_in_percent DESC')--Get index data and fragmentation, set the percentage as high or low as you need
DECLARE @IndexTempID BIGINT=0,@SchemaName NVARCHAR(128),@TableName NVARCHAR(128),@IndexName NVARCHAR(128),@IndexFrag FLOAT
SELECT * FROM @I--View your results, comment out if not needed...
-- Loop through the indexes
WHILE @IndexTempID IS NOT NULL BEGIN
SELECT @SchemaName=SchemaName,@TableName=TableName,@IndexName=IndexName,@IndexFrag=IndexFrag FROM @I WHERE IndexTempID=@IndexTempID
IF @IndexName IS NOT NULL AND @SchemaName IS NOT NULL AND @TableName IS NOT NULL BEGIN
IF @IndexFrag<30. BEGIN--Low fragmentation can use re-organise, set at 30 as per most articles
PRINT 'USE '+@Database+'; ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @TableName + N' REORGANIZE'
EXEC('USE '+@Database+'; ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @TableName + N' REORGANIZE')
END
ELSE BEGIN--High fragmentation needs re-build
PRINT 'USE '+@Database+'; ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @TableName + N' REBUILD'
EXEC('USE '+@Database+'; ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @TableName + N' REBUILD')
END
END
SET @IndexTempID=(SELECT MIN(IndexTempID) FROM @I WHERE IndexTempID>@IndexTempID)
END
GO