Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Automatizar a reconstrução do INDEX com base nos resultados da fragmentação?


Eu uso este script. Por favor, note que eu aconselho você a ler sobre o dmv que estou usando aqui, eles são uma jóia escondida no 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

Lembre-se também de que esse script pode ser executado por um tempo e bloquear o acesso às suas tabelas. A menos que você tenha edições Enterprise, o SQL pode BLOQUEAR a tabela ao reconstruir o índice. Isso bloqueará todas as consultas a essa tabela usando o índice até que a desfragmentação do índice seja concluída. Portanto, não é aconselhável executar a reconstrução do índice durante o horário de funcionamento apenas durante as janelas de manutenção. Se você estiver executando a edição corporativa, poderá usar a opção ONLINE=ON para desfragmentar índices online. Isso usará mais espaço, mas suas tabelas não serão bloqueadas/bloqueadas durante a operação de desfragmentação.

Grite se precisar de mais informações.

ATUALIZADA:

Se você estiver executando essa consulta em um banco de dados menor, provavelmente poderá usar o parâmetro 'DETAILED' na chamada para sys.dm_db_index_physical_stats. Este é provavelmente um exame mais detalhado dos índices. A discussão nos comentários também apontará que em tabelas muito maiores provavelmente vale a pena fazer uma varredura SAMPLED, pois isso ajudará a reduzir o tempo necessário para fazer a varredura de índice.