script reconstruir index ejemplo dm_db_index_physical_stats desfragmentar sql-server indexing fragmentation

sql-server - reconstruir - sql server reindex



¿Script para reconstruir y reindexar el índice fragmentado? (5)

Dos soluciones: una simple y otra más avanzada.

Introducción

Hay dos soluciones disponibles para usted dependiendo de la gravedad de su problema

Reemplace con sus propios valores, de la siguiente manera:

  • Reemplace XXXMYINDEXXXX con el nombre de un índice.
  • Reemplace XXXMYTABLEXXX con el nombre de una tabla.
  • Reemplace XXXDATABASENAMEXXX con el nombre de una base de datos.

Solución 1. Indexación

Reconstruir todos los índices de una tabla en modo fuera de línea

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD

Reconstruir un índice especificado para una tabla en modo fuera de línea

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD

Solución 2. Fragmentación.

La fragmentación es un problema en las tablas que regularmente tienen entradas agregadas y eliminadas.

Ver porcentaje de fragmentación

SELECT ips.[index_id] , idx.[name] , ips.[avg_fragmentation_in_percent] FROM sys.dm_db_index_physical_stats(DB_ID(N''XXXMYDATABASEXXX''), OBJECT_ID(N''XXXMYTABLEXXX''), NULL, NULL, NULL) AS [ips] INNER JOIN sys.indexes AS [idx] ON [ips].[object_id] = [idx].[object_id] AND [ips].[index_id] = [idx].[index_id]

Fragmentación 5..30%

Si el valor de fragmentación es mayor que 5%, pero menor que 30%, entonces vale la pena reorganizar los índices.

Reorganizar todos los índices de una tabla.

ALTER INDEX ALL ON XXXMYTABLEXXX REORGANIZE

Reorganizar un índice especificado para una tabla

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REORGANIZE

Fragmentación 30% +

Si el valor de fragmentación es del 30% o mayor, entonces vale la pena reconstruir los índices en el modo en línea.

Reconstruir todos los índices en modo en línea para una tabla

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD WITH (ONLINE = ON)

Reconstruir un índice especificado en modo en línea para una tabla

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD WITH (ONLINE = ON)

¿Puede alguien proporcionar el script para reconstruir y volver a indexar el índice fragmentado cuando ''avg_fragmentation_in_percent'' excede ciertos límites (mejor si no se usa el cursor)?


Aquí está la secuencia de comandos modificada que tomé de http://www.foliotek.com/devblog/sql-server-optimization-with-index-rebuilding que encontré útil para publicar aquí. Aunque utiliza un cursor y sé cuál es el problema principal con los cursores, se puede convertir fácilmente en una versión sin cursor.

Está bien documentado y puede leerlo fácilmente y modificarlo según sus necesidades.

IF OBJECT_ID(''tempdb..#work_to_do'') IS NOT NULL DROP TABLE tempdb..#work_to_do BEGIN TRY --BEGIN TRAN use yourdbname -- Ensure a USE statement has been executed first. 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 = 50 DECLARE @fragmentation_minimum FLOAT SET @fragmentation_minimum = 30.0 -- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function -- and convert object and index IDs to names. 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; IF CURSOR_STATUS(''global'', ''partitions'') >= -1 BEGIN PRINT ''partitions CURSOR DELETED'' ; CLOSE partitions DEALLOCATE partitions END -- Declare the cursor for the list of partitions to be processed. DECLARE partitions CURSOR LOCAL 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 + N'' REBUILD''; IF @partitioncount > 1 SET @command = @command + N'' PARTITION='' + CAST(@partitionnum AS NVARCHAR(10)); EXEC (@command); --print (@command); //uncomment for testing PRINT N''Rebuilding 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:'' + ERROR_MESSAGE() END CATCH




Para reconstruir el uso:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REBUILD

o para reorganizar el uso:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REORGANIZE

La reorganización se debe utilizar en fragmentaciones inferiores (<30%), pero solo la reconstrucción (que es más pesada para la base de datos) reduce la fragmentación al 0%.
Para obtener más información, consulte https://msdn.microsoft.com/en-us/library/ms189858.aspx