2009-07-13 71 views
2

我試圖減少在SQL Server 2005上運行的數據庫的所有索引中的碎片。 當前我正在嘗試將ALTER INDEX與sp_MSforeachtable結合使用,以將其應用於所有索引所有表格:Reindexing的最佳方法

sp_MSforeachtable "ALTER INDEX ALL ON ? REBUILD;" 

但由於某些原因,這似乎並不總是奏效? 如果我嘗試使用單個索引或單個表的所有索引,那麼碎片就會被清除,這似乎是我將它應用到整個數據庫時出現問題的時候。

此前我可能使用過DBCC DBREINDEX,但BOL聲明它會在下一版本的SQL Server中刪除,所以我不想使用它。

任何人都可以給我任何建議的最佳方法來解決清理數據庫中的所有索引?

感謝

回答

5

如果你想完全自動化你的SQL Server索引維護,那麼我嚴重建議你檢查一下Michelle Ufford的存儲過程。

Index Defrag Script V4.1

它是什麼,我認爲是最好的索引維護腳本我讀過。

有關此腳本的最佳功能之一是,您可以自定義您使用的閾值,以確定是重建還是重組給定的索引結構。

它還提供了限制該過程使用的CPU內核數量的選項。如果您打算在繁忙的實時生產數據庫上運行腳本,這是一個很好的選擇。

警告:與所有可用的互聯網代碼一樣,確保在生產環境中使用之前對其進行徹底測試。你也很可能想要納入你自己的定製和功能。

3

請查看文章和附帶的示例腳本來處理在SQL愚人節這個任務(米歇爾Ufford的網站):

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

這是一個相當不錯的解決方案,一旦處理這對全部!

最佳實踐建議是,如果您有5-30%的碎片,請重新組織您的索引,並且只有碎片超過30%時才重建。您可以輕鬆使用這些閾值或使用此腳本指定您自己的閾值。

馬克

0

最安全和最簡單的方法是刪除索引並重新添加。

1

或者你也可以使用微軟的索引重建腳本這裏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 

發現我一起使用這個腳本與SQL Server代理自動執行任務。希望這可以幫助。