2009-07-06 15 views
12

Quelqu'un peut-il fournir le script de reconstruction et de réindexation de l'index fragmenté lorsque 'avg_fragmentation_in_percent' dépasse certaines limites (mieux si le curseur n'est pas utilisé)?Script pour la reconstruction et la réindexation de l'index fragmenté?

+1

Pourquoi pas? N'importe qui peut choisir de poser une question à une question Wiki. Cela évite de perdre des points de rep. –

+0

@Savitha: quelle partie est le problème? Je ne suis pas sûr immédiatement comment vous feriez l'opération avec un curseur. Cherchez-vous un script pour détecter le pourcentage, puis reconstruire? Avez-vous vérifié le manuel pour les options? Quelles sont les déclarations disponibles? Devez-vous déterminer les détails de l'index? Y a-t-il une instruction ALTER INDEX? –

+0

@Jonathan Leffler, mais c'est une bonne question légitime avec peu de risque de descendre des voix. moins de personnes voient les wikis et/ou veulent répondre pour zéro point. –

Répondre

18

Pour reconstruire l'utilisation:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REBUILD 

ou réorganisant utilisation:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REORGANIZE 

Réorganiser doit être utilisé au plus bas (< 30%) fragmentations mais seulement la reconstruction (qui est plus lourd à la base de données) réduit la fragmentation à 0%.
Pour plus d'informations, voir https://msdn.microsoft.com/en-us/library/ms189858.aspx

6

Voici le script modifié que je pris de http://www.foliotek.com/devblog/sql-server-optimization-with-index-rebuilding que j'ai trouvé utile de poster ici. Bien qu'il utilise un curseur et je sais quel est le principal problème avec les curseurs, il peut être facilement converti en une version sans curseur.

Il est bien documenté et vous pouvez facilement le lire et le modifier selon vos besoins.

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 
5

Deux solutions: Un simple et plus avancé.

Présentation

Il y a deux solutions à votre disposition en fonction de la gravité de votre problème

remplacer par vos propres valeurs, comme suit:

  • Remplacer XXXMYINDEXXXX avec le nom de Un index.
  • Remplacez XXXMYTABLEXXX par le nom d'une table. Remplacez XXXDATABASENAMEXXX par le nom d'une base de données.

Solution 1. L'indexation

Reconstruire tous les index pour une table en mode hors ligne

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD 

Reconstruire un index spécifié pour une table en mode hors ligne

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD 

Solution 2. Fragmentation

La fragmentation est un problème dans les tables qui ont régulièrement des entrées ajoutées et supprimées.

Vérifier le pourcentage de fragmentation

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] 

Fragmentation 5..30%

Si la valeur de la fragmentation est supérieure à 5%, mais moins de 30%, alors il est une valeur d'index réorganisation.

Réorganiser tous les index pour une table

ALTER INDEX ALL ON XXXMYTABLEXXX REORGANIZE 

Réorganiser un index spécifié pour une table

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REORGANIZE 

Fragmentation 30% +

Si la valeur de la fragmentation est de 30% ou supérieur alors il vaut la peine de reconstruire ensuite les index en mode en ligne.

Reconstruire tous les index en mode en ligne pour une table

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

Reconstruire un index spécifié en mode en ligne pour une table

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