Click here to Skip to main content
15,888,984 members
Articles / Database Development / SQL Server
Tip/Trick

Reorganize and Rebuild Indexes and Update Statistics

Rate me:
Please Sign up or sign in to vote.
4.95/5 (15 votes)
30 Mar 2024Public Domain1 min read 34.6K   18   8
A simple stored procedure to add at your database to keep it reactive

Introduction

In this tip, I want share my solution about a common issue: indexed maintenance. That is an easy stored procedure to add to your database to keep a good query execution performance.

Implementation

To implement this procedure on your database, it's just necessary to execute the creation statement. Personally, I suggest to execute this procedure one or two times for a week according to your database size and complexity.

Using the Code

Stored Procedure Explanation

This stored procedure can be divided into 4 parts:

  1. Check database integrity
  2. Reorganize Indexes
  3. Rebuild Indexes
  4. Updates Statistics

1. Database Integrity

The first operation is check your database's integrity, if this step returns an error, the system can't proceed to indexes maintenance operations. This step is completed with executing this statement:

SQL
DBCC CHECKDB WITH NO_INFOMSGS

2. Indetify Index to Reorganize

The code to complete this step is based on function sys.dm_db_index_physical_stats. sys.dm_db_index_physical_stats return size and fragmentation information for the data and indexes of the specified database. Personally, I chose to reorganize all indexes with an average fragmentation between 10 and 35 percent.

SQL
SELECT  @Reorganize = @Reorganize + ' ' + _
'ALTER INDEX [' + i.[name] + '] ON [dbo].[' + t.[name] + ']
        REORGANIZE WITH ( LOB_COMPACTION = ON )'
FROM    sys.dm_db_index_physical_stats
          (DB_ID(@DBName ), NULL, NULL, NULL , 'DETAILED') fi
        inner join sys.tables t
         on fi.[object_id] = t.[object_id]
        inner join sys.indexes i
         on fi.[object_id] = i.[object_id] and
            fi.index_id = i.index_id
where t.[name] is not null and i.[name] is not null
        and avg_fragmentation_in_percent > 10
        and avg_fragmentation_in_percent <=35
order by t.[name]

3. Identify Index to Rebuild

In the same way as the previous step, this statement identifies all indexes with an average fragmentation greater than 35 percent. For these type of indexes, a rebuild operation is necessary.

SQL
SELECT  @Rebild = @Rebild + ' ' + _
'ALTER INDEX [' + i.[name] + '] ON [dbo].[' + t.[name] + ']
        REBUILD WITH (ONLINE = OFF )'
FROM    sys.dm_db_index_physical_stats
          (DB_ID(@DBName ), NULL, NULL, NULL , 'DETAILED') fi
        inner join sys.tables t
         on fi.[object_id] = t.[object_id]
        inner join sys.indexes i
         on fi.[object_id] = i.[object_id] and
            fi.index_id = i.index_id
where avg_fragmentation_in_percent > 35 and t.[name] is not null and i.[name] is not null
order by t.[name]

4. Updated Index Statistics

The last step is to update the database statistics. To update indexes, just execute this statement:

SQL
EXEC sp_updatestats

Procedure Code

SQL
CREATE PROCEDURE [dbo].[usp_Inxed_Statistics_Maintenance]
@DBName AS NVARCHAR(128)
AS

DECLARE @ERRORE INT
--Check Database Error
DBCC CHECKDB WITH NO_INFOMSGS
SET @ERRORE = @@ERROR
IF @ERRORE = 0 
BEGIN
	DECLARE @RC INT
	DECLARE @Messaggio VARCHAR(MAX)
	DECLARE @Rebild AS VARCHAR(MAX)
	DECLARE @Reorganize AS VARCHAR(MAX)

	SET @Reorganize = ''
	SET @Rebild = ''

	SELECT  @Reorganize = @Reorganize + ' ' + 
	'ALTER INDEX [' + i.[name] + '] ON [dbo].[' + t.[name] + '] 
			REORGANIZE WITH ( LOB_COMPACTION = ON )'
	FROM	sys.dm_db_index_physical_stats
			  (DB_ID(@DBName ), NULL, NULL, NULL , 'DETAILED') fi
			inner join sys.tables t
			 on fi.[object_id] = t.[object_id]
			inner join sys.indexes i
			 on fi.[object_id] = i.[object_id] and
				fi.index_id = i.index_id
	where t.[name] is not null and i.[name] is not null 
			and avg_fragmentation_in_percent > 10   
			and avg_fragmentation_in_percent <=35
	order by t.[name]

	EXEC (@Reorganize)

	SELECT  @Rebild = @Rebild + ' ' + 
	'ALTER INDEX [' + i.[name] + '] ON [dbo].[' + t.[name] + '] 
			REBUILD WITH (ONLINE = OFF )'
	FROM	sys.dm_db_index_physical_stats
			  (DB_ID(@DBName ), NULL, NULL, NULL , 'DETAILED') fi
			inner join sys.tables t
			 on fi.[object_id] = t.[object_id]
			inner join sys.indexes i
			 on fi.[object_id] = i.[object_id] and
				fi.index_id = i.index_id
	where avg_fragmentation_in_percent > 35 and t.[name] is not null and i.[name] is not null
	order by t.[name]

	EXEC (@Rebild)
END

-- if there are not error update statistics
SET @ERRORE = @@ERROR
IF @ERRORE = 0
	BEGIN
		EXEC sp_updatestats
	END
	
;

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Software Developer
Italy Italy
I'm a software engineer, specializing in backend development and distributed systems. I have extensive experience in designing and implementing resilient, responsive, scalable, and maintainable systems using C#, .NET on top of cutting-edge technologies.

Comments and Discussions

 
QuestionNice, but no cigar Pin
ObiWan_MCC10-Apr-24 23:47
ObiWan_MCC10-Apr-24 23:47 
QuestionError with SQL2008R2 needs replacement with smallint variable Pin
Herbert Moll3-Apr-24 23:39
Herbert Moll3-Apr-24 23:39 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA31-Mar-24 1:30
professionalȘtefan-Mihai MOGA31-Mar-24 1:30 
Questioncheckdb: Analyse what is error reason, don't blindly stop processing, maybe we can fix it before it causes a harder headache with a corrupted database Pin
Tuomas Keskitalo5-Mar-21 22:51
Tuomas Keskitalo5-Mar-21 22:51 
QuestionSchemas other than DBO Pin
cthue14-Nov-16 9:12
cthue14-Nov-16 9:12 
AnswerRe: Schemas other than DBO Pin
cthue14-Nov-16 9:32
cthue14-Nov-16 9:32 
QuestionTypos but a nice post Pin
Rahul_Biswas25-Oct-16 1:38
professionalRahul_Biswas25-Oct-16 1:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.