日々の運用で断片化したテーブルのインデックスデフラグ(インデックスの再構成)と統計情報の更新をします。
インデックスのデフラグ(再構成)とリビルド(再構築)がありますが、下のコマンドはデフラグを行います。また、統計情報の更新をします。
マイクロソフトのサイトを参考に、システムDB以外、読み取り専用になっていない全DBを対象にテーブル所有者にも配慮したものにしました。
DECLARE @comand VARCHAR (8000) ---------------------------------- --@comand ここから SELECT @comand=' -- Declare variables SET NOCOUNT ON DECLARE @dbename VARCHAR (255) DECLARE @tableownername VARCHAR (128) DECLARE @tableownername2 VARCHAR (128) DECLARE @tablename VARCHAR (128) DECLARE @tablename2 VARCHAR (128) DECLARE @inflg INT DECLARE @execstr VARCHAR (255) DECLARE @objectid INT DECLARE @indexid INT DECLARE @frag DECIMAL DECLARE @maxfrag DECIMAL DECLARE @IndexName VARCHAR (255) -- Decide on the maximum fragmentation to allow -- どれくらい断片化が進んだテーブルを対象にするか 10~30% SELECT @maxfrag = 10.0 -- 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) -- Do the showcontig of all indexes of the table EXEC SP_MSForEachTable '' INSERT INTO #fraglist EXEC (''''DBCC SHOWCONTIG (''''''''?'''''''') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS''''); '' -- Declare cursor for list of indexes to be defragged DECLARE indexes CURSOR FOR SELECT DISTINCT TABLE_SCHEMA, ObjectName, ObjectId, LogicalFrag, IndexName FROM #fraglist A inner join INFORMATION_SCHEMA.TABLES B ON A.ObjectName=B.TABLE_NAME WHERE LogicalFrag >= @maxfrag AND INDEXPROPERTY (ObjectId, IndexName, ''IndexDepth'') > 0 AND ( IndexName IS NOT NULL OR RTRIM(IndexName) <> '''' ) -- Open the cursor OPEN indexes SELECT @inflg = 0 -- loop through the indexes FETCH NEXT FROM indexes INTO @tableownername, @tablename, @objectid, @frag, @IndexName WHILE @@FETCH_STATUS = 0 BEGIN SELECT @inflg = 1 SELECT @tablename2 = @tablename SELECT @tableownername2 = @tableownername PRINT ''Executing DBCC INDEXDEFRAG (0, ''''['' + RTRIM(@tableownername) + ''].['' + RTRIM(@tablename) + '']'''', ['' + RTRIM(@IndexName) + '']) - fragmentation currently '' + RTRIM(CONVERT(varchar(15),@frag)) + ''%'' SELECT @execstr = ''DBCC INDEXDEFRAG (0, ''''['' + RTRIM(@tableownername) + ''].['' + RTRIM(@tablename) + '']'''', ['' + RTRIM(@IndexName) + ''])'' EXEC (@execstr) FETCH NEXT FROM indexes INTO @tableownername, @tablename, @objectid, @frag, @IndexName --統計情報更新 IF @tablename2 <> @tablename BEGIN PRINT ''UPDATE STATISTICS ['' + RTRIM(@tableownername2) + ''].['' + RTRIM(@tablename2) + ''] WITH FULLSCAN'' SELECT @execstr = ''UPDATE STATISTICS ['' + RTRIM(@tableownername2) + ''].['' + RTRIM(@tablename2) + ''] WITH FULLSCAN'' EXEC (@execstr) END END IF @inflg = 1 BEGIN --統計情報更新 PRINT ''UPDATE STATISTICS ['' + RTRIM(@tableownername2) + ''].['' + RTRIM(@tablename2) + ''] WITH FULLSCAN'' SELECT @execstr = ''UPDATE STATISTICS ['' + RTRIM(@tableownername2) + ''].['' + RTRIM(@tablename2) + ''] WITH FULLSCAN'' EXEC (@execstr) END -- Close and deallocate the cursor CLOSE indexes DEALLOCATE indexes -- Delete the temporary table DROP TABLE #fraglist ' --@comand ここまで ---------------------------------- DECLARE @dbename VARCHAR (255) -- Create the table CREATE TABLE #dbname ( dbName VARCHAR (255)) --システム以外、読み取り専用になっていないもの INSERT INTO #dbname SELECT [name] FROM sys.databases WHERE is_read_only =0 and database_id > 4 -- Declare cursor for list of indexes to be defragged DECLARE dbname CURSOR FOR SELECT DBName FROM #DBName -- Open the cursor OPEN dbname -- loop through the indexes FETCH NEXT FROM dbname INTO @dbename WHILE @@FETCH_STATUS = 0 BEGIN print 'DB = ' + @dbename exec ('use [' + @dbename + ']' + @comand +';' ); -- loop through the indexes FETCH NEXT FROM dbname INTO @dbename END CLOSE dbname DEALLOCATE dbname -- Delete the temporary table DROP TABLE #dbname
参考サイト:https://msdn.microsoft.com/ja-jp/library/ms177571%28v=sql.110%29.aspx