Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Automatizzare la ricostruzione di INDEX in base ai risultati della frammentazione?

Uso questo script. Tieni presente che ti consiglierei di leggere il dmv che sto usando qui sono una gemma nascosta 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

Tieni inoltre presente che questo script può essere eseguito per un po' e bloccare l'accesso alle tue tabelle. A meno che non si disponga di edizioni Enterprise, SQL può BLOCCARE la tabella durante la ricostruzione dell'indice. Ciò bloccherà tutte le query su quella tabella utilizzando l'indice fino al termine della deframmentazione dell'indice. Pertanto non è consigliabile eseguire la ricostruzione dell'indice durante le ore di funzionamento solo durante le finestre di manutenzione. Se stai utilizzando l'edizione aziendale, puoi utilizzare l'opzione ONLINE=ON per deframmentare gli indici online. Questo utilizzerà più spazio ma le tue tabelle non verranno bloccate/bloccate durante l'operazione di deframmentazione.

Grida se hai bisogno di maggiori informazioni.

AGGIORNATO:

Se stai eseguendo questa query su un database più piccolo, probabilmente puoi utilizzare il parametro 'DETAILED' nella chiamata a sys.dm_db_index_physical_stats. Questo è probabilmente un esame più dettagliato degli indici. La discussione nei commenti sottolineerà anche che su tabelle molto più grandi probabilmente vale la pena eseguire una scansione SAMPLED in quanto ciò contribuirà a ridurre il tempo necessario per eseguire la scansione dell'indice.