2009-07-06 118 views
12

任何人都可以在'avg_fragmentation_in_percent'超過特定限制時更好地重建和重新索引碎片索引(如果不使用遊標,這個腳本會更好嗎?)?重建和重新索引分段索引的腳本?

+1

爲什麼不呢?任何人都可以選擇提出他們問維基問題的任何問題。它避免了丟失重要點。 – 2009-07-06 13:09:46

回答

18

要重建使用:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REBUILD 

或重組用途:

ALTER INDEX __NAME_OF_INDEX__ ON __NAME_OF_TABLE__ REORGANIZE 

改組應在較低(< 30%)分片使用,但僅重建(這是較重到數據庫)將碎片率降至0%。
有關更多信息,請參閱https://msdn.microsoft.com/en-us/library/ms189858.aspx

6

下面是修改腳本,我從http://www.foliotek.com/devblog/sql-server-optimization-with-index-rebuilding,我發現在這裏發表了有益的。 雖然它使用遊標,我知道遊標的主要問題是什麼,它可以很容易地轉換爲無遊標的版本。

它有很好的文檔記錄,您可以通過它輕鬆閱讀並修改您的需求。

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

兩個解決方案:一個簡單的和一個更加先進。

介紹

有提供給您兩種解決方案取決於您的問題的嚴重性

替換爲自己的值,如下所示:

  • 替換XXXMYINDEXXXX用的名字索引。
  • 用表名稱替換XXXMYTABLEXXX
  • 用數據庫的名稱替換XXXDATABASENAMEXXX

溶液1索引

重建爲一個表中所有索引在離線模式下

ALTER INDEX ALL ON XXXMYTABLEXXX REBUILD 

在離線模式下重建一個指定的索引爲表

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REBUILD 

解決方案2.碎片化

碎片是表格中的問題,表格中經常會添加和刪除條目。

檢查碎片百分比

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] 

碎片5..30%

如果碎片值大於5%但低於30%,那麼就值得重新組織索引。

重新組織的所有索引爲表

ALTER INDEX ALL ON XXXMYTABLEXXX REORGANIZE 

重新組織一項所述的表

ALTER INDEX XXXMYINDEXXXX ON XXXMYTABLEXXX REORGANIZE 

碎片30%+

如果碎片值爲30%指定索引或更高,那麼值得重建,然後在線模式索引。

重建在聯機模式下的所有索引的表

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

重建一個指定的索引在聯機模式下爲表

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