データベースは適切なインデックスを設定することで、検索レスポンスを向上させることが出来ます。しかし、運用していくうちにデータの追加や更新・削除など発生することで、検索レスポンスが遅くなることがあります。
原因はインデックスの断片化です。
断片化とは、データの物理的な順序や論理的な順序がバラバラになることです。
目次
インデックスの断面化を確認する方法
データベース内の断片化が10%以上発生しているテーブルを見る方法は以下のSQLを流してください。
SELECT QUOTENAME(S.name) AS SchemaName,
QUOTENAME(O.name) AS ObjectName,
QUOTENAME(I.name) AS IndexName,
PS.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED') AS PS
INNER JOIN sys.objects AS O
ON PS.object_id = O.object_id
INNER JOIN sys.schemas AS S
ON O.schema_id = S.schema_id
INNER JOIN sys.indexes AS I
ON PS.object_id = I.object_id
AND PS.index_id = I.index_id
WHERE avg_fragmentation_in_percent >= 10.0
AND PS.index_id > 0
ORDER BY 1,4 DESC;
インデックスの断片化を解消する方法
インデックスの断片化を解消する方法としては大きく2つあります。再構築と再構成です。
再構築はオフラインとオンラインがあります。
以下のスクリプトを流した結果、ALTER文が生成されます。そのALTER文を実行すると断片化解消してくれます。
/*-------------------------------------------
再構築・再編成が必要なインデックスリスト取得
1.断片化対象リストを取得(10%以上)
2.上記リストより30%未満のものは再編成
3.上記リストより30%以上のものは再構築
-------------------------------------------*/
DECLARE @IndexName NVARCHAR(128),
@SchemaName NVARCHAR(128),
@ObjectName NVARCHAR(128),
@avg_fragmentation_in_percent NVARCHAR(128),
@Sql NVARCHAR(128) = '';
DECLARE crDM CURSOR FOR
SELECT QUOTENAME(S.name) AS SchemaName,
QUOTENAME(O.name) AS ObjectName,
QUOTENAME(I.name) AS IndexName,
PS.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED') AS PS
INNER JOIN sys.objects AS O
ON PS.object_id = O.object_id
INNER JOIN sys.schemas AS S
ON O.schema_id = S.schema_id
INNER JOIN sys.indexes AS I
ON PS.object_id = I.object_id
AND PS.index_id = I.index_id
WHERE avg_fragmentation_in_percent >= 10.0
AND PS.index_id > 0
ORDER BY 1,4 DESC;
OPEN crDM;
FETCH NEXT FROM crDM
INTO @SchemaName,@ObjectName,@IndexName,@avg_fragmentation_in_percent;
WHILE @@FETCH_STATUS = 0
IF @avg_fragmentation_in_percent < 30.0
BEGIN
SET @Sql = N'ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @ObjectName + N' REORGANIZE';
PRINT @Sql;
FETCH NEXT FROM crDM
INTO @SchemaName,@ObjectName,@IndexName,@avg_fragmentation_in_percent;
END
ELSE
BEGIN
SET @Sql = N'ALTER INDEX ' + @IndexName + N' ON ' + @SchemaName + N'.' + @ObjectName + N' REBUILD';
PRINT @Sql;
FETCH NEXT FROM crDM
INTO @SchemaName,@ObjectName,@IndexName,@avg_fragmentation_in_percent;
END
CLOSE crDM;
DEALLOCATE crDM;
ALTER INDEX インデックス名 ON テーブル名 REBUILD
ALTER INDEX インデックス名 ON テーブル名 REBUILD WITH ONLINE = ON
ALTER INDEX インデックス名 ON テーブル名 REORGANIZE
インデックスの再構築と再構成の違い
インデックスの再構築と再構成の違いを解説します。
再構築 | 再編成 | |
トランザクション | 一つのトランザクションでインデックスを完全に再作成 | トランザクションが分散されていて、リーフページ間でインデックス行を移動させ断片化を解消 |
中断 | トランザクションはロールバックされ、断片化した状態に戻る | 既に完了しているトランザクションの結果は維持される |
領域 | 新しいインデックスと古いインデックスが2つ存在する状態になるため、それらを格納する領域が必要 | 追加の領域は基本的に必要としない |
利用制限 | 処理中はインデックスをロックするため、使用できない | 処理中でもインデックスを利用することは可能 |
まとめ:定期的なインデックスのお掃除が必要
テーブルの断片化が多くなると、みるみるシステムのレスポンスが悪くなってきます。
定期的な監視と、再編成・再構築(お掃除)が大切です。
Udemyというオンライン講座でもデータベースの学習はできます。 再生速度を早めてみたり、何度も見返すことができるのでおすすめです! 私も色々なデータベースをここで学習しています。
インデックスについて詳しく解説してくれて、理解しやすいと思います。
SQLServerのインデックスを理解して検索を速くする方法パフォーマンスチューニングについて詳しく解説しています。
【SQL Server】インデックスを使用したパフォーマンスチューニング こんにちは、KiYOです。 システムエンジニア歴20年オーバー。製造現場に特化したシステム開発を主にやってます。 新しい物好きで色々なIT技術を勉強しては、仕事に使…
コメント