SQL Server : Index Fragmentation

Index Fragmentation

Fragmentation can happen within a page (Internal) or between pages (External). SQL Server DBAs seem obsessed by rebuilding indexes.

You will probably detect and fix index fragmentation as part of your maintenance plan, but this article focuses on manually identifying and fixing index fragmentation.

Detecting Index Fragmentation

Note. Small indexes will often show large amounts of fragmentation, which might actually get worse after index rebuilds. Indexes with a page_count of less than ~1000 pages are unlikely to suffer from performance issues caused by fragmentation. Microsoft recommend avoiding rebuilds on indexes on indexes smaller than 1000 pages (here). Keep this in mind when looking at the information below.

The following query gives you the statistics for all indexes in every database. One of the columns produced is called avg_fragmentation_in_percent, which gives the information we are looking for.

SELECT *
FROM   sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, NULL)
ORDER BY avg_fragmentation_in_percent DESC

You can narrow this down to a specific database using the first parameter. We have also returned the object name associated with the object_id.

USE MyDatabase
GO

SELECT object_name(object_id) AS object_name, *
FROM   sys.dm_db_index_physical_stats(DB_ID('MyDatabase'), NULL, NULL, NULL, NULL)
ORDER BY avg_fragmentation_in_percent DESC

We can now see which indexes are suffering from fragmentation.

Fixing Index Fragmentation

The following commands can be used to fix index fragmentation for all indexes on a specified table. A rebuild removes both internal and external fragmentation.

USE MyDatabase
GO

ALTER INDEX ALL ON dbo.MyTable
  REBUILD WITH (ONLINE = ON)

The WITH option of “ONLINE = ON” means transactions can continue against the object while the processing happens. Without it, the table would be locked for the duration of the operation.

A rebuild could result in the index being bigger as the index is rebuilt using the fill factor. If the fill factor is the default (100%), no space is left for future changes, which could result in a page split on the next insert. If you specify a fill factor, leaving some space for future updates you can reduce this fragmentation, but the index will be bigger. The necessity for a non-default fill factor depends on the nature of the work done against the table. The following example does a rebuild, specifying an 80% fill factor.

USE MyDatabase
GO

ALTER INDEX ALL ON dbo.MyTable
  REBUILD WITH (ONLINE = ON, FILLFACTOR = 80)

An alternative is to reorg the index, which shuffles the pages, only fixing external page fragmentation.

USE MyDatabase
GO

ALTER INDEX ALL ON dbo.MyTable
  REORG WITH (ONLINE = ON)

For more information see: