OLTPデータベースです。SQLサーバー2008 R2にあります)2週間前、私たちはDBAの1人が統計を個別に更新するメンテナンスジョブ。これは、インデックス最適化ジョブの前に毎週実行されます。これが作成された後、少数のストアドプロシージャでパフォーマンスの問題が発生しているようです。統計のメンテナンスについてあまり詳しくないので、すべての統計を更新するには、毎週ジョブを個別に実行する必要がありますか?
ここのDBAは、これが必要だと思っていたようですが、メンテナンスジョブの実行後、朝にストアドプロシージャのパフォーマンスが低下し始めたため、同じストアドプロシージャを少なくとも1〜2回再コンパイルする必要がありました。次の数日間は、問題が発生しなくなります。私の理論は以前に行われた統計の更新を指していますが、その理由を見つけるのに苦労しています。統計は、ある程度の変更の後、またはインデックスの再構築中に更新されませんか?それらを個別に再計算すると問題が発生するのはなぜですか?
統計が更新されるたびに同じストアドプロシージャにこれが発生する理由について、誰かが明確にできるでしょうか?
これは、統計ジョブに使用されているコマンドです。
EXECUTE dbo.IndexOptimize
@Databases = 'DB_PRO',
@FragmentationLow = NULL,
@FragmentationMedium = NULL,
@FragmentationHigh = NULL,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y' ,
@TimeLimit = 3600,
@LogToTable = N'Y';
次に、インデックスメンテナンスジョブは次のように実行されます。
sqlcmd -E -S $(ESCAPE_SQUOTE(SRVR)) -d master -Q "EXECUTE [dbo].[IndexOptimize]
@Databases = 'DB_PRO', @TimeLimit = 10800, @LogToTable = 'Y'" -b
質問:統計のメンテナンスについてあまり詳しくないので、すべての統計を更新するために毎週ジョブを個別に実行する必要があるのでしょうか?
はい、テーブルが大きい場合は統計を維持する必要があります。自動統計更新の仕組みについては、こちらをご覧ください。
統計の自動更新オプションの統計は、クエリのコンパイル前またはキャッシュされたクエリプランの実行前にチェックされます。次の場合、統計は古くなったと見なされます。
空のテーブルでデータが変更されました。統計の作成時にテーブルの行数が500以下であり、統計オブジェクトの先頭列の列変更カウンターがそれ以降500以上変更されています。
統計の収集時にテーブルに500行を超える行があり、統計オブジェクトの先頭列の列変更カウンターが、統計の収集時にテーブルの行数の500 + 20%を超えて変更されました。
6行未満のTempDBのテーブルには、少なくとも6行の変更がありました。
質問:ある程度の変更の後、またはインデックスの再構築中に統計が更新されないのですか?
たとえば、ALTER INDEX…REBUILDを使用してインデックスを再構築すると、テーブルがパーティション化されていない限り、WITH FULLSCANを使用した場合と同等のインデックス統計も更新されます。インデックスを再構築しても、列の統計は更新されません。
インデックスの再編成、
aLTER INDEX…REORGANIZEを使用した例では、統計は更新されません。
質問:個別に再計算すると問題が発生するのはなぜですか?
サンプルレートが低く、統計が正確ではない可能性があります。 FULLSCANを使用して、それが役立つかどうかを確認します。カーディナリティ推定が統計を誤って解釈している可能性もあります(SQL Server 2014で発生する可能性があります)。この場合、SQL Server 2014でカーディナルエスティメータを無効にするためにトレースフラグ9481を試してください。
Ola HallengrensスクリプトのStatisticsSampleパラメーターはこれを提供します:
統計の更新時に収集されるテーブルの割合をパーセントで示します。値100は、フルスキャンと同等です。値が指定されていない場合、SQL Serverは必要なサンプルを自動的に計算します。
手動で実行しているUPDATE STATISTICSコマンドが十分な行をサンプリングしていない場合は、誤った見積もりを引き起こしている可能性があり、統計が自動的に更新されるまでパフォーマンスが低下する可能性があります。与えられた情報では、これが報告している問題の原因であるかどうかを知ることはできません。はるかに多くの情報を提供する必要があります。
Showplanをオンにして、統計が更新される前にクエリを実行します。返された実際の行と推定された行を確認します。次に、統計を更新して、もう一度クエリを実行します。実際の行と推定された行が前のテストよりもさらに離れている場合は、手動の統計更新により状況が少し損なわれている可能性があります。
まず、両方のスクリプトが何をしているのかを説明しましょう。 Olaのソリューションは使用しません。私の答えは彼のサイトのドキュメントに基づいています。
私はあなたのコメントから両方のコマンドを受け取りました。
「インデックスの最適化のためのメンテナンススクリプト」と呼ばれる実行中のコマンドは、実際にはインデックスの最適化を行っていませんでした。
EXECUTE dbo.IndexOptimize
@Databases = 'DB_PRO',
@FragmentationLow = NULL,
@FragmentationMedium = NULL,
@FragmentationHigh = NULL,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y' ,
@TimeLimit = 3600,
@LogToTable = N'Y';
@ FragmentationLow、Medium、またはHighにNULL
を渡すと、Do not perform index maintenance.
渡した他の3つのパラメーター値に基づいて、Update statistics only if any rows have been modified since the most recent statistics update
。サンプルの行数を使用して統計を更新します。
DBAが追加した他のコマンドを見てみましょう。
sqlcmd -E -S $(ESCAPE_SQUOTE(SRVR)) -d
master -Q "EXECUTE [dbo].[IndexOptimize]
@Databases = 'DB_PRO', @TimeLimit = 10800, @LogToTable = 'Y'" -b
私が正しく理解していれば、これはReorganize index. Rebuild index online if reorganizing is not supported on an index. Rebuild index offline if reorganizing and online rebuilding are not supported on an index. This is the default for a medium-fragmented index.
5%から30%の間でフラグメント化されたインデックスの場合。
またRebuild index online. Rebuild index offline if online rebuilding is not supported on an index. This is the default for a high-fragmented index.
は、30%以上フラグメント化されたインデックスの場合。
このコマンドは、統計を明示的に更新しません。ただし、一部のインデックス統計は、説明されているように、再構築操作中に更新されます ここ 。
これら2つのスクリプトのシーケンスによって害が発生することはありません。 2番目のスクリプトは、再構築を行う場合、サンプルの統計をフルスキャン(インデックス統計のみ)で上書きします。
ストアドプロシージャは、DBAがメンテナンスジョブを追加する前に正常に動作していたとのことですが、サンプルを使用して統計を更新すると、ストアドプロシージャは正常に動作していました。
理論的には、DBAのステップは、ストアプロシージャの実行速度を低下させる要因にはなりません。しかし、他の人が述べたように、見つける唯一の方法は、両方の実際の実行計画を比較して、違いを確認することです。
また、DBAと話し、Olaのドキュメントを読み、これら2つのコマンドを1つにマージすることをお勧めします。