In the previous article (see Index Fragmentation), I described how to detect index fragmentation using a script that utilizes system tables. According to Microsoft’s recommendations, we should reorganize (REORGANIZE) indexes with fragmentation between 5 – 30% and rebuild (REBUILD) indexes with fragmentation above 30%. We will use the script from the previous article and create an automatic script. The SQL index fragmentation fix performed in this way is simple and fast.

Automatic Index Repair Using a Script in SQL Server

The script works as follows:

  • We create a preparation table @TablesToMaintenance.
  • In the table, we prepare indexes to be repaired, i.e., all indexes with fragmentation greater than 5%. We also add the operation to be performed (REBUILD vs. REORGANIZE).
  • In the end, using a cursor, we perform the required operation sequentially on each index (executing dynamic SQL queries).

DECLARE @TablesToMaintenance AS TABLE
(
  DB_Schema VARCHAR(255),
  DB_Table VARCHAR(255),
  DB_Index VARCHAR(255),
  INDEX_Fragmentation FLOAT,
  OperationToMaintenance VARCHAR(255)
)
-----------Příprava fragmentovaných tabulek----
INSERT INTO @TablesToMaintenance(
  DB_Schema,
  DB_Table,
  DB_Index,
  INDEX_Fragmentation,
  OperationToMaintenance
)
SELECT
   sch.name AS DB_Schema,
   obj.name AS DB_Table,
   ind.name AS DB_Index,
   stat.avg_fragmentation_in_percent AS INDEX_Fragmentation,
   CASE
     WHEN avg_fragmentation_in_percent between 5 and 30 THEN 'REORGANIZE'
     WHEN avg_fragmentation_in_percent >30 THEN 'REBUILD'
   END AS OperationToMaintenance
FROM
   sys.objects obj
   LEFT JOIN sys.schemas sch
     ON obj.schema_id= sch.schema_id
   LEFT JOIN sys.indexes ind
     ON obj.object_id=ind.object_id
   LEFT JOIN sys.dm_db_index_physical_stats (db_id(), NULL, NULL, NULL, 'LIMITED') AS stat
     ON ind.object_id=stat.object_id
     AND ind.index_id=stat.index_id
WHERE
   obj.type='U'
   AND ind.index_id > 0
   AND avg_fragmentation_in_percent>5

-----------Kurzor---------------------
DECLARE @SQL VARCHAR(255)
DECLARE @DB_Index VARCHAR(255)
DECLARE @DB_Schema VARCHAR(255)
DECLARE @DB_Table VARCHAR(255)
DECLARE @OperationToMaintenance VARCHAR(255)

DECLARE index_cursor CURSOR FOR (SELECT DB_Index,DB_Schema,DB_Table,OperationToMaintenance FROM @TablesToMaintenance)

OPEN index_cursor
FETCH NEXT FROM index_cursor INTO @DB_Index, @DB_Schema, @DB_Table, @OperationToMaintenance
WHILE @@FETCH_STATUS = 0
  BEGIN
    SET @SQL= 'Alter INDEX [' + @DB_Index + '] ON [' + @DB_Schema + '].[' + @DB_Table + '] ' + @OperationToMaintenance
    EXECUTE (@SQL)
    FETCH NEXT FROM index_cursor INTO @DB_Index, @DB_Schema, @DB_Table, @OperationToMaintenance
  END
CLOSE index_cursor
DEALLOCATE index_cursor

Enjoy!

Edit 11.12.2018 – Script inside the cursor has been updated – dynamic SQL assembly. It is advisable to use square brackets because some automatically created SQL indexes may contain special characters or spaces, and executing SQL with such characters can fail. In the future, I pledge to use square brackets where they belong; it’s optional and a more professional approach.

Rate this post

Ing. Jan Zedníček - Data Engineer & Controlling

My name is Jan Zedníček and I have been working as a freelancer for many companies for more than 10 years. I used to work as a financial controller, analyst and manager at many different companies in field of banking and manufacturing. When I am not at work, I like playing volleyball, chess, doing a workout in the gym.

🔥 If you found this article helpful, please share it or mention me on your website

Leave a Reply

Your email address will not be published. Required fields are marked *