データベースSQL Server 2017 Enterprise CU16 14.0.3076.1
最近、デフォルトのインデックス再構築メンテナンスジョブからOla Hallengren IndexOptimize
に切り替えてみました。デフォルトのインデックス再構築ジョブは数か月間問題なく実行されており、クエリと更新は許容可能な実行時間で機能していました。データベースでIndexOptimize
を実行した後:
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 = 5,
@FragmentationLevel2 = 30,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y'
パフォーマンスが極端に低下しました。 IndexOptimize
の前に100ミリ秒かかった更新ステートメントは78.000ミリ秒かかり(同じプランを使用)、クエリも数桁悪いパフォーマンスを示しました。
これはまだテストデータベースなので(Oracleから本番システムを移行しています)、バックアップに戻ってIndexOptimize
を無効にし、すべてを通常に戻しました。
ただし、IndexOptimize
が「通常の」Index Rebuild
とは異なる動作をすることを理解したいと思います。これにより、本番環境に移行したときに確実に回避するために、この極端なパフォーマンス低下を引き起こした可能性があります。何を探すべきかについての提案は大歓迎です。
遅い場合のupdateステートメントの実行計画。つまり.
IndexOptimize後
実際の実行計画(できるだけ早く)
違いを見つけることができませんでした。
同じクエリが高速な場合に計画する
実際の実行計画
2つのメンテナンスアプローチ間で異なる サンプルレート が定義されていると思います。 @StatisticsSample
parameter を指定しない限り、Olaのスクリプトはデフォルトのサンプリングを使用していると思います。これは、現在実行しているようには見えません。
この時点でこれは推測ですが、データベースで次のクエリを実行することで、統計で現在使用されているサンプリングレートを確認できます。
SELECT OBJECT_SCHEMA_NAME(st.object_id) + '.' + OBJECT_NAME(st.object_id) AS TableName
, col.name AS ColumnName
, st.name AS StatsName
, sp.last_updated
, sp.rows_sampled
, sp.rows
, (1.0*sp.rows_sampled)/(1.0*sp.rows) AS sample_pct
FROM sys.stats st
INNER JOIN sys.stats_columns st_col
ON st.object_id = st_col.object_id
AND st.stats_id = st_col.stats_id
INNER JOIN sys.columns col
ON st_col.object_id = col.object_id
AND st_col.column_id = col.column_id
CROSS APPLY sys.dm_db_stats_properties (st.object_id, st.stats_id) sp
ORDER BY 1, 2
これが1秒(100%など)の可能性がある場合は、これが問題である可能性があります。おそらく、このクエリによって返されるパーセンテージを含む@StatisticsSample
パラメータを含むOlaのスクリプトを再試行して、問題が解決するかどうかを確認してください。
この理論を裏付ける追加の証拠として、実行プランXMLは、スロークエリの非常に異なるサンプリングレート(2.18233%)を示しています。
<StatisticsInfo LastUpdate="2019-09-01T01:07:46.04" ModificationCount="0"
SamplingPercent="2.18233" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]"
Schema="[SVALA]" Database="[ulek-sva]" />
高速クエリとの比較(100%):
<StatisticsInfo LastUpdate="2019-08-25T23:01:05.52" ModificationCount="555"
SamplingPercent="100" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]"
Schema="[SVALA]" Database="[ulek-sva]" />
ジョンの答え が正しい解決策です。これは、実行プランのどの部分が変更されたか、および Sentry One Plan Explorer を使用して簡単に違いを見つける方法の例に関する追加です。
IndexOptimizeが78.000ミリ秒かかるまでに100ミリ秒かかった更新ステートメント(同じプランを使用)
パフォーマンスが低下したときにすべてのクエリプランを見ると、違いを簡単に見つけることができます。
パフォーマンスの低下
35秒を超えるCPU時間と経過時間の2つのカウント
期待されるパフォーマンス
はるかに良い
主な低下は、この更新クエリで2回です:
UPDATE SVALA.INGÅENDEANALYS
SET
UPPDRAGAVSLUTAT = @NEW$AVSLUTAT
WHERE INGÅENDEANALYS.ID IN
(
SELECT IA.ID
FROM
SVALA.INGÅENDEANALYS AS IA
JOIN SVALA.INGÅENDEANALYSX AS IAX
ON IAX.INGÅENDEANALYS = IA.ID
JOIN SVALA.ANALYSMATERIAL AS AM
ON AM.ID = IA.ANALYSMATERIALID
JOIN SVALA.ANALYSMATERIALX AS AMX
ON AMX.ANALYSMATERIAL = AM.ID
JOIN SVALA.INSÄNTMATERIAL AS IM
ON IM.ID = AM.INSÄNTMATERIALID
JOIN SVALA.INSÄNTMATERIALX AS IMX
ON IMX.INSÄNTMATERIAL = IM.ID
WHERE IM.UPPDRAGSID = SVALA.PKGSVALA$STRIPVERSION(@NEW$ID)
)
パフォーマンスが低下したこのクエリの実行プラン
この更新クエリの推定クエリプランは、パフォーマンスが低下したときの推定が非常に高くなっています。
実際には(実際の実行計画)、それでも機能する必要がありますが、見積もりが示す狂った量ではありません。
パフォーマンスへの最大の影響は、以下の2つのスキャンとハッシュ一致結合です。
パフォーマンス低下の実際のスキャン#1
パフォーマンス低下の実際のスキャン#2
予想されるパフォーマンスを備えたこのクエリの実行プラン
これをクエリプランの推定値(または実績値)と通常の予想パフォーマンスと比較すると、違いを簡単に見つけることができます。
また、前の2つのテーブルアクセスは発生しませんでした。
ビルド(トップ)入力が最初にハッシュテーブルに挿入されるため、ハッシュ結合ではこの削除は見られません。その後、このハッシュテーブルでゼロ値がプローブされ、ゼロ値が返されます。
詳細情報がないと、暗闇の中で情報の少ない刺し傷しか受けられないため、質問を編集してもう少し詳しく説明する必要があります。たとえば、インデックスの統計が更新されたために計画が異なる可能性があるため、インデックスのメンテナンス操作の前後に、タイミングを指定したその更新ステートメントのクエリプラン( https://www.brentozar .com/pastetheplan / これは、XMLの巨大なチャンクである可能性のあるもので質問を埋めたり、計画のテキストに含まれる関連情報の一部が含まれていないスクリーングラブを与えたりするのではなく、これに役立ちます) 。
ただし、2つの非常に単純な点が次のとおりです。