web-dev-qa-db-ja.com

クエリはWebから実行するとタイムアウトしますが、SSMSから実行すると超高速になります

私が管理しているWebアプリケーションでSQLタイムアウトの原因をデバッグしようとしています。 C#コードのソースコードが後ろにあるので、実行されているコードを正確に把握しています。タイムアウトしたSQLコードを実行する行までアプリケーションをデバッグし、SQLプロファイラーでクエリが実行されていることを確認しました。

このクエリがWebから実行されると、30秒後にタイムアウトになります。ただし、Profilerに表示されているとおりにクエリをカットアンドペーストし、SSMSに入れて実行すると、ほぼ瞬時に返されます。 Webが使用している接続でARITHABORTがOFFに設定されている問題を追跡しました(つまり、SSMSセッションでARITHABORTをOFFにすると長時間実行され、ONに戻すと実行されます)非常に迅速に)。ただし、ARITHABORTの説明を読んで、それが適用されていないようです...私は単純なSELECTを実行しているだけで、計算はまったく実行されません.. WHERE条件を持つ単一のINNER JOINのみ:

ARITHABORT OFFがこのコンテキストでこの動作を引き起こしているのはなぜですか? SSMSからその接続のARITHABORT設定を変更する方法はありますか? SQL Server 2008を使用しています。

41
Michael Bray

したがって、C#コードは、SQL ServerにアドホックSQLクエリを送信しています。ストアドプロシージャの使用を検討しましたか?だれがそれを呼び出したかにかかわらず、(少なくともエンジンでは)同じパフォーマンスが保証されます。

どうして? ARITHABORT設定は、オプティマイザーがクエリの実行方法(具体的には、プランのマッチング)を決定するときに確認するものの1つです。キャッシュ内のプランがSSMSと同じ設定を持っている可能性があるため、キャッシュされたプランを使用しますが、反対の設定では、C#コードが再コンパイルを強制しています(または、実際に[〜#〜] bad [〜#〜]キャッシュ内のプラン)。これは、多くの場合、確かにパフォーマンスを低下させる可能性があります。

ストアドプロシージャを既に呼び出している場合(クエリを投稿しなかったが、意図したとおりだったと思われます)、ストアドプロシージャの問題のあるクエリ(複数可)にOPTION(RECOMPILE)を追加してみてください。これは、それらのステートメントが常に再コンパイルされることを意味しますが、ヒットしているように見える悪い計画の使用を防ぐことができます。別のオプションは、ストアドプロシージャがコンパイルされるときに、バッチがSET ARITHABORT ONで実行されることを確認することです。

最後に、SSMSでARITHABORT設定を変更する方法を尋ねているようです。あなたが質問するつもりだったのは、コードでARITHABORT設定を強制する方法です。 C#アプリからアドホックSQLを送信し続ける場合は、もちろん、コマンドをセミコロンで区切った複数のステートメントを含むテキストとして送信できます。

SET ARITHABORT ON; SELECT ...

この問題が発生する理由の詳細については、Erland Sommarskogのすばらしい記事を参照してください。

39
Aaron Bertrand

これまで何度もこの問題がありましたが、同じ問題のあるストアドプロシージャがある場合は、ストアドプロシージャを削除して再作成すると問題が解決します。

これはパラメータースニッフィングと呼ばれます。今後この問題を回避するには、ストアドプロシージャのパラメーターを常にローカライズする必要があります。

これは元の投稿者が望んでいることではないかもしれないが、同じ問題のある人を助けるかもしれないことを理解しています。

4
Novice in.NET

Entity Frameworkを使用する場合、文字列値のクエリパラメーターはデフォルトでnvarcharとしてデータベースに送信されることに注意してください。比較するデータベース列が型付きvarcharの場合、照合に応じて、クエリ実行プランで "IMPLICIT CONVERSION"ステップが必要になる場合があります。完全スキャンを強制します。実行プランを表示する高価なクエリオプションでデータベース監視を確認することで確認できます。

最後に、この記事のこの動作に関する説明: https://www.sqlskills.com/blogs/jonathan/implicit-conversions-that-c​​ause-index-scans/

1
edumen

同じ問題がありましたが、 "WITH RECOMPILE"プロシージャを実行することで修正されました。パラメータスニッフィングを使用することもできます。私の問題はSQLキャッシュに関連していました。

0
Manmeet

コードを変更してパラメータスニッフィングを修正できる場合は、不明なヒントを最適化するのが最適なオプションです。コードを変更できない場合、最良のオプションはexec sp_recompile 'name of proc'です。これにより、その1つのストアドプロシージャのみが新しい実行プランを取得するよう強制されます。プロシージャを削除して再作成しても同様の効果がありますが、削除したまま誰かがプロシージャを実行しようとすると、エラーが発生する可能性があります。 DBCC FREEPROCCACHEはすべてのキャッシュされたプランを削除します。これにより、負荷の高いトランザクションの運用環境でシステムを破壊し、タイムアウトを引き起こす可能性があります。 arithabortの設定は問題の解決策ではありませんが、パラメーターのスニッフィングが問題であるかどうかを発見するための有用なツールです。

0
N. Rhoades

SP SMSSから2秒かかりましたが、webapp(ASP.NET)から約3分かかりましたが、同じ問題があります。

提案されたすべての解決策を試しましたsp_recompileDBCC FREEPROCCACHEおよびDBCC DROPCLEANBUFFERSしかし、何も私の問題を修正しませんでしたが、パラメータスニッフィングを試みたときに、それはうまくいきました。

0
Karim Tawfik