マルチサーバー環境で、すべてのデータベースのインデックス断片化レポートをコンパイルしようとしています。クエリはopenqueryコマンドを介して実行されるため、ストアドプロシージャや一時テーブルなどを使用せずに、できるだけ簡単にしたいと思います。
私はフォローがすべてのデータベースのすべてのインデックスを戻すことができることを知っています
select * from sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, 'SAMPLED')
しかし、sys.indexes、sys.objectsに結合するとすぐに、システム全体のインデックスを制限し、現在実行中のデータベースのインデックスに焦点を合わせます。
これを回避する方法はあるので、すべてのデータベースについて次の出力を取得できます。
データベース名、インデックス名、インデックスタイプ、ページ数、断片化の割合。
使用しているDMV/DMFはデータベーススコープであり、要件はサーバースコープであるため、一時テーブルを使用せずに達成することはできません。
Declare @Tbl table (ServerName varchar(128), DBName varchar(128), SchemaName varchar(128), TableName varchar (100), IndexName varchar (100), FragPercent float, IndexType tinyint, IsPrimaryKey bit);
Insert into @Tbl
exec SP_MSforeachdb @command1 =
'use [?];
select @@Servername,
DB_NAME(),
sc.name as SchemaName,
object_name (s.object_id) as TableName,
I.name,
s.avg_fragmentation_in_percent,
I.type,
I.is_primary_key
from sys.dm_db_index_physical_stats (DB_ID (), NULL, NULL, NULL, ''LIMITED'') as S
join sys.indexes as I on s.object_id = I.object_id and s.index_id = I.index_id
join sys.objects as O on s.object_id = O.object_id
join sys.schemas as sc on O.schema_id = sc.schema_id
where o.type = ''U'' and avg_fragmentation_in_percent > 20 and (I.name is not null)
ORDER BY avg_fragmentation_in_percent DESC'
select * from @Tbl
go
これらのDMVはデータベース固有であるため、現在のデータベースに関連する情報のみを表示するため、sys.indexes/sys.objectsに結合してインデックス情報を取得することはできません。
以下のクエリを使用して、必要な情報の一部を取得できます。インデックス名ではなくテーブル名が返されますが、これは適切な場合があります。
SELECT DB_NAME(database_id) AS [Database Name],
OBJECT_NAME(object_id, database_id) AS [Table Name],
[index_type_desc] AS [Index Type],
page_count AS [Number Of Pages],
[avg_fragmentation_in_percent] AS [Percentage Of Fragementation]
FROM sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, 'SAMPLED')
それ以外の場合は、SQL Serverにプロシージャを展開して、インデックス名の情報をフェッチする必要があります。
最初のパラメーターは、sys.databasesテーブルにあるデータベースIDです。
以下のクエリは、提案に役立つ場合があります。
--SELECT * FROM sys.databases
DECLARE @dbid int = 9
SELECT dbschemas.[name] as 'Schema',
dbtables.[name] as 'Table',
dbindexes.[name] as 'Index',
indexstats.avg_fragmentation_in_percent,
indexstats.page_count,
CASE WHEN indexstats.page_count <= 100 OR indexstats.avg_fragmentation_in_percent < 10 THEN '--Do nothing. It''s good'
WHEN indexstats.avg_fragmentation_in_percent BETWEEN 10 AND 30 THEN 'ALTER INDEX '+dbindexes.[name]+' ON '+dbschemas.[name]+'.'+dbtables.[name]+' REORGANIZE;'
ELSE 'ALTER INDEX '+dbindexes.[name]+' ON '+dbschemas.[name]+'.'+dbtables.[name]+' REBUILD;'
END
FROM sys.dm_db_index_physical_stats (@dbid, NULL, NULL, NULL, NULL) AS indexstats
JOIN sys.tables dbtables ON dbtables.[object_id] = indexstats.[object_id]
JOIN sys.schemas dbschemas ON dbtables.[schema_id] = dbschemas.[schema_id]
JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id] AND indexstats.index_id = dbindexes.index_id
WHERE indexstats.database_id = @dbid
ORDER BY indexstats.avg_fragmentation_in_percent DESC