SQL Server 2005 Index Maintenance

  • Luke C

    Right there with Babe

    Points: 790

    Comments posted to this topic are about the item SQL Server 2005 Index Maintenance

    Luke C
    MCSE: Data Platform, MCP, MCTS, MCITP - Database Administrator & Database Developer

  • zoltix

    SSC Eights!

    Points: 813

    I have modified the script for removing and for improving the compatibility.....

    USE [master]

    GO

    SET ANSI_NULLS OFF

    GO

    SET QUOTED_IDENTIFIER OFF

    GO

    /**

    ********* 03/26/2008 - Luke Campbell - uspIndexMaintenance.

    This procedure reorganizes any indexes (NON XML) that have a page

    count greater than 10 and a fragmentation level greater than 20%. If

    the fragmentation level is 30% or above the index will be rebuilt

    using the ONLINE parameter (enterprise edition only). Sorting will be

    done in the TEMPDB to decrease the maintenance time interval.

    TEMPDB must have sufficient space available otherwise remove "SORT_IN_TEMPDB=ON"

    before creating this script in the Master db.

    Modified by lli : 2009/02/09

    Bug : double the reindex on the same table

    Bug : Partion Table not fully compatible

    Bug : remove Maint.dbo.DBIndexInfo for logging purposes

    */

    create PROCEDURE [dbo].[uspIndexMaintenance] @dbname varchar(50)

    --

    AS

    BEGIN

    --DECLARE @dbname varchar(50)

    --Set @dbname = ''

    --Setup dynamic SQL to run. Otherwise the Procedure needs to be deployed to each db.

    DECLARE @SQL varchar(4000)

    SET @SQL = 'Use ' + @dbname + '

    --Declare variables here

    DECLARE @objectid int

    DECLARE @indexid int

    DECLARE @partitioncount bigint

    DECLARE @schemaname varchar(130)

    DECLARE @objectname varchar(130)

    DECLARE @indexname varchar(130)

    DECLARE @partitionnum bigint

    DECLARE @partitions bigint

    DECLARE @frag int

    DECLARE @command varchar(4000)

    --Used for looping

    DECLARE @max int

    DECLARE @min int

    --Create tables to hold Index information about each table in the database

    CREATE TABLE #IndexList (ID int IDENTITY(1,1),

    DBName varchar(50),

    objectID int,

    indexID int,

    IndexType varchar(30),

    frag int,

    avg_fragment_size_in_pages int,

    page_count int,

    partition_number int)

    --Create indexes on #IndexList

    CREATE CLUSTERED INDEX IX_CL_IndexList ON #IndexList(ID)

    --Get Index stats

    INSERT #IndexList (DBName, objectID, indexID, IndexType, frag, avg_fragment_size_in_pages, page_count, partition_number)

    SELECT DB_Name(database_id) AS DBName,

    object_id,

    index_id,

    index_type_desc AS IndexType,

    avg_fragmentation_in_percent,

    avg_fragment_size_in_pages,

    page_count,

    partition_number FROM sys.dm_db_index_physical_stats

    (DB_ID(), NULL, NULL, NULL, ''LIMITED'')

    WHERE page_count > 10 AND index_id > 0 AND avg_fragmentation_in_percent > 20 AND

    index_type_desc NOT LIKE ''%XML%''

    --Begin reorganizing or rebuilding indexes. Determined by level of fragmentation.

    --Rebuilding of indexes will use the SORT_IN_TEMPDB and ONLINE parameters.

    SELECT @max = (SELECT max(ID) FROM #IndexList)

    SELECT @min = 1

    WHILE @min <= @max

    BEGIN

    SELECT @objectid = objectID,

    @indexid = indexID,

    @partitionnum = partition_number,

    @frag = frag FROM #IndexList

    WHERE ID = @min

    SELECT @objectname = o.name, @schemaname = s.name

    FROM sys.objects AS o

    JOIN sys.schemas AS s ON s.schema_id = o.schema_id

    WHERE o.object_id = @objectid

    SELECT @indexname = name

    FROM sys.indexes

    WHERE object_id = @objectid AND index_id = @indexid;

    SELECT @partitioncount = count(*)

    FROM sys.partitions

    WHERE object_id = @objectid AND index_id = @indexid

    --Reorganize or Rebuild

    --Inserts Index information into Maint.dbo.DBIndexInfo for logging purposes

    --INSERT Maint.dbo.DBIndexInfo (DBName, TableName, IndexName, Status, CreationDate)

    --VALUES ('''+ @dbname +''', @objectname, @indexname, ''Start'', Getdate())

    IF @frag < 30

    begin

    SET @command = ''ALTER INDEX '' + @indexname + '' ON '' + @schemaname + ''.'' + @objectname +'' REORGANIZE'';

    IF @partitioncount > 1

    SET @command = @command + '' PARTITION ='' + CAST(@partitionnum AS varchar(10));

    --PRINT @command

    end

    IF @frag >= 30

    begin

    SET @command = ''ALTER INDEX '' + @indexname + '' ON '' + @schemaname + ''.'' + @objectname +'' REBUILD ''

    IF @partitioncount > 1

    SET @command = @command + '' PARTITION ='' + CAST(@partitionnum AS varchar(10));

    SET @command = @command + ''WITH(SORT_IN_TEMPDB = ON)''; --FILLFACTOR = 90, ONLINE = ON,

    --PRINT @command

    end

    PRINT @command

    EXEC (@command)

    --INSERT Maint.dbo.DBIndexInfo (DBName, TableName, IndexName, Status, CreationDate)

    -- VALUES ('''+ @dbname +''', @objectname, @indexname, ''End'', Getdate())

    SET @min = @min+1

    END

    PRINT ''Index maintenance on the '+@dbname +' database has completed.''

    --select * from maint.dbo.DBIndexInfo

    DROP TABLE #IndexList

    '

    --PRINT @SQL

    EXEC (@SQL)

    END

    GO

    USE [master]

    GO

    SET ANSI_NULLS OFF

    GO

    SET QUOTED_IDENTIFIER OFF

    GO

    /*

    ********** 03/26/2008 - Luke Campbell uspDBIndexCycle ************

    Script will cycle through each database on the server and execute the

    sp_MaintAutoReindex2005 procedure.

    */

    create PROCEDURE [dbo].[uspDBIndexCycle]

    AS

    BEGIN

    DECLARE @sql varchar(300)

    DECLARE @dbname sysname

    DECLARE @min int

    DECLARE @max int

    --Create our temp table to hold all database names on the server

    CREATE TABLE #database ([ID] int IDENTITY(1,1), [Name] varchar(60))

    --

    --Create Clustered Index on the name column & and insert values

    CREATE CLUSTERED INDEX IX_CL_database ON #database([Name])

    INSERT INTO #database ([Name])

    SELECT [name] FROM sys.databases WHERE [name] NOT IN('master','tempdb','model','msdb')

    --Build our loop

    SELECT @max = (SELECT max(ID) FROM #database)

    SELECT @min = 1

    WHILE @min <= @max

    BEGIN

    SELECT @dbname = [Name] FROM #database WHERE ID = @min

    SELECT @sql = 'EXEC uspIndexMaintenance ''' + @dbname +''''

    PRINT @sql

    EXEC (@sql)

    SET @min = @min+1

    END

    --Clean up

    DROP TABLE #database

    END

  • akljfhnlaflkj

    SSC Guru

    Points: 76202

    Thanks for the script.

Viewing 3 posts - 1 through 3 (of 3 total)

You must be logged in to reply to this topic. Login to reply