41

SQL Server データベースを改善するための SSW ルールには、完全なデータベース メンテナンス プランの例があります: SSW。この例では、インデックスの再編成、インデックスの再構築、統計の更新の両方を実行しています。これには何か意味がありますか?Reorganize Index は Rebuild Index の高速ですが効果の低いバージョンだと思いましたか? また、インデックスの再構築により、統計も自動的に更新されます (少なくともクラスター化されたインデックスでは)。

4

9 に答える 9

32

再編成と再構築は別物です。

再編成: インデックスのデフラグです。既存のインデックスを取得し、既存のページを最適化します。ただし、ページが連続していない場合は、以前のままです。ページの内容のみが変更されます。

再構築: 実際には、インデックスを削除し、最初から再構築します。これは、最適化された連続したページを含む、まったく新しいインデックスを取得することを意味します。

さらに、再構築を使用すると、パーティションまたはファイル グループを変更できますが、再編成を使用すると、インデックス全体だけでなく、インデックスの 1 つのパーティションのみを最適化できます。

統計の更新は、クラスター化インデックスでは自動ですが、非クラスター化インデックスでは自動ではありません。

于 2008-08-11T07:44:54.637 に答える
25

インデックスのメンテナンスを検討する前に、次の 2 つの主な質問に答えることが重要です。

  1. 断片化の程度は?
  2. 適切な行動は何ですか?再編成か再構築か?

この記事http://solutioncenter.apexsql.com/why-when-and-how-to-rebuild-and-reorganize-sql-server-indexes/で説明されているように、インデックスの再構築を実行する必要があるかどうかを判断するのに役立ちます。インデックスの再編成については、次の点をご理解ください。

  • インデックスの再編成は、SQL Server が既存のインデックスを調べてクリーンアップするプロセスです。インデックスの再構築は、インデックスが削除された後、まったく新しい構造でゼロから再作成され、積み上げられたフラグメントや空のページがすべて解放されるという負荷の高いプロセスです。

  • インデックスの再編成は、影響を受けるテーブルやビューをロックアウトせずにシステムの状態をそのままにしておく純粋なクリーンアップ操作ですが、再構築プロセスでは、影響を受けるテーブルが再構築期間全体にわたってロックされます。いくつかの環境。これを念頭に置いて、インデックスの再構築が「より強力な」ソリューションを備えたプロセスであることは明らかですが、影響を受けるインデックス付きテーブルが長時間ロックされる可能性があるという代償が伴います。

一方、インデックスの再編成は「軽量」のプロセスであり、効果の低い方法で断片化を解決します。クリーンなインデックスは、完全にゼロから作成された新しいインデックスに常に次ぐためです。ただし、インデックスの再編成は、操作中に影響を受けるインデックス付きテーブルをロックしないため、効率の観点からははるかに優れています。

上記の記事では、SSMS、T-SQL (テーブル内のインデックスを再編成/再構築するため)、および ApexSQL Backup と呼ばれるサードパーティ ツールを使用してインデックスを再編成および再構築する方法についても説明しています。

于 2016-01-27T10:39:28.347 に答える
22

同じインデックスに対して a を実行してからREORGANIZEaを実行しても意味がありません。REBUILDREORGANIZEREBUILD

それよりも悪いのは、SSW のメンテナンス プラン ダイアグラムでは、SHRINKスペースを解放する方法の副作用としてインデックスを断片化する最初の処理を実行することです。次に、操作REBUILD中の作業領域として、データベース ファイルにより多くの領域が再度割り当てられますREBUILD

  • REORGANIZE余分な作業スペースをほとんど使用せずに、クラスター化または非クラスター化インデックス ページのリーフ ページをページごとに最適化するオンライン操作です。

  • REBUILDEnterprise エディションではオンライン操作であり、他のエディションではオフライン操作であり、インデックス サイズと同じ余分な作業領域を再び使用します。インデックスの新しいコピーを作成してから古いものを削除することで、断片化を解消します。デフォルトでは、この操作の一部として統計が再計算されますが、これは無効にすることができます。

詳細については、インデックスの再編成と再構築を参照してください。

SHRINKオプションを除いて使用しないでくださいTRUNCATEONLY。それでもファイルが再び大きくなる場合は、それが必要かどうかをよく考えてください。

sqlservercentral_SHRINKFILE

于 2012-02-24T01:49:11.527 に答える
10

インデックスの再編成を行うときに、インデックスが 2 つ以上の物理ファイルにまたがっている場合、データはデータ ファイル内でのみ最適化されます。ページは、あるデータ ファイルから別のデータ ファイルに移動されません。

インデックスが単一のファイルにある場合、reorg と reindex の最終結果は同じになります。

インデックスの断片化の程度によっては、reorg が高速になる場合もあれば、reindex が高速になる場合もあります。インデックスの断片化が少ないほど再編成は高速になり、断片化が進むほど再編成は遅くなりますが、再インデックスは高速になります。

于 2008-09-03T06:36:13.970 に答える
8

ビリさんの言うとおりです。データベース全体のインデックスを再作成する方法は次のとおりです。

EXEC [sp_MSforeachtable] @command1="RAISERROR('DBCC DBREINDEX(''?'') ...',10,1) WITH NOWAIT DBCC DBREINDEX('?')"
于 2008-08-11T09:17:41.640 に答える
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

この SP を毎週実行する 1 つのジョブを作成します。

于 2013-09-25T11:37:54.327 に答える
3

さらに良いのは:

EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REINDEX'

また

EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REORGANIZE'
于 2013-06-26T05:56:20.200 に答える
0

私の 2 セント... この方法は、tech net で概説されている仕様に従います: http://technet.microsoft.com/en-us/library/ms189858(v=sql.105).aspx

USE [MyDbName]
GO

SET ANSI_NULLS OFF
GO

SET QUOTED_IDENTIFIER OFF
GO

CREATE PROCEDURE [maintenance].[IndexFragmentationCleanup]
AS
DECLARE @reIndexRequest VARCHAR(1000)

DECLARE reIndexList CURSOR
FOR
SELECT INDEX_PROCESS
FROM (
    SELECT CASE 
            WHEN avg_fragmentation_in_percent BETWEEN 5
                    AND 30
                THEN 'ALTER INDEX [' + i.NAME + '] ON [' + t.NAME + '] REORGANIZE;'
            WHEN avg_fragmentation_in_percent > 30
                THEN 'ALTER INDEX [' + i.NAME + '] ON [' + t.NAME + '] REBUILD with(ONLINE=ON);'
            END AS INDEX_PROCESS
        ,avg_fragmentation_in_percent
        ,t.NAME
    FROM sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, NULL) AS a
    INNER JOIN sys.indexes AS i ON a.object_id = i.object_id
        AND a.index_id = i.index_id
    INNER JOIN sys.tables t ON t.object_id = i.object_id
    WHERE i.NAME IS NOT NULL
    ) PROCESS
WHERE PROCESS.INDEX_PROCESS IS NOT NULL
ORDER BY avg_fragmentation_in_percent DESC

OPEN reIndexList

FETCH NEXT
FROM reIndexList
INTO @reIndexRequest

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY

        PRINT @reIndexRequest;

        EXEC (@reIndexRequest);

    END TRY

    BEGIN CATCH
        DECLARE @ErrorMessage NVARCHAR(4000);
        DECLARE @ErrorSeverity INT;
        DECLARE @ErrorState INT;

        SELECT @ErrorMessage = 'UNABLE TO CLEAN UP INDEX WITH: ' + @reIndexRequest + ': MESSAGE GIVEN: ' + ERROR_MESSAGE()
            ,@ErrorSeverity = 9 
            ,@ErrorState = ERROR_STATE();

    END CATCH;

    FETCH NEXT
    FROM reIndexList
    INTO @reIndexRequest
END

CLOSE reIndexList;

DEALLOCATE reIndexList;

RETURN 0

GO
于 2014-10-03T17:52:09.930 に答える