最初から私の質問/問題はこの前のものと似ていると言いますが、原因または開始情報が同じであるかどうかわからないため、質問をいくつか詳細に投稿することにしました。
手元の問題:
- 奇妙な時間(営業日の終わり近く)に、本番インスタンスの動作が不安定になります。
- インスタンスのCPU使用率が高い(ベースラインが約30%の場合、約2倍になり、まだ増加し続けていた)
- 1秒あたりのトランザクション数の増加(ただし、アプリの負荷には変化が見られません)
- アイドルセッションの数の増加
- この動作を表示しなかったセッション間の奇妙なブロッキングイベント(コミットされていない読み取りセッションでもブロッキングが発生していました)
- 間隔の上位の待機は1位で非ページラッチで、ロックは2位でした。
初期調査:
- sp_whoIsActiveを使用して、監視ツールによって実行されたクエリが非常に低速で実行され、大量のCPUを取得することを決定したことがわかりました。
- その分離レベルはコミットされずに読み取られました。
- 奇妙な数字が見られた計画を調べました。StatementEstRows= "3.86846e + 010"で、約150 TBの推定データが返されます。
- 監視ツールのクエリモニター機能が原因であると考えたため、この機能を無効にしました(プロバイダーにチケットを開いて、問題が発生しているかどうかを確認しました)
- その最初のイベントから、それはさらに数回起こりました。セッションを終了するたびに、すべてが通常に戻ります。
- クエリがクエリストアの監視のためにBOLでMSによって使用されるクエリの1つに非常に類似していることがわかります-パフォーマンスが最近低下したクエリ(異なる時点での比較)
- 同じクエリを手動で実行し、同じ動作を確認します(使用されるCPUが増え続ける、ラッチ待機が増える、予期しないロックなど)。
有罪の質問:
Select qt.query_sql_text,
q.query_id,
qt.query_text_id,
rs1.runtime_stats_id AS runtime_stats_id_1,
interval_1 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi1.start_time),
p1.plan_id AS plan_1,
rs1.avg_duration AS avg_duration_1,
rs2.avg_duration AS avg_duration_2,
p2.plan_id AS plan_2,
interval_2 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi2.start_time),
rs2.runtime_stats_id AS runtime_stats_id_2
From sys.query_store_query_text AS qt
Inner Join sys.query_store_query AS q
ON qt.query_text_id = q.query_text_id
Inner Join sys.query_store_plan AS p1
ON q.query_id = p1.query_id
Inner Join sys.query_store_runtime_stats AS rs1
ON p1.plan_id = rs1.plan_id
Inner Join sys.query_store_runtime_stats_interval AS rsi1
ON rsi1.runtime_stats_interval_id = rs1.runtime_stats_interval_id
Inner Join sys.query_store_plan AS p2
ON q.query_id = p2.query_id
Inner Join sys.query_store_runtime_stats AS rs2
ON p2.plan_id = rs2.plan_id
Inner Join sys.query_store_runtime_stats_interval AS rsi2
ON rsi2.runtime_stats_interval_id = rs2.runtime_stats_interval_id
Where rsi1.start_time > DATEADD(hour, -48, GETUTCDATE())
AND rsi2.start_time > rsi1.start_time
AND p1.plan_id <> p2.plan_id
AND rs2.avg_duration > rs1.avg_duration * 2
Order By q.query_id, rsi1.start_time, rsi2.start_time
設定と情報:
- Windows Server 2012R2クラスター上のSQL Server 2016 SP1 CU4 Enterprise
- クエリストアを有効にし、デフォルトとして構成(設定は変更されません)
- SQL 2005インスタンスからインポートされたデータベース(互換性レベル100のまま)
経験的観察:
- 非常に奇妙な統計のため、不適切な推定計画で使用されているすべての* plan_persist **オブジェクトを取得し(実際の計画はまだない、クエリが完了しない)、統計を確認しました。計画で使用されているインデックスの一部には統計がありませんでした(DBCC SHOWSTATISTICSは何も返しませんでした。sys.statsから選択すると、一部のインデックスに対してNULL stats_date()関数が表示されました
迅速で汚れたソリューション:
- クエリストアに関連するシステムオブジェクトの不足している統計を手動で作成する、または
- 新しいCE(トレースフラグ)を使用してクエリを強制的に実行します。これにより、必要な統計情報も作成/更新されます。
- データベースの互換性レベルを130に変更します(デフォルトで新しいCEを使用します)
だから、私の本当の質問は:
クエリストアのクエリがインスタンス全体でパフォーマンスの問題を引き起こすのはなぜですか?クエリストアのバグ領域にいますか?
PS:いくつかのファイル(印刷画面、IO統計、計画)を少しでアップロードします。
Dropboxに追加されたファイル。
計画1-生産における最初の奇抜な推定計画
計画2-テスト環境での実際の計画、古いCE(同じ動作、同じ奇抜な統計)
計画3-テスト環境での実際の計画、新しいCE