以前に高速なSQLクエリの実行が遅くなった場合、どこで問題の原因を見つけることができますか?


36

バックグラウンド

私は、約12の異なる「テーブル」を結合および/または左結合するSQL Server 2008 R2に対してクエリを実行しています。データベースはかなり大きく、5000万行を超える多くのテーブルと約300の異なるテーブルがあります。全国に10の倉庫がある大企業向けです。すべての倉庫は、データベースに対して読み取りと書き込みを行います。だから、かなり大きくてかなり忙しい。

私が問題を抱えているクエリは次のようになります:

select t1.something, t2.something, etc.
from Table1 t1
    inner join Table2 t2 on t1.id = t2.t1id
    left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
    [etc]...
where t1.something = 123

結合の1つが非相関サブクエリ上にあることに注意してください。

問題は、今朝から、システムに変更を加えずに(私または私のチームの誰もが知っている)、クエリの実行に通常約2分かかり、実行に1時間半かかることです。まったく走った。データベースの残りの部分はうまくいっています。私は通常実行するsprocからこのクエリを取り出し、同じスローネスでハードコードされたパラメータ変数を使用してSSMSで実行しました。

奇妙なことに、非相関サブクエリを取得して一時テーブルにスローし、サブクエリの代わりにそれを使用すると、クエリは正常に実行されます。また、このコードをクエリの最後に追加すると、クエリが非常によく実行されます(これは私にとって最も奇妙なことです)。

and t.name like '%'

これらの小さな実験から、スローダウンの理由は、SQLのキャッシュされた実行計画の設定方法によるものであると(おそらく間違って)結論付けました-クエリが少し異なる場合、新しい実行計画を作成する必要があります。

私の質問は次のとおりです:高速で実行されていたクエリが深夜に突然遅くなり、このクエリ以外に何も影響を受けない場合、どのようにトラブルシューティングし、今後発生しないようにするのですか? ?SQLが内部で何をして非常に遅くするかを知るには(悪いクエリが実行された場合、実行計画は取得できますが、実行されません-予想される実行計画が何かを与えるでしょうか?)この問題が実行計画に関連している場合、SQLが本当にくだらない実行計画は良いアイデアだと考えないようにするにはどうすればよいですか?

また、これはパラメータースニッフィングの問題ではありません。SSMSで変数をハードコーディングした場合でも、パフォーマンスが低下するため、これは以前見たことがありますが、そうではありません。


クエリプラン(遅いもの)をここで共有してもらえますか: brentozar.com/pastetheplan
MJH

回答:


31

かつて高速で実行されていたクエリが深夜に突然遅くなり、このクエリ以外に何も影響がない場合、どのようにトラブルシューティングすればよいですか?

実行計画がまだキャッシュにあるかどうかを確認することから開始できます。確認しsys.dm_exec_query_statssys.dm_exec_procedure_statsそしてsys.dm_exec_cached_plans。不良な実行計画がまだキャッシュされている場合、分析でき、実行統計を確認することもできます。実行統計には、論理読み取り、CPU時間、実行時間などの情報が含まれます。これらは、問題が何であるかを強力に示すことができます(たとえば、大規模なスキャンとブロッキング)。データの解釈方法の説明については、問題のある照会の識別を参照してください。

また、これはパラメータースニッフィングの問題ではありません。SSMSで変数をハードコーディングした場合でも、パフォーマンスが低下するため、これは以前見たことがありますが、そうではありません。

私は確信していません。SSMSのハードコーディング変数は、過去の不正な実行計画が歪んだ入力に対してコンパイルされなかったことを証明しません。このトピックに関する非常に優れた記事については、パラメータスニッフィング、埋め込み、およびRECOMPILEオプションをお読みください。アプリケーションが遅く、SSMSが速い?パフォーマンスミステリーを理解すること も、もう1つの優れたリファレンスです。

これらの小さな実験から、スローダウンの理由は、SQLのキャッシュされた実行計画の設定方法によるものであると(おそらく間違って)結論付けました-クエリが少し異なる場合、新しい実行計画を作成する必要があります。

これは簡単にテストできます。SET STATISTICS TIME ONコンパイル時間と実行時間を表示します。SQL Server:Statisticsパフォーマンスカウンターは、コンパイルが問題であるかどうかも明らかにします(率直に言って、私はそれがありそうもないと思います)。

ただし、ヒットする可能性のある類似したものがあります。クエリ許可ゲートです。詳細については、SQLサーバーのメモリ許可についてをご覧ください。クエリが使用可能なメモリがない瞬間に大きな許可を要求する場合、待機する必要があり、アプリケーションに対してはすべて「遅い実行」のように見えます。待機情報の統計を分析すると、これが当てはまるかどうかがわかります。

何を測定し、何を探すべきかについてのより一般的な議論については、SQL Serverのパフォーマンスを分析する方法を参照してください。


7

これは、SQL Serverで複雑なクエリを実行する際の悩みの種です。幸いなことに、それはそれほど頻繁には起こりません。

クエリのクエリプランを確認します(実行速度が遅い場合)。結合のインデックスがないテーブルで、ネストされたループ結合が1回以上発生することがわかると思います。これは本当に物事を遅くします。早送りするには、これを修正する方法にヒントがあります。クエリの最後に次を追加します。

OPTION (MERGE JOIN, HASH JOIN)

これにより、過去にこの問題が一般的に修正されました。

何が起こっているのかは、テーブル(または一時スペースの可用性)に対する微妙な変更により、SQL最適化がより遅い結合アルゴリズムを好むようになることです。これは非常に微妙で、突然発生する可能性があります。一時テーブルを作成すると、オプティマイザーはテーブルに関するより多くの情報(サイズなど)を持つため、より良いプランを生成できます。


1
実際、実行計画はネストされたループ結合を使用しています。ただし、提案どおりにヒントを配置すると、次のエラーが表示されます。「このクエリで定義されたヒントのため、クエリプロセッサはクエリプランを作成できませんでした。ヒントを指定せず、SET FORCEPLANを使用せずにクエリを再送信してください」もちろん、OPTION(LOOP JOIN)を追加すると、実行計画が作成されますが、実行に時間がかかるという問題がまだあります。この問題に遭遇しましたか?ループ結合が必要だと思われるようです。

@Trevor 。。いいえ、私は実際にこの問題を見たことはありません。クエリで非等結合(等号を使用しない)を実行している場合、オプティマイザはそこでネストされたループ結合を使用する必要があります。
ゴードンリノフ14年

3

通常、この種の問題の原因となるインデックスの欠落です。

私が通常行うことは、SQL Management Studioを使用してクエリを実行し、「実際の実行計画を含める(CTRL + M)」を有効にして、どの結合が最も高い割合を持っているかを調べることです。

アプリケーションはボトルネックに焦点を合わせていませんが、結果を調べるだけで「すばやく」見つけることができます。

例: 48PercentForTop


2
インデックスが突然、これはパフォーマンスを向上させるかもしれないが、しかし、それは問題で説明していない「行方不明」に行くことはありません
家禽

3

私は最近、このページに私をもたらしたこの同じ問題を経験しました。

@MartinSmithは、統計と説明計画を更新することを勧めたとき、何かに夢中になりました。また、ロックを作成して応答時間を遅くする可能性のあるジョブ/クエリの実行を確認するようにしてください。

私の場合、犯人はテーブル統計を収集する仕事でした。何らかの理由で、本来あるべきウィンドウで完了せず、ユーザーが再開したときに実行を続けました。プロセスを見つけて強制終了し、クエリが再び応答し始めました。

これが他の人の助けになることを願っています


0

また、T-SQL \ Procedureでパフォーマンスの問題が発生した場合、サーバーバックアップまたはアーカイブ/インデックス作成ジョブが実行されているかどうかを確認する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.