In order to reduce fragmentation
on indexes, you have two options. You can REORGANIZE an index, or you can
REBUILD the index.
When you REORGANIZE an index,
the leaf level will be reorganized, and the index is kept online during this
operation. The advantage to this is that table locks are not held, and queries
can continue as normal.
When you REBUILD an index the
default is to take the index offline. What this means is that a table lock is
held, and all reads and writes that utilize the index are blocked until the
REBUILD is complete. This can cause blocking and poor performance of queries.
Dynamics AX Database Maintenance Strategies
The recommended strategy is to REORGANIZE indexes below a certain fragmentation threshold, and REBUILD those above that same threshold on a daily basis. See the script at the end for how to accomplish this. The fragmentation threshold that you choose can vary the amount of time that your maintenance job takes to complete, and should be monitored to make sure that it is not running into business hours.
Microsoft recommends not performing any operation on indexes that are fragmented less than 10%. For those indexes which are between 10 and 30 percent fragmentation, a REORGANIZE should be used. Above 30% fragmentation, the cost of an ONLINE REBUILD is actually less than that of a REORGANIZE.
Index Maintenance Script
-- Ensure a USEstatement has been executed first. SET NOCOUNT ON; DECLARE @objectid int; DECLARE @indexid int; DECLARE @partitioncount bigint; DECLARE @schemaname nvarchar(130); DECLARE @objectname nvarchar(130); DECLARE @indexname nvarchar(130); DECLARE @partitionnum bigint; DECLARE @partitions bigint; DECLARE @frag float; DECLARE @command nvarchar(4000); -- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function -- and convert object and index IDs to names. SELECT object_id AS objectid, index_id AS indexid, partition_number AS partitionnum, avg_fragmentation_in_percent AS frag INTO #work_to_do FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED') WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0; -- Declare the cursor for the list of partitions to be processed. DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do; -- Open the cursor. OPEN partitions; -- Loop through the partitions. WHILE (1=1) BEGIN; FETCH NEXT FROM partitions INTO @objectid, @indexid, @partitionnum, @frag; IF @@FETCH_STATUS < 0 BREAK; SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(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 = QUOTENAME(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; -- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding. IF @frag < 30.0 SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE'; IF @frag >= 30.0 SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD'; IF @partitioncount > 1 SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10)); EXEC (@command); PRINT N'Executed: ' + @command; END; -- Close and deallocate the cursor. CLOSE partitions; DEALLOCATE partitions; -- Drop the temporary table. DROP TABLE #work_to_do; GO
No comments:
Post a Comment