Script for reconstruction and reindexing the fragmentado index?

Alguém pode fornecer o programa para reconstruir e indexar de novo o índice fragmentado quando 'avg_fragmentation_in_percent' excede certos limites (melhor se o cursor não for usado)?

Author: savitha, 2009-07-06

5 answers

Para reconstruir usar:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REBUILD

Ou para reorganizar a utilização:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REORGANIZE

A reorganização deve ser utilizada em fragmentações inferiores ( Para mais informações, ver https://msdn.microsoft.com/en-us/library/ms189858.aspx

 21
Author: KM., 2015-09-01 11:30:16

Aqui está o script modificado que eu tirei de http://www.foliotek.com/devblog/sql-server-optimization-with-index-rebuilding que achei útil publicar aqui. Embora use um cursor e eu sei qual é o principal problema com cursores ele pode ser facilmente convertido para uma versão sem cursor.

Está bem documentado e você pode facilmente ler através dele e modificar para as suas necessidades.

  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
 10
Author: ImanAbidi, 2016-12-22 07:06:29
Duas soluções: uma simples e outra mais avançada.
Introdução

Existem duas soluções disponíveis para si dependendo da gravidade do seu problema

Substitua pelos seus próprios valores, do seguinte modo:

  • substituir XXXMYINDEXXXX pelo nome de um índice.
  • substituir {[8] } pelo nome de uma tabela.
  • substituir XXXDATABASENAMEXXX pelo nome de uma base de dados.

Solução 1. Indexação

Reconstruir tudo índices para uma tabela em Modo Desligado

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD

Reconstruir um índice indicado para uma tabela em Modo Desligado

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD

Solução 2. Fragmentação

A fragmentação é uma questão em tabelas que regularmente têm entradas adicionadas e removidas.

Verificar a percentagem de fragmentação

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]
Fragmentação 5..30%

Se o valor da fragmentação for superior a 5%, mas inferior a 30%, então vale a pena reorganizar Index.

Reorganizar todos os índices de um quadro

ALTER INDEX ALL ON XXXMYTABLEXXX REORGANIZE

Reorganizar um índice especificado para um quadro

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REORGANIZE

Fragmentação 30%+

Se o valor de fragmentação for igual ou superior a 30%, então vale a pena reconstruir e então indexar no modo online.

Reconstruir todos os índices no modo 'online' para uma tabela

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

Reconstruir um índice indicado no modo 'online' para uma tabela

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD WITH (ONLINE = ON)
 10
Author: Knickerless-Noggins, 2017-02-02 16:30:20

Descobri que o seguinte script é muito bom em manter os índices, você pode ter isso agendado para correr todas as noites ou qualquer outro período de tempo que desejar.

Http://sqlfool.com/2011/06/index-defrag-script-v4-1/

 4
Author: Lima, 2013-03-13 16:49:29

A resposta real, em 2016 e 2017, é: Use os scripts de Ola Hallengren:

Https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html

É tudo o que qualquer um de nós precisa de saber ou preocupar-se, neste momento da nossa evolução mútua.
 2
Author: Jonesome, 2017-08-16 01:59:20