46

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

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

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

4

8 に答える 8

44

C# コードはアドホック SQL クエリを SQL Server に送信していますが、どの方法を使用していますか? ストアド プロシージャの使用を検討したことがありますか。これにより、誰が呼び出したかに関係なく、(少なくともエンジン内で) 同じパフォーマンスが保証されるでしょう。

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

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

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

SET ARITHABORT ON; SELECT ...

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

于 2010-02-11T23:27:05.737 に答える
17

この回答には、この問題を解決する方法が含まれています。

データベースで管理者として次のコマンドを実行すると、ARITHABORT の設定に関係なく、すべてのクエリが期待どおりに実行されます。

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

アップデート

ほとんどの人がこの問題に遭遇することはめったにないようで、上記のテクニックは 1 回限りの適切な修正方法です。ただし、特定のクエリでこの問題が複数回発生する場合、この問題に対するより長期的な解決策は、この記事で説明されている ようOPTIMIZE FORに、 や などのクエリ ヒントを使用することです。OPTION(Recompile)

更新 2

SQL Server ではクエリ実行プラン アルゴリズムがいくつか改善されており、このような問題は新しいバージョンではますますまれになっています。この問題が発生している場合は、実行しているデータベースの互換性レベルの設定を確認することをお勧めします (必ずしもクエリを実行しているデータベースではなく、デフォルトのデータベース、つまり「InitialCatalog」)。繋がり)。古い互換性レベルに固執している場合は、古いクエリ実行プラン生成手法を使用することになり、不適切なクエリが生成される可能性がはるかに高くなります。

于 2011-10-06T15:53:01.233 に答える
4

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

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

これは元のポスターが望んでいるものではないかもしれませんが、同じ問題を抱えている人を助けるかもしれないことを私は理解しています。

于 2012-08-17T15:35:22.927 に答える
0

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

于 2016-01-08T19:20:22.033 に答える