Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Den INDEX-Neuaufbau basierend auf den Fragmentierungsergebnissen automatisieren?

Ich verwende dieses Skript. Bitte beachten Sie, dass ich Ihnen raten würde, sich über die dmv zu informieren, die ich hier verwende, sie sind ein verstecktes Juwel in SQL2005+.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
CREATE TABLE #FragmentedIndexes
(
 DatabaseName SYSNAME
 , SchemaName SYSNAME
 , TableName SYSNAME
 , IndexName SYSNAME
 , [Fragmentation%] FLOAT
)

INSERT INTO #FragmentedIndexes
SELECT
 DB_NAME(DB_ID()) AS DatabaseName
 , ss.name AS SchemaName
 , OBJECT_NAME (s.object_id) AS TableName
 , i.name AS IndexName
 , s.avg_fragmentation_in_percent AS [Fragmentation%]
FROM sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL, 'SAMPLED') s
INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas ss ON ss.[schema_id] = o.[schema_id]
WHERE s.database_id = DB_ID()
AND i.index_id != 0
AND s.record_count > 0
AND o.is_ms_shipped = 0
DECLARE @RebuildIndexesSQL NVARCHAR(MAX)
SET @RebuildIndexesSQL = ''
SELECT
 @RebuildIndexesSQL = @RebuildIndexesSQL +
CASE
 WHEN [Fragmentation%] > 30
   THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
      + QUOTENAME(SchemaName) + '.'
      + QUOTENAME(TableName) + ' REBUILD;'
 WHEN [Fragmentation%] > 10
    THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
    + QUOTENAME(SchemaName) + '.'
    + QUOTENAME(TableName) + ' REORGANIZE;'
END
FROM #FragmentedIndexes
WHERE [Fragmentation%] > 10
DECLARE @StartOffset INT
DECLARE @Length INT
SET @StartOffset = 0
SET @Length = 4000
WHILE (@StartOffset < LEN(@RebuildIndexesSQL))
BEGIN
 PRINT SUBSTRING(@RebuildIndexesSQL, @StartOffset, @Length)
 SET @StartOffset = @StartOffset + @Length
END
PRINT SUBSTRING(@RebuildIndexesSQL, @StartOffset, @Length)
EXECUTE sp_executesql @RebuildIndexesSQL
DROP TABLE #FragmentedIndexes

Denken Sie auch daran, dass dieses Skript eine Weile laufen und den Zugriff auf Ihre Tabellen blockieren kann. Sofern Sie keine Enterprise-Editionen haben, kann SQL die Tabelle LOCKEN, wenn der Index neu erstellt wird. Dadurch werden alle Abfragen an diese Tabelle, die den Index verwenden, blockiert, bis die Index-Defragmentierung abgeschlossen ist. Daher wird davon abgeraten, den Indexneuaufbau während der Betriebszeiten nur während Wartungsfenstern auszuführen. Wenn Sie die Enterprise Edition ausführen, können Sie die Option ONLINE=ON verwenden, um Indizes online zu defragmentieren. Dies verbraucht mehr Speicherplatz, aber Ihre Tabellen werden während der Defragmentierung nicht blockiert/gesperrt.

Rufen Sie an, wenn Sie weitere Informationen benötigen.

AKTUALISIERT:

Wenn Sie diese Abfrage auf einer kleineren Datenbank ausführen, können Sie wahrscheinlich den Parameter „DETAILED“ im Aufruf von sys.dm_db_index_physical_stats verwenden. Dies ist wahrscheinlich eine detailliertere Untersuchung der Indizes. Die Diskussion in den Kommentaren wird auch darauf hinweisen, dass es sich bei viel größeren Tabellen wahrscheinlich lohnt, einen SAMPLED-Scan durchzuführen, da dies dazu beiträgt, die für den Index-Scan benötigte Zeit zu verkürzen.