Need to Defrag Indexes Without Writing to the Transaction Log

  • Every weekend we defrag our indexes on our primary ERP database. It takes about four hours. I run about 4,300 lines to defrag each index. Here is a sample:

    DBCC INDEXDEFRAG (ERP_App, [ABOPTS], [ABOPTSIx1])

    The problem is that I discovered that it grows the transaction log to about 600 GB. Is there a way I can do this without growing the log so dramatically? Since this is a 24/7 production database, I can't make the recovery mode Simple. Any insight would be greatly appreciated.

    Thanks.

    Steve

  • You can't prevent this from writing to the transaction log, but you could preform tlog backups more frequently during this process to keep the size to a minimum.



    Microsoft Certified Master - SQL Server 2008
    Follow me on twitter: @keith_tate

    Forum Etiquette: How to post data/code on a forum to get the best help[/url]

  • Run the transaction log backups more often. Are you running replication?

    If you are not doing it already, set them up to run every 15 minutes 24x7. If that is not often enough, run them every 5 minutes.

    If that is still not often enough, you could put a wait (WAITFOR DELAY) after each defrag command to allow the log backups time to catch-up. That would increase the total elapsed time for the defrag to run. To start, I suggest putting in a delay that is equal to the amount of time that the last defrag command took to run, and adjusting up or down as needed.

  • indexdefrag is an online process so backing up your logs more frequently will help, the work done so far will be truncated.

    You can reduce the amount odf logging by putting the database into bulk recovery mode, the log will not grow as much but the log backups will still be large.

    Also, are you only defragging those indexes that actually need it? this will reduce elapsed time and logging.

    Here is an example script (SQL2000)

    This example shows a simple way to defragment all indexes in a database that is fragmented above a declared threshold.

    /*Perform a 'USE <database name>' to select the database in which to run the script.*/

    -- Declare variables

    SET NOCOUNT ON

    DECLARE @tablename VARCHAR (128)

    DECLARE @execstr VARCHAR (255)

    DECLARE @objectid INT

    DECLARE @indexid INT

    DECLARE @frag DECIMAL

    DECLARE @maxfrag DECIMAL

    -- Decide on the maximum fragmentation to allow

    SELECT @maxfrag = 30.0

    -- Declare cursor

    DECLARE tables CURSOR FOR

    SELECT TABLE_NAME

    FROM INFORMATION_SCHEMA.TABLES

    WHERE TABLE_TYPE = 'BASE TABLE'

    -- Create the table

    CREATE TABLE #fraglist (

    ObjectName CHAR (255),

    ObjectId INT,

    IndexName CHAR (255),

    IndexId INT,

    Lvl INT,

    CountPages INT,

    CountRows INT,

    MinRecSize INT,

    MaxRecSize INT,

    AvgRecSize INT,

    ForRecCount INT,

    Extents INT,

    ExtentSwitches INT,

    AvgFreeBytes INT,

    AvgPageDensity INT,

    ScanDensity DECIMAL,

    BestCount INT,

    ActualCount INT,

    LogicalFrag DECIMAL,

    ExtentFrag DECIMAL)

    -- Open the cursor

    OPEN tables

    -- Loop through all the tables in the database

    FETCH NEXT

    FROM tables

    INTO @tablename

    WHILE @@FETCH_STATUS = 0

    BEGIN

    -- Do the showcontig of all indexes of the table

    INSERT INTO #fraglist

    EXEC ('DBCC SHOWCONTIG (''' + @tablename + ''')

    WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS')

    FETCH NEXT

    FROM tables

    INTO @tablename

    END

    -- Close and deallocate the cursor

    CLOSE tables

    DEALLOCATE tables

    -- Declare cursor for list of indexes to be defragged

    DECLARE indexes CURSOR FOR

    SELECT ObjectName, ObjectId, IndexId, LogicalFrag

    FROM #fraglist

    WHERE LogicalFrag >= @maxfrag

    AND INDEXPROPERTY (ObjectId, IndexName, 'IndexDepth') > 0

    -- Open the cursor

    OPEN indexes

    -- loop through the indexes

    FETCH NEXT

    FROM indexes

    INTO @tablename, @objectid, @indexid, @frag

    WHILE @@FETCH_STATUS = 0

    BEGIN

    PRINT 'Executing DBCC INDEXDEFRAG (0, ' + RTRIM(@tablename) + ',

    ' + RTRIM(@indexid) + ') - fragmentation currently '

    + RTRIM(CONVERT(varchar(15),@frag)) + '%'

    SELECT @execstr = 'DBCC INDEXDEFRAG (0, ' + RTRIM(@objectid) + ',

    ' + RTRIM(@indexid) + ')'

    EXEC (@execstr)

    FETCH NEXT

    FROM indexes

    INTO @tablename, @objectid, @indexid, @frag

    END

    -- Close and deallocate the cursor

    CLOSE indexes

    DEALLOCATE indexes

    -- Delete the temporary table

    DROP TABLE #fraglist

    GO

    ---------------------------------------------------------------------

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

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