在Sql Server维护计划中重新组织索引与重建索引

BTB*_*BTB 36 sql-server reorganize rebuild maintenance-plan

在更好的SQL Server数据库的SSW规则中,有一个完整的数据库维护计划的例子:SSW.在示例中,它们既运行重组索引,又运行重建索引,然后运行更新统计信息.这有什么意义吗?我认为重组指数是一个快速但不太有效的重建指数版本?并且索引重建也会自动更新统计信息(至少在聚簇索引上).

Bir*_*iri 31

重组和重建是不同的事情.

重组:它是索引的碎片整理.获取现有索引并对现有页面进行碎片整理.但是,如果页面不是连续的,它们就像以前一样.只有页面内容正在发生变化.

重建:实际上它会删除索引并从头开始重建它.这意味着您将获得一个全新的索引,包含碎片整理和连续的页面.

此外,通过重建,您可以更改分区或文件组,但通过重新组织,您不仅可以对整个索引进行碎片整理,还可以仅对索引的一个分区进行碎片整理.

更新统计信息在聚簇索引上是自动的,但在非聚簇索引上则不是.

  • 实际上,根据联机丛书http://msdn.microsoft.com/en-us/library/ms189858.aspx,Reorg DOES重新组织页面以使它们在物理上连续.下面是确切的引用:"重新组织索引通过对叶级别页面进行物理重新排序以匹配叶子节点的逻辑顺序(从左到右)来对表和视图上的聚簇索引和非聚簇索引的叶级别进行碎片整理.使页面按顺序排列提高索引扫描性能.索引在分配给它的现有页面内重新组织;不分配新页面." (2认同)
  • @ MichaelK.Campbell:你的引言有点脱离背景.虽然ReOrg将重新排序页面,但它只能在中间级节点指向它们的最低级别重新排序它们.在ReOrg之后,整个索引中的所有页面都不保证是连续的.这是一个更好的解释:http://dba.stackexchange.com/a/36817/6816 (2认同)

小智 24

在考虑维护索引之前,回答两个主要问题很重要:

  1. 碎片的程度是多少?
  2. 什么是适当的行动?重组还是重建?

如本文所述http://solutioncenter.apexsql.com/why-when-and-how-to-rebuild-and-reorganize-sql-server-indexes/,并帮助您确定是否应执行索引重建或指数重组,请理解以下内容:

  • 索引重组是SQL Server通过现有索引并清除它的过程.索引重建是一个重要的过程,其中索引被删除,然后从头开始重新创建,具有全新的结构,没有所有堆积的碎片和空白页面.

  • 虽然索引重组是一个纯清理操作,它会使系统状态保持原样,而不会锁定受影响的表和视图,但重建过程会在整个重建期间锁定受影响的表,这可能会导致长时间的停机时间无法接受.一些环境.考虑到这一点,很明显索引重建是一个具有"更强"解决方案的过程,但它带来了价格 - 可能对受影响的索引表进行长锁定.

另一方面,索引重组是一个"轻量级"流程,它将以一种不太有效的方式解决碎片问题 - 因为清理后的索引总是第二个完全从头开始制作的新索引.但是从效率的角度来看,重组索引要好得多,因为它在操作过程中不会锁定受影响的索引表.

上面提到的文章还解释了如何使用SSMS,T-SQL(重组/重建表中的索引)和名为ApexSQL Backup的第三方工具重新组织和重建索引.


小智 16

在相同的索引上执行a REORGANIZE然后执行a REBUILD是没有意义的,因为通过执行此操作REORGANIZE会丢失任何更改REBUILD.

更糟糕的是,在SSW的维护计划图中,它执行SHRINK第一个,它将索引分段为释放空间的方式的副作用.然后REBUILDREBUILD操作期间再次为数据库文件分配更多空间作为工作空间.

  • REORGANIZE 是一个在线操作,使用很少的额外工作空间逐页对聚簇或非聚集索引页中的叶页进行碎片整理.

  • REBUILD是企业版的在线操作,在其他版本中脱机,并且使用与索引大小一样多的额外工作空间.它创建索引的新副本,然后删除旧索引,从而摆脱碎片.默认情况下,统计信息将作为此操作的一部分重新计算,但可以禁用.

有关详细信息,请参阅重组和重建索引.

不要使用SHRINK除了TRUNCATEONLY选项,即使然后如果文件将再次增长,那么你应该认真考虑是否有必要:

sqlservercentral_SHRINKFILE

  • 令人惊讶的是,有多少在线“权威”是完全错误和误导的,即建议您应该对数据库进行收缩! (2认同)

mrd*_*nny 10

在对索引进行重组时,如果索引分布在两个或多个物理文件中,则数据将仅在数据文件中进行碎片整理.页面不会从一个数据文件移动到另一个数据文件.

当索引在单个文件中时,reorg和reindex将具有相同的最终结果.

有时重组会更快,有时重新索引会更快,具体取决于索引的碎片程度.索引碎片越少,重组越快,重组越慢,重组越慢,但重新索引的速度越快.


Gat*_*ler 8

正是Biri所说的.以下是重新索引整个数据库的方法:

EXEC [sp_MSforeachtable] @command1="RAISERROR('DBCC DBREINDEX(''?'') ...',10,1) WITH NOWAIT DBCC DBREINDEX('?')"
Run Code Online (Sandbox Code Playgroud)


Ard*_*oli 5

我用这个SP

CREATE PROCEDURE dbo.[IndexRebuild]
AS 
DECLARE @TableName NVARCHAR(500);
DECLARE @SQLIndex NVARCHAR(MAX);
DECLARE @RowCount INT;
DECLARE @Counter INT;

DECLARE @IndexAnalysis TABLE
    (
      AnalysisID INT IDENTITY(1, 1)
                     NOT NULL
                     PRIMARY KEY ,
      TableName NVARCHAR(500) ,
      SQLText NVARCHAR(MAX) ,
      IndexDepth INT ,
      AvgFragmentationInPercent FLOAT ,
      FragmentCount BIGINT ,
      AvgFragmentSizeInPages FLOAT ,
      PageCount BIGINT
    )

BEGIN
    INSERT  INTO @IndexAnalysis
            SELECT  [objects].name ,
                    'ALTER INDEX [' + [indexes].name + '] ON ['
                    + [schemas].name + '].[' + [objects].name + '] '
                    + ( CASE WHEN (   [dm_db_index_physical_stats].avg_fragmentation_in_percent >= 20
                                    AND [dm_db_index_physical_stats].avg_fragmentation_in_percent < 40
                                  ) THEN 'REORGANIZE'
                             WHEN [dm_db_index_physical_stats].avg_fragmentation_in_percent > = 40
                             THEN 'REBUILD'
                        END ) AS zSQL ,
                    [dm_db_index_physical_stats].index_depth ,
                    [dm_db_index_physical_stats].avg_fragmentation_in_percent ,
                    [dm_db_index_physical_stats].fragment_count ,
                    [dm_db_index_physical_stats].avg_fragment_size_in_pages ,
                    [dm_db_index_physical_stats].page_count
            FROM    [sys].[dm_db_index_physical_stats](DB_ID(), NULL, NULL,
                                                       NULL, 'LIMITED') AS   [dm_db_index_physical_stats]
                    INNER JOIN [sys].[objects] AS [objects] ON (   [dm_db_index_physical_stats].[object_id] = [objects].[object_id] )
                    INNER JOIN [sys].[schemas] AS [schemas] ON ( [objects].[schema_id]  = [schemas].[schema_id] )
                    INNER JOIN [sys].[indexes] AS [indexes] ON (  [dm_db_index_physical_stats].[object_id] = [indexes].[object_id]
                                                          AND  [dm_db_index_physical_stats].index_id = [indexes].index_id
                                                          )
            WHERE   index_type_desc <> 'HEAP'
                    AND [dm_db_index_physical_stats].avg_fragmentation_in_percent > 20
END

SELECT  @RowCount = COUNT(AnalysisID)
FROM    @IndexAnalysis

SET @Counter = 1
WHILE @Counter <= @RowCount 
    BEGIN

        SELECT  @SQLIndex = SQLText
        FROM    @IndexAnalysis
        WHERE   AnalysisID = @Counter

        EXECUTE sp_executesql @SQLIndex

        SET @Counter = @Counter + 1

    END
 GO
Run Code Online (Sandbox Code Playgroud)

并创建一个每周执行此SP的作业.