web-dev-qa-db-ja.com

SPまたは一時テーブルを使用せずにすべてのデータベースのインデックスの断片化を確認するためのクエリ

マルチサーバー環境で、すべてのデータベースのインデックス断片化レポートをコンパイルしようとしています。クエリはopenqueryコマンドを介して実行されるため、ストアドプロシージャや一時テーブルなどを使用せずに、できるだけ簡単にしたいと思います。

私はフォローがすべてのデータベースのすべてのインデックスを戻すことができることを知っています

select * from sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, 'SAMPLED')

しかし、sys.indexes、sys.objectsに結合するとすぐに、システム全体のインデックスを制限し、現在実行中のデータベースのインデックスに焦点を合わせます。

これを回避する方法はあるので、すべてのデータベースについて次の出力を取得できます。

データベース名、インデックス名、インデックスタイプ、ページ数、断片化の割合。

1
Asher

使用している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
1
Shekar Kola

これらの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にプロシージャを展開して、インデックス名の情報をフェッチする必要があります。

0
HandyD

最初のパラメーターは、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
0
Dat Nguyen