私はこのスクリプトを使用します。ここで使用している dmv について読むことをお勧めします。それらは SQL2005+ の隠された宝石です。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
CREATE TABLE #FragmentedIndexes
(
DatabaseName SYSNAME
, SchemaName SYSNAME
, TableName SYSNAME
, IndexName SYSNAME
, [Fragmentation%] FLOAT
)
INSERT INTO #FragmentedIndexes
SELECT
DB_NAME(DB_ID()) AS DatabaseName
, ss.name AS SchemaName
, OBJECT_NAME (s.object_id) AS TableName
, i.name AS IndexName
, s.avg_fragmentation_in_percent AS [Fragmentation%]
FROM sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL, 'SAMPLED') s
INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas ss ON ss.[schema_id] = o.[schema_id]
WHERE s.database_id = DB_ID()
AND i.index_id != 0
AND s.record_count > 0
AND o.is_ms_shipped = 0
DECLARE @RebuildIndexesSQL NVARCHAR(MAX)
SET @RebuildIndexesSQL = ''
SELECT
@RebuildIndexesSQL = @RebuildIndexesSQL +
CASE
WHEN [Fragmentation%] > 30
THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
+ QUOTENAME(SchemaName) + '.'
+ QUOTENAME(TableName) + ' REBUILD;'
WHEN [Fragmentation%] > 10
THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
+ QUOTENAME(SchemaName) + '.'
+ QUOTENAME(TableName) + ' REORGANIZE;'
END
FROM #FragmentedIndexes
WHERE [Fragmentation%] > 10
DECLARE @StartOffset INT
DECLARE @Length INT
SET @StartOffset = 0
SET @Length = 4000
WHILE (@StartOffset < LEN(@RebuildIndexesSQL))
BEGIN
PRINT SUBSTRING(@RebuildIndexesSQL, @StartOffset, @Length)
SET @StartOffset = @StartOffset + @Length
END
PRINT SUBSTRING(@RebuildIndexesSQL, @StartOffset, @Length)
EXECUTE sp_executesql @RebuildIndexesSQL
DROP TABLE #FragmentedIndexes
また、このスクリプトはしばらく実行され、テーブルへのアクセスがブロックされる可能性があることに注意してください。 Enterprise エディションを使用していない限り、SQL はインデックスを再構築するときにテーブルをロックできます。これにより、インデックスのデフラグが完了するまで、インデックスを使用してそのテーブルへのすべてのクエリがブロックされます。したがって、運用時間中にインデックスの再構築を実行するのは、メンテナンス期間中のみにすることはお勧めしません。 Enterprise Edition を実行している場合は、ONLINE=ON オプションを使用してインデックスをオンラインで最適化できます。これにより、より多くのスペースが使用されますが、最適化操作中にテーブルがブロック/ロックされることはありません。
さらに情報が必要な場合は声をかけてください。
更新:
小規模なデータベースでこのクエリを実行している場合は、おそらく sys.dm_db_index_physical_stats への呼び出しで「DETAILED」パラメーターを使用できます。これはおそらく、インデックスのより詳細な調査です。コメント内の議論では、インデックス スキャンに必要な時間を短縮するのに役立つため、はるかに大きなテーブルではおそらく SAMPLED スキャンを実行する価値があることも指摘されています。