Several factors contribute to MSD index maintenance woes. For one, MSDs often run on the Standard Edition of SQL, so you can't rebuild the indices with the "online" option. Secondly MSDs are large enough that rebuilding an index takes a fair amount of time. Finally the MSD indices often get built by developers who forget to include a fill factor.
Obviously at your first opportunity you will schedule some jobs to rebuild the fragmented indices with an adequate fill factor. More importantly though you should find some time to meet with the developers and encourage them to use a fill factor (when appropriate) on indices where the referenced fields are clearly loading with out-of-sequence data. They'll be clueless what factor to use so it's easiest to specify a safe fixed fill, say 85 or 90%... then you can adjust it to lower if you find it fragmenting exceedingly fast.
Once you've got your fill allocated the next challenge is finding the time to run index reorganization on a regular basis. Although it won't lock tables or block other spids, the reorgs do take a fair amount of resources. If you've got a nice chunk of quiet time on the weekend you can schedule a big reorg job then, naturally, but if your systems is always active then you might like this little trick.
First build a table within your MSD to hold the reorganization SQL statements; I use something like this:
CREATE TABLE [IndexReorgScripts](Now from a connection to your MSD, run this query:
[ReorgSQL] [varchar](350) NOT NULL,
[RunDayNum1] [smallint] NULL,
[RunDayNum2] [smallint] NULL)
INSERT INTO IndexReorgScriptsThis will build all the statements to reorganize the SQL indices. The two RunDayNum columns are for you to set to a day of the month you want the index rebuilt -- I made two columns because I reorganize my indices on average twice a month. Try to assign a broad range of days across the various tables.
(ReorgSQL)
SELECT 'ALTER INDEX ' + [name] + ' ON [dbo].' + OBJECT_NAME(OBJECT_ID) +
' REORGANIZE WITH ( LOB_COMPACTION = ON )' AS ReorgSQL
FROM sys.indexes
where type_desc = 'NONCLUSTERED'
and fill_factor > 0
and is_disabled = 0
Finally, schedule a SQL job to run this script every evening:
DECLARE @ReorgStatement varchar(350)
DECLARE @ThisDayOfMonth AS smallint
SET @ThisDayOfMonth = DAY(GETDATE())
DECLARE IndicesToReorg CURSOR FOR
SELECT [ReorgSQL]
FROM [IndexReorgScripts]
WHERE [ReorgSQL] LIKE 'ALTER INDEX%'
AND ( [RunDayNum1] = @ThisDayOfMonth
OR [RunDayNum2] = @ThisDayOfMonth )
OPEN IndicesToReorg;Now you're all set to check in every morning and find another handful of indices got rebuilt! The method isn't foolproof; you will need to occasionally update the table with additional indices that folks have added, or remove those that got disabled. Still though quite a lifesaver.
FETCH NEXT FROM IndicesToReorg into @ReorgStatement
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC(@ReorgStatement)
FETCH NEXT FROM IndicesToReorg into @ReorgStatement
END
CLOSE IndicesToReorg;
DEALLOCATE IndicesToReorg;