14

インデックスの断片化をチェックするためのメンテナンスジョブを追加することは可能ですか?50%を超える場合は、それらのインデックスを自動的に再構築しますか?

インデックスサイズは100MBから10GBまでさまざまです。SQL2005。

ありがとうございました。

4

4 に答える 4

24

このスクリプトを使用します。ここで使用している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スキャンを実行する価値があることも指摘します。

于 2012-05-08T08:58:49.830 に答える
3

場合によっては、一時テーブルの作成を避け、文字列を解析してSQL文字列のリストを作成することを考えていました。これを達成するための効率的な方法は次のとおりです。

USE databasename

GO

DECLARE @Queryresult NVARCHAR(4000)

SET @Queryresult=''

SELECT

  @Queryresult=@Queryresult + 'ALTER INDEX ' + QUOTENAME(i.name) + ' ON '
  + QUOTENAME('dbo') + '.'
  + QUOTENAME(OBJECT_NAME(i.OBJECT_ID)) + ' REBUILD;'

 FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'SAMPLED') ss

  INNER JOIN sys.indexes i ON i.OBJECT_ID = ss.OBJECT_ID AND i.index_id = ss.index_id

  INNER JOIN sys.objects o ON ss.object_id = o.object_id

WHERE ss.avg_fragmentation_in_percent > 50

AND ss.record_count > 0 

AND o.is_ms_shipped = 0 --Excludes any objects created as a part of SQL Server installation

AND ss.index_id > 0     --Excludes heap indexes

EXEC sp_executesql @Queryresult
于 2013-02-19T22:01:34.933 に答える
1

はい、できます。

このクエリを使用して、フラグメント化されたインデックスを取得できます。

SELECT OBJECT_NAME(i.OBJECT_ID) AS TableName,
i.name AS IndexName,
indexstats.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') indexstats
INNER JOIN sys.indexes i ON i.OBJECT_ID = indexstats.OBJECT_ID
AND i.index_id = indexstats.index_id
WHERE indexstats.avg_fragmentation_in_percent > 20

結果に基づいて、それらを再作成するコマンドを作成するだけです

すべてをストアドプロシージャでラップし、SQLServerジョブから呼び出します

参考までに、50%は非常に大きな断片化です。私はより少なく行くでしょう。

于 2012-05-08T08:52:18.290 に答える
1

sys.dm_db_index_physical_statsを使用して、インデックスの断片化に関する情報を取得できます(avg_fragmentation_in_percent列を参照)。次に、しきい値に達したときはいつでも、rebuild句を使用してインデックスの変更を行うことができます。

于 2012-05-08T08:52:28.397 に答える