Index Fragmented?

  • Hi,

    we are using sqlresponse for monitoring,Iam new to this product. It recommending that the following indexes are fragmented. What are the steps do I need to take to avoid this index fragmentation?

    Here is the message:

    Index Fragmented:Database BiztalkmgmtDb

    IndexName TableNAme LogicalscanFragmentation Pages Size

    IX_bt_DocumentSpec_msgtype dbo.bt_DocumentSpec92.59 % 27 216.0 kB

    IX_bt_DocumentSpec_clr_namespace dbo.bt_DocumentSpec54.84 % 62 496.0 kB

    Thanks

  • Hi I develop this query to defrag indexes that have 30% defragmentation (you can change the %). it also show you a report of before and after fragmentation. I hope this will help:

    ALTER Proc [DBM].[Defrag]

    as

    -- Index Fragmentation: Delete unused pages

    Declare @sql nvarchar(4000),

    @acursor_TableName cursor,

    @TableName varchar(150),

    @acursor_Indexes cursor,

    @Indexes varchar(150)

    Create Table #Report

    (

    [Table Name] varchar(150),

    Fragment decimal(18,2),

    Defragment decimal(18,2),

    Percentage decimal(18,2)

    )

    Create Table #TableIndex

    (

    Indexes varchar(150),

    Fragment decimal(18,2)

    )

    -- Change change compatibility level to 90

    EXEC sp_dbcmptlevel ICDB, 90

    --Start Looping (Get table)

    set @acursor_TableName = cursor for SELECT TABLE_NAME AS Table_Name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' And TABLE_SCHEMA = 'dbo'

    open @acursor_TableName

    fetch next from @acursor_TableName into @TableName

    while (@@fetch_status = 0)

    begin

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

    INSERT INTO #Report

    Values(@TableName,'0','0','0')

    Truncate Table #TableIndex

    Set @sql = 'Select Name, Avg_fragmentation_in_Percent

    FROM sys.dm_db_index_physical_stats (db_id(N''ICDB''),

    Object_id(''' + @TableName + '''),null,null,null) as A

    JOIN

    sys.indexes as B on a.Object_ID = b.Object_id

    AND a.index_id = b.index_id

    AND name is not null

    AND name <> '''''

    Insert INTO #TableIndex(Indexes,Fragment)

    Execute sp_Executesql @sql

    UPDATE A SET Fragment = (SELECT Sum(Fragment) / (Select Count(*) FROM #TableIndex) FROM #TableIndex)

    FROM #Report A

    Where [Table Name] = @TableName

    --Start Looping (Get Indexes)

    set @acursor_Indexes = cursor for SELECT Indexes FROM #TableIndex Where Fragment >= 30

    open @acursor_Indexes

    fetch next from @acursor_Indexes into @Indexes

    while (@@fetch_status = 0)

    begin

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

    Set @sql = 'Alter INDEX ' + @Indexes + ' on ' + @TableName + ' Rebuild'

    Execute sp_Executesql @sql

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

    fetch next from @acursor_Indexes into @Indexes

    end

    close @acursor_Indexes

    deallocate @acursor_Indexes

    --End Looping

    Truncate Table #TableIndex

    Set @sql = 'Select Name, Avg_fragmentation_in_Percent

    FROM sys.dm_db_index_physical_stats (db_id(N''Database Name''),

    Object_id(''' + @TableName + '''),null,null,null) as A

    JOIN

    sys.indexes as B on a.Object_ID = b.Object_id

    AND a.index_id = b.index_id

    AND name is not null

    AND name <> '''''

    Insert INTO #TableIndex(Indexes,Fragment)

    Execute sp_Executesql @sql

    UPDATE A SET Defragment = (SELECT Sum(Fragment) / (Select Count(*) FROM #TableIndex) FROM #TableIndex)

    FROM #Report A

    Where [Table Name] = @TableName

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

    fetch next from @acursor_TableName into @TableName

    end

    close @acursor_TableName

    deallocate @acursor_TableName

    --End Looping

    Update A Set Percentage = (Defragment/Fragment) * 100

    FROM #Report A

    Where Defragment <> 0

    and Defragment is not null

    and Fragment <> 0

    and Fragment is not null

    Select *

    FROM #Report

    Where Defragment is not null

    and Defragment <> '0.00'

    and Defragment <> Fragment

    Drop table #TableIndex

    Drop Table #Report

    EXEC sp_recompile sys_profile

    -- Change back compatibility level to 80

    EXEC sp_dbcmptlevel ICDB, 80

  • You can't avoid index fragmentation unless you don't change data. Sooner or later with deletes or page splits you'll get fragmentation. The thing to do is monitor it (as shown above) and then rebuild the indexes when it gets bad.

  • Hi there. I also have a process that will defrag indexes nightly. You can find the script on my SQL blog here: http://sqlfool.com/?p=63.

    Aside from that, Steve's right... data is bound to become fragmented in SQL Server. There are some steps you can do to minimize fragmentation, however. For example, you can ensure that you're clustering on an incrementing value, such an identity column or even a datetime stamp. If this is not an option, then you can play with the fill factor on the index (http://msdn.microsoft.com/en-us/library/ms177459.aspx).

    HTH!

  • With indexes as small as you're showing (27 pages), it's not likely that a rebuild OR a defragment will do anything. the Defrag and rebuild operation focus on improving performance, and NOT on building a perfectly ordered contiguous index. If your performance isn't negatively affected, then it's not going to do anything. The algorithm used essentially doesn't do much on indexes <1000 pages.

    ----------------------------------------------------------------------------------
    Your lack of planning does not constitute an emergency on my part...unless you're my manager...or a director and above...or a really loud-spoken end-user..All right - what was my emergency again?

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

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