web-dev-qa-db-ja.com

以前は高速だったSQLクエリの実行が遅くなった場合、問題の原因をどこで見つければよいですか?

背景

約12の異なる「テーブル」を結合または左結合するSQL Server 2008 R2に対して実行するクエリがあります。データベースはかなり大きく、5,000万行を超える多くのテーブルと約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のキャッシュされた実行プランがどのように設定されているかによると結論付けました-クエリが少し異なる場合、新しい実行プランを作成する必要があります。

私の質問はこれです:高速で実行されていたクエリが真夜中に突然ゆっくりと実行を開始し、この1つのクエリ以外は何も影響を受けない場合、トラブルシューティング方法と方法それが将来起こらないようにしますか?どのようにしてSQLが内部で実行しているのでそれを遅くするのかを知るには(悪いクエリが実行された場合、その実行プランを取得できますが、実行されません-予想される実行プランが何かを与えるでしょうか?)?この問題が実行プランに関連している場合、SQLが本当にひどい実行プランが良いアイデアであると考えないようにするにはどうすればよいですか?

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

39
Trevor

以前は高速で実行されていたクエリが、真夜中に突然ゆっくりと実行を開始し、この1つのクエリ以外は何も影響を受けない場合、どのようにトラブルシューティングすればよいですか?

まず、実行プランがまだキャッシュにあるかどうかを確認します。チェック 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サーバーのメモリ許可について を参照してください。クエリが利用可能なメモリがない瞬間に大規模な許可を要求する場合、クエリは待機する必要があり、すべてアプリケーションに対して「実行が遅い」ように見えます。 wait info stats を分析すると、これが当てはまるかどうかがわかります。

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

33
Remus Rusanu

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

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

OPTION (MERGE JOIN, HASH JOIN)

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

発生している可能性があるのは、テーブルへの微妙な変更(または一時スペースの可用性)により、SQL最適化がより遅い結合アルゴリズムを優先することです。これは非常に微妙で突然発生する可能性があります。一時テーブルを作成すると、オプティマイザはテーブルに関する詳細(サイズなど)を取得できるため、より適切な計画を生成できます。

7
Gordon Linoff

最近、同じ問題が発生し、このページが表示されました。

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

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

これが誰かを助けることを願っています

3
daffyjeje

通常、それはこの種の問題を引き起こしている欠落しているインデックスです。

私が通常行うことは、SQL Management Studioを使用してクエリを実行し、[実際の実行計画を含める(CTRL + M)]を有効にして、どの結合が最大のパーセンテージを持っているかを調べます。

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

ここの例: 48PercentForTop

3
Xavier

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

0
Amol Nimbalkar