T-SQLストアドプロシージャを呼び出すADO.NETにより、SqlTimeoutExceptionが発生します
署名付きのT-SQLストアドプロシージャがあります
CREATE PROCEDURE MyProc
@recordCount INT OUTPUT
@param1 INT
...
SQL Serverで直接実行すると、プロシージャは5秒未満で実行され、合計で約100行になるいくつかの結果セットが返されます。
ADO.NETを使用してこのプロシージャを呼び出すSqlDataAdapter.Fill
メソッドでDataset
を設定すると、3分後(指定されたタイムアウト間隔)にSqlTimeoutException
にSqlCommand
が発生します。
ストアドプロシージャを変更して、出力パラメータがなくなり、必要な出力値が最後の結果セットとして返されるようにすると、問題が解決し、すべてが期待どおり5秒未満で実行されます。
しかし、なぜ?
私が本当に問題を解決したかどうかを理解せずに、コードベースを調べてこのタイプの動作のすべてのインスタンスを変更したくありません。
もう1つの注意点は、これは1つの特定のサーバーでのみ明らかであり、実行している他の同様のデータベースよりも大きなデータセットがあることは確かです。確かにSQLServerの設定ではありませんか?
[〜#〜] update [〜#〜]
フレームワークソースに足を踏み入れると、問題はメタデータの取得にあるようです。 ConsumeMetaData
オブジェクトのSqlDataReader
メソッドが無期限にハングします。ただし、他のデータベースでテストを実行して再現できないため、このプロシージャがADO.NETを介して呼び出された場合のデータベース固有の問題です...すばらしい。
アップデートII
SQLOLEDBまたはSQLNCLIプロバイダータイプでOleDbDataAdapter
を使用するようにコードを変更しても、問題が引き続き発生することを確認しました。間違いなく接続と関係があります。
問題の根本にあるのはADO.NET接続であると判断すると、この thread が答えにつながりました。
基本的に、SQL Server Management Studio(SSMS)を介した接続には、デフォルトでSET ARITHABORT ON
があります。 ADO.NET接続はそうではありません。
ARITHABORT OFF
を設定し、SSMSを介して直接クエリを実行すると、同じように応答時間が遅くなります。
この設定の有無にかかわらず実行する場合の主な違いは、2つの呼び出しに対して異なるクエリプランが作成されることです。 ARITHABORT
がOFF
の場合、SSMSコマンドは、ADO.NET接続が使用していたコンパイル済みのキャッシュクエリプランを使用するため、タイムアウトになります。
データベースの管理者として次のコマンドを実行すると、ARITHABORT
の設定に関係なく、すべてのクエリが期待どおりに実行されます。
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
コンパイルされたクエリプランが破損しているか、無効になっているとしか考えられません。
私はこれを他の解決策(私は答えに賛成票を投じました)として使用します スレッド
ありがとう。
私は正直に立っています-はい、あなた[〜#〜] can [〜#〜]両方を持っています-OUTPUTパラメータと返される行のセット。あなたは毎日何か新しいことを学びます:-)
タイムアウトが発生する理由については、うーん....わかりにくいです。簡単な小さなサンプルは私にとってはうまくいきます。ストアドプロシージャ(少なくともその関連ビット)を投稿できますか?
ここに返される行はいくつありますか?
ストアドプロシージャのどの時点で、OUTPUTパラメータとして返す必要のある行数を計算していますか?
テストとして別のパラメーターMaxRows
を1つのSProcに追加し、データに対してSELECT TOP (@MaxRows).......
を実行しようとするとどうなりますか?それはすぐに戻りますか?
マーク
つまり、SQL Serverがそれ自体で理解できない場合に、最も適切なインデックスを使用してlob論理読み取りを制限するように強制することで問題を修正しました。
長い間-
私はちょうどこの問題に遭遇し、他のすべての提案された答えを試した後、別の方法でそれを解決しました。 SSMSでは、クエリは約3秒で実行されていましたが、.Net MVCWebアプリケーションから呼び出されたときにタイムアウトしていました。
統計IO SSMSの出力は、1つのテーブルに195,500,000を超えるLOB論理読み取りがあったことを示していました(クラスター化された列ストアインデックスを持ち、行インデックスもあるが、「LOB」がない20M行のテーブル実行計画から、負荷の大部分(76%)が行インデックスの1つでのインデックスシークから発生していることに気付きました。次を使用しました。
from [table] with (index([clustered columnstore index name]))
クエリでクラスター化列ストアインデックスの使用を強制すると、クエリが1秒未満に減少し、LOB論理読み取りが1億9500万を超えるから6k未満に低下し、WebからSPアプリは現在、1.3秒でラウンドトリップしています。
オプションの再コンパイル、arithabortの設定、パラメーターのスニッフィングを試しましたが、最終的にSQLServerは使用するインデックスを特定できませんでした。これはエッジのケースでもあり、このデータベースでインデックスを強制する必要があるのはこのときだけです。