2009-07-06 178 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)