Tara Kizer Blog

Tara Kizer

DBCC INDEXDEFRAG stored procedure - new version

Due to the problem mr_mist found in the DBCC DBREINDEX stored procedure, I have an updated version of the DBCC INDEXDEFRAG sproc as well:

----------------------------------------------------------------------------------------------------
-- OBJECT NAME         : isp_DBCC_INDEXDEFRAG
--
-- AUTHOR               : Tara Duggan
-- DATE     : May 11, 2004
--
-- INPUTS    : @dbName - name of the database
-- OUTPUTS    : None
-- DEPENDENCIES         : None
--
-- DESCRIPTION         : This stored procedure runs DBCC INDEXDEFRAG for each of the indexes in the database.
--
-- EXAMPLES (optional)  : EXEC isp_DBCC_INDEXDEFRAG @dbName = 'GT'
----------------------------------------------------------------------------------------------------
CREATE   PROC isp_DBCC_INDEXDEFRAG
(@dbName SYSNAME)
AS
SET NOCOUNT ON

DECLARE @objName SYSNAME
DECLARE @idxName SYSNAME
DECLARE @SQL NVARCHAR(4000)
DECLARE @ID INT
DECLARE @RowCnt INT

CREATE TABLE ##Indexes
(
 Indexes_ID INT IDENTITY(1, 1) NOT NULL,
 IndexName SYSNAME NOT NULL,
 ObjectName SYSNAME NOT NULL
)

SET @SQL = ''
SET @SQL = @SQL + 'INSERT INTO ##Indexes (IndexName, ObjectName) '
SET @SQL = @SQL + 'SELECT i.name, o.name '
SET @SQL = @SQL + 'FROM ' + @dbName + '.dbo.sysindexes i '
SET @SQL = @SQL + 'INNER JOIN ' + @dbName + '.dbo.sysobjects o '
SET @SQL = @SQL + 'ON i.id = o.id '
SET @SQL = @SQL + 'WHERE indid > 0 AND indid < 255 AND '
SET @SQL = @SQL + 'o.type = ''U'' AND '
SET @SQL = @SQL + '(i.status & (64 | 8388608)) <= 0'

EXEC sp_executesql @statement = @SQL

SELECT TOP 1 @ID = Indexes_ID, @idxName = IndexName, @objName = ObjectName
FROM ##Indexes
ORDER BY Indexes_ID

 

SET @RowCnt = @@ROWCOUNT

WHILE @RowCnt <> 0
BEGIN

 SET @SQL = 'DBCC INDEXDEFRAG(' + @dbname + ',' + @objName + ', ' + @idxName + ') WITH NO_INFOMSGS'

 EXEC sp_executesql @statement = @SQL

 SELECT TOP 1 @ID = Indexes_ID, @idxName = IndexName, @objName = ObjectName
 FROM ##Indexes
 WHERE Indexes_ID > @ID
 ORDER BY Indexes_ID
 
 SET @RowCnt = @@ROWCOUNT

END

DROP TABLE ##Indexes

RETURN 0

 

Here's a link to the old version.

Legacy Comments


mk_garg20
2004-08-02
re: DBCC INDEXDEFRAG stored procedure - new version
Hi Tara,
I have many indexes on tables in my database. I need to reindex them time to time. Can you tell me what to do for that.

I am using SQL server 7.0.

Thanks
Manoj


mk_garg20
2004-08-02
re: DBCC INDEXDEFRAG stored procedure - new version
Hi Tara,
Please ignore my previous comments.
Just checked your isp_DBCC_DBREINDEX stored procedure.

Can i use this for SQL server 7.0 without any change.

Thanks
Manoj

Tara
2004-08-03
re: DBCC INDEXDEFRAG stored procedure - new version
I have not tested it on 7.0. I don't have any 7.0 servers available to see if it is backward compatible. I'd suggest running it with PRINT @SQL instead of EXEC to try it out first.

Tara
2004-08-04
re: DBCC INDEXDEFRAG stored procedure - new version
;-)

I haven't put it on my weblog yet as I'm not happy with the cursor. As soon as I rewrite it using a WHILE loop instead, I'll post it.

BossHogg
2004-10-06
re: DBCC INDEXDEFRAG stored procedure - new version
I like your proc. I need one like it for Sybase to do update stats and another for dbccs for tables.
I'm not a Sybase developer so I'm looking everywhere for such a procedure.
Thanks! naxos98@hotmail.com

idigmail
2004-10-19
re: DBCC INDEXDEFRAG stored procedure - new version
This is great works on almost all my databases. You are the guru!! If you run it against the northwind database you can see the only problem my team found. It fails against the Order Details table. I think because there seems to be an issue with tables names that contain spaces. Anybody have any ideas on how to fix this? Did anybody else try this against northwind and get the same results?

Very cool..thanks for posting.

Tara
2004-10-19
re: DBCC INDEXDEFRAG stored procedure - new version
Table names with spaces, the horror!

I didn't test this, but:

SET @SQL = 'DBCC INDEXDEFRAG(' + @dbname + ',' + @objName + ', ' + @idxName + ')

change to:

SET @SQL = 'DBCC INDEXDEFRAG(' + @dbname + ',' + '[' + @objName + ']' + ', ' + @idxName + ')

Just need square brackets around object name.

Ken
2005-06-16
re: DBCC INDEXDEFRAG stored procedure - new version
The stored procedure works great, though I don't quite understand the code yet.

Can you explain what is meaning of [sysindexes].[status] value here, since I couldn't find any reference about them.
and why the "EXEC sp_executesql @statement = @SQL" was used in the WHILE loop, since it's first EXECUTION should have all the indexes collected.

Thanks

Tara
2005-06-16
re: DBCC INDEXDEFRAG stored procedure - new version
Sysindexes.status is used as we don't want to bother with hypothetical indexes and statistics.

The first "EXEC sp_executesql @statement = @SQL" was used to populate the ##Indexes table. The second was used to execute the DBCC DBREINDEX command. The second is done in the loop since we want to repeatedly run DBCC DBREINDEX, number of loops around depends on ##Indexes values.

Ken
2005-06-16
re: DBCC INDEXDEFRAG stored procedure - new version
The Previous question about "EXEC sp_executesql" was a mistake.

Can you just explain the status meaning? I couldn't find any reference. Thanks


Tara
2005-06-16
re: DBCC INDEXDEFRAG stored procedure - new version
Did my answer help explain why sysindexes.status is used? If not, I can elaborate more.

Bernt
2005-07-25
re: DBCC INDEXDEFRAG stored procedure - new version
Hello.

Thanks for a great script. Is the anyway this script can have another argument for running just for tables begining with some letters. For ex reindex all table begining with finance*. Why ? I have big databases with tables for different customers and want to spilt up this task.

Regards Bernt H. Jensen
DBA

Tara
2005-07-25
re: DBCC INDEXDEFRAG stored procedure - new version
I have a version of DBCC DBREINDEX that reads a table to see which indexes to build that day. It can easily be modified for INDEXDEFRAG.

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO



----------------------------------------------------------------------------------------------------
-- OBJECT NAME : isp_DBCC_DBREINDEX
--
-- AUTHOR : Tara Duggan
-- DATE : January 26, 2005
--
-- INPUTS : @Debug - 0, 1; whether to execute the command or display it
-- OUTPUTS : None
-- DEPENDENCIES : None
--
-- DESCRIPTION : This stored procedure runs DBCC DBREINDEX for the tables in the Defrag table per
-- the day of the week.
--
-- EXAMPLES (optional) : EXEC isp_DBCC_DBREINDEX_DayOfWeek
--
-- MODIFICATION HISTORY :
----------------------------------------------------------------------------------------------------
--
----------------------------------------------------------------------------------------------------
ALTER PROC isp_DBCC_DBREINDEX_DayOfWeek
(@Debug int = 0)
AS

SET NOCOUNT ON

DECLARE @DayOfWeek int, @i int, @j int, @SQL nvarchar(4000), @dbName sysname, @tblName sysname
DECLARE @Reindex table
(
Reindex_ID int IDENTITY(1, 1) NOT NULL,
DatabaseName sysname NOT NULL,
TableName sysname NOT NULL
)

SELECT @DayOfWeek = DATEPART(dw, GETDATE()), @i = 0

INSERT INTO @Reindex(DatabaseName, TableName)
SELECT DatabaseName, TableName
FROM Reindex
WHERE DayOfWeek = @DayOfWeek
ORDER BY DatabaseName, TableName

SELECT @j = @@ROWCOUNT

IF @j > 0
SET @i = 1

WHILE @i >= 1 AND @i <= @j
BEGIN
SELECT @dbName = DatabaseName, @tblName = TableName
FROM @Reindex
WHERE Reindex_ID = @i

SET @SQL = 'DBCC DBREINDEX(''' + @dbName + '.dbo.' + @tblName + ''', '''', 0) WITH NO_INFOMSGS'

IF @Debug = 0
EXEC (@SQL)
ELSE
PRINT @SQL

SET @i = @i + 1
END





GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO


Bernt
2005-07-31
re: DBCC INDEXDEFRAG stored procedure - new version
Hello Again.

Regarding my earlier request I have now solved it.

I have added a new argument which is tablename
-------------------------
CREATE PROCEDURE dbo.isp_DBCC_INDEXDEFRAG
@dbName sysname,
@tablename varchar(100)
AS
SET NOCOUNT ON
---------------
SET @SQL = @SQL + '(i.status & (64 | 8388608)) <= 0 AND '
SET @SQL = @SQL + 'i.name LIKE ' + ''''+ @tablename + ''''
---------------

Now you can call it like this and it will run for all table starting with : Finance Dep Oslo
dbo.isp2_DBCC_INDEXDEFRAG '[199_FIN01]', 'Finance Dep Oslo%'

Hope you find it useful, if not ignore it:-)

Bernt
DBA, Oslo Norway
sunbernt@hotmail.com

Dennis
2005-10-12
re: DBCC INDEXDEFRAG stored procedure - new version
@Ken -- reguarding what the status values relate to.

Take a look at
SELECT * FROM master.dbo.spt_values WHERE type = 'I'


Paul Hills, SQL Programmer
2005-12-02
re: DBCC INDEXDEFRAG stored procedure - new version
Was on the verge of writing a procedure to defrag all indexes on a particular database when I happened upon this article!

Quotes on the DBCC EXEC line had to be modified to make it work, but an excellent and useful procedure indeed.

Many thanks :-)


Stan
2005-12-28
re: DBCC INDEXDEFRAG stored procedure - new version
Tara, this is a great procedure. Thanks so much! I did find I had a problem when the object is not owned by dbo. I had to add a join to the sysusers table to get the object owner name to use along with the object name in the DBCC IndexDefrag call.

I enjoy your blog and find many useful tidbits. Keep posting! :-)

Dana
2006-04-05
re: DBCC INDEXDEFRAG stored procedure - new version
Did you know this doesn't compile in Query Anaylzer? Cut and paste it...

Tara
2006-04-06
re: DBCC INDEXDEFRAG stored procedure - new version
Well you have to reformat it as it didn't post correctly in the blog. Comments got wrapped around to the next line.

So once you reformat it, it does compile and works great.

Dana
2006-04-06
re: DBCC INDEXDEFRAG stored procedure - new version
Not exactly:

(@dbName SYSNAME)
...
SET @SQL = 'DBCC INDEXDEFRAG(' + @dbname ...

Note the case difference (@dbName, #@dbname). The server I compiled this on must have a case-sensitive option set (not sure exactly which one, but I seem to recall that as an option).

jessica
2006-04-28
re: DBCC INDEXDEFRAG stored procedure - new version
hi, can i run this sp with any database in my sql server 2000? just creating a new procedure and pasting your code?

Mohcine
2006-08-14
re: DBCC INDEXDEFRAG stored procedure - new version
Hello Great script... Can you tell me how can this script be modified to run this script on all indexes in one table?
Thanks
-Mohcine

Mohcine
2006-08-16
re: DBCC INDEXDEFRAG stored procedure - new version
Figured it out thx guys!

Vivekanand
2006-10-16
re: DBCC INDEXDEFRAG stored procedure - new version
Hi ,
The new version Defragmentation is working fine and its really useful for dev/db support point of view.