web-dev-qa-db-ja.com

Ola Hallengren IndexOptimizeスクリプトを構成して、テーブルのサブセットに対して実行する方法

サイズが7 TB、300,000を超えるテーブルであるSQL 2016データベースに対してOla Hallengren IndexOptimizeスクリプトを使用しています。インデックスを管理するために毎晩6時間のウィンドウしかありません。私はtimelimitパラメーターを使用して、6時間後にジョブを停止します。

問題は、毎晩、インデックスジョブがインデックスの先頭から始まり、約4,000のテーブルのみを通過することです。

インデックスジョブでデータベース内のすべてのインデックスをカバーするにはどうすればよいですか?おそらく、インデックスのサブセットを行う複数のジョブを毎週1つ作成することにより、それとも、ジョブが前に中断した翌日にジョブを再開させる方法はありますか?

すべてのテーブルは同じデータベーススキーマにあります。これはベンダー提供のデータベースです。データベーススキーマを変更できません。

ガイダンスを事前に感謝します。

私の現在のジョブステップは次のとおりです。

EXECUTE [dbo].[IndexOptimize]
@Databases = 'USER_DATABASES',
@FragmentationLow = NULL, 
@FragmentationMedium = 'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE', 
@FragmentationHigh = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE', 
@FragmentationLevel1 = 10, 
@FragmentationLevel2 = 40,
@UpdateStatistics = 'ALL', 
@OnlyModifiedStatistics = 'Y', 
@PartitionLevel = 'N', 
@MaxDOP = 0,
@SortInTempdb = 'Y',
@TimeLimit = 21600,
@LogToTable = 'Y'
6
johna

毎晩インデックスをデフラグしないでください。最近のハードウェアでは特に必要ありません(特にシークタイムがゼロのソリッドステートストレージの場合)。毎日のメンテナンスでは、変更された統計情報を更新するだけでよく、パフォーマンスの低下に気付いた場合にのみこれを実行する必要があります(つまり、監視システムの通知内容を確認します)。

Olaのサイトによると、次のようなことができます。

EXECUTE dbo.IndexOptimize
@Databases = 'USER_DATABASES',
@FragmentationLow = NULL,
@FragmentationMedium = NULL,
@FragmentationHigh = NULL,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y'

インデックスを最適化する必要がある場合(たとえば、大量のデータを削除した場合)にできるもう1つのことは、SQL Serverの Service Broker を使用して複数のメンテナンスプランを設定することですバッチ内のテーブル。

この記事は詳細であり、この返信で要約することは困難ですが、非同期のキューを作成することになります。これにより、エージェントジョブが並行して起動されます。

9
Randolph West

philcart が何をしたかは、「前に中断した翌日から再開する」のに役立つはずです。

2つのSQLエージェントジョブでIndexOptimiseを実行しています。

毎週実行される最初のジョブでは、以下を使用して最適化が必要なすべてのインデックスを引き出します。

@FragmentationLow = NULL,  @FragmentationMedium =
'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE', 
@FragmentationHigh = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE', 
@FragmentationLevel1 = 5,  @FragmentationLevel2 = 30,  @LogToTable =
'Y',  @Execute = 'N'; 

これにより、CommandLogテーブルのIndex rebuild/defragコマンドがキャプチャされます。 IndexOptimiseコマンドを実行すると、挿入されたばかりのすべてのレコードの "EndTime"列がnullに設定されます。

次に、毎日、メンテナンスウィンドウ内で、2番目のジョブは単純なカーソルを使用して、EndTimeがNULLの各コマンドを引き出し、時間ウィンドウが経過していない場合はそれを実行します。

DECLARE @sqlCmd nvarchar(max);  DECLARE @maxDuration int = 60; 
DECLARE @startTime datetime = GETDATE();  DECLARE @totalCmds int =
(SELECT COUNT(1) FROM [dbo].[CommandLog] WHERE [EndTime] IS NULL); 
DECLARE @currCount int = 0;  DECLARE @cmdSample nvarchar(100);  IF
@totalCmds > 0  BEGIN -- we have work to do  DECLARE cmds CURSOR
FAST_FORWARD FOR SELECT [ID],[Command] FROM [dbo].[CommandLog] WHERE
[EndTime] IS NULL ORDER BY [ID] DESC  OPEN cmds  FETCH NEXT FROM cmds
INTO @logID, @sqlCmd  WHILE (@@FETCH_STATUS = 0 AND
(DATEDIFF(MI,@startTime,GETDATE()) < @maxDuration))  BEGIN  SET
@currCount += 1;  SET @cmdSample = LEFT(@sqlCmd,60)+'...';  UPDATE
[dbo].[CommandLog] SET [StartTime] = GETDATE() WHERE [ID] = @logID;
RAISERROR('Excuting IndexOptimize command for ID:%i (%i of %i) -
%s',10,1,@logID, @currCount, @totalCmds,@cmdSample) WITH NOWAIT;  EXEC
sp_executeSql @command = @sqlCmd;  UPDATE [dbo].[CommandLog] SET
[EndTime] = GETDATE() WHERE [ID] = @logID;  RAISERROR('Command
complete for ID:%i (%i of %i) - %s',10,1,@logID, @currCount,
@totalCmds,@cmdSample) WITH NOWAIT;  FETCH NEXT FROM cmds INTO @logID,
@sqlCmd  END  IF (@currCount < @totalCmds)  BEGIN 
RAISERROR('IndexOptimize finishing due to elapsed time, executed %i
commands out of %i',10,1,@currCount, @totalCmds) WITH NOWAIT;  END 
ELSE  BEGIN  RAISERROR('All commands executed within allowed time
window',10,1) WITH NOWAIT;  END  CLOSE cmds  DEALLOCATE cmds  END --
we have work to do  ELSE  BEGIN -- we have work to do 
RAISERROR('IndexOptimize has nothing to execute',10,1) WITH NOWAIT; 
END -- we have work to do 
3
MSSQLServerDBA
0
Jerry Hung

@Indexesパラメータを使用すると、個々のインデックスまたはテーブルを指定できます。非常に大きなテーブルで使用し、そのデータベースのメインインデックスジョブから除外します。

詳細はこちら: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html 、特にIndexesセクション。

メタテーブルを作成してテーブルのリストにデータを入力し、スケジュールを設定して、カーソルで実行することもできます。

0
BCM