インデックスデフラグと統計情報更新

日々の運用で断片化したテーブルのインデックスデフラグ(インデックスの再構成)と統計情報の更新をします。

 

インデックスのデフラグ(再構成)とリビルド(再構築)がありますが、下のコマンドはデフラグを行います。また、統計情報の更新をします。

マイクロソフトのサイトを参考に、システム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

 

デフラグ_統計情報更新

 


管理人 has written 36 articles