2009-07-13 13 views
2

J'essaie de réduire la fragmentation dans tous les index pour une base de données exécutée sur SQL Server 2005. Actuellement, j'essaie d'utiliser ALTER INDEX en conjonction avec sp_MSforeachtable, pour l'appliquer à tous les index pour toutes les tables:Meilleure approche pour la réindexation

sp_MSforeachtable "ALTER INDEX ALL ON ? REBUILD;" 

Mais pour une raison quelconque cela ne semble pas toujours fonctionner? Si je l'essaie pour un seul index, ou tous les index pour une seule table, alors la fragmentation est nettoyée, il semble juste que lorsque je l'applique à toute la base de données, j'ai des problèmes.

Auparavant, j'aurais pu utiliser DBCC DBREINDEX mais BOL indique qu'il sera supprimé dans la prochaine version de SQL Server, donc je ne veux pas l'utiliser.

Quelqu'un peut-il me donner des conseils sur la meilleure façon d'aborder le nettoyage de tous les index d'une base de données?

Merci

Répondre

5

Si vous souhaitez automatiser complètement la maintenance de votre index SQL Server, je vous recommande vivement de consulter la procédure stockée de Michelle Ufford pour cela.

Index Defrag Script V4.1

Il est ce que je considère être le meilleur script de maintenance des index j'ai jamais lu.

L'une des meilleures caractéristiques de ce script est que vous pouvez personnaliser les valeurs de seuil que vous utilisez afin de déterminer s'il faut REBUILD ou REORGANIZE un strucutre d'index donné.

Il offre également la possibilité de limiter le nombre de cœurs de processeur utilisés par la procédure. Une excellente option si vous avez l'intention d'exécuter le script sur une base de données en production chargée. Attention: Comme pour tout code disponible sur Internet, assurez-vous de bien le tester avant de l'utiliser dans un environnement de production. Vous souhaiterez également intégrer vos propres fonctionnalités de personnalisation.

3

Vérifiez l'article et exemple de script d'accompagnement pour gérer cette tâche à Fool SQL (le site Web de Michelle Ufford):

http://sqlfool.com/2009/06/index-defrag-script-v30/

Ceci est tout à fait une belle solution pour gérer cette fois pour tous!

La recommandation de meilleure pratique consiste à réorganiser votre index si vous avez 5 à 30% de fragmentation et à ne le reconstruire que s'il comporte plus de 30% de fragmentation. Vous pouvez facilement utiliser ces seuils ou spécifier les vôtres en utilisant ce script.

Marc

0

Le plus sûr et la plus portable est de laisser tomber les indices et les ajouter à nouveau.

1

Ou vous pouvez utiliser le script reconstruire l'index de Microsoft trouvé ici http://msdn.microsoft.com/en-us/library/ms188917.aspx

-- Ensure a USE <databasename> 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 @command nvarchar(4000); 
-- 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 
INTO #work_to_do 
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED') 
WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0; 

-- Declare the cursor for the list of partitions to be processed. 
DECLARE partitions CURSOR 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; 
     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; 

-- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding. 
     IF @frag < 30.0 
      SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE'; 
     IF @frag >= 30.0 
      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 N'Executed: ' + @command; 
    END; 

-- Close and deallocate the cursor. 
CLOSE partitions; 
DEALLOCATE partitions; 

-- Drop the temporary table. 
DROP TABLE #work_to_do; 
GO 

J'utilise ce script avec SQL Server Agent pour automatiser la tâche. J'espère que cela t'aides.

Questions connexes