Sql-server – Query to see Index Fragmentation on all databases without using SP or temp tables

fragmentationindexsql serversql-server-2008sql-server-2012

I am trying to compile a index fragmentation report on all databases, in a multi-server environment. The query will be executed via an openquery command, so I would like to make it as simple as possible, without using stored procedures, temporary tables, etc.

I am aware the follow can bring back all indexes on all databases

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

but as soon as we join it to sys.indexes, sys.objects, we restrict out system wide indexes and rather focus on indexes in the currently executing database.

Is there a way around this, so I can get the following output for all databases:

Database Name, Index Name, Index Type, Number of Pages, Percentage of Fragmentation.

Best Answer

It's not possible to achieve without using temp table as the DMVs/DMFs that we are using are database scoped and requirement is server scoped, and i don't see any difficulties or complication using temp table as follows:

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