2013-02-27 13 views
7

LinqToSQLを使用して呼び出すストアドプロシージャがあります。私は特別なことは一切していません。Linqストアドプロシージャタイムアウト、SSMSクイック

MyDataContext db = new MyDataContext() 

var results = db.storedProcedure(param1, param2, param3) 

// Do stuff 

正確に同じパラメータを使用してストアドプロシージャを実行すると、2〜6秒の結果が得られます。データベースはリモートデータベースです。

ただし、ストアドプロシージャを実行すると(デバッグ後に....)275秒かかる!通常の状況下では、これは次の例外与える:

を:

を[Win32Exceptionが(0x80004005が)待機操作がタイムアウトしました] [SQLExceptionが(0x80131904):タイムアウトが発生しました。 System.Data.SqlClient.SqlConnection.OnError(SqlException例外、ブールブレークコネクション、アクション1 wrapCloseInAction) +1753346 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action、1 wrapCloseInAction)+5295154 System.Data.SqlClient.TdsParserこのイベントが発生すると、 .ThrowExceptionAndWarning(TdsParserStateObject stateObj、ブールcallerHasConnectionLock、ブールasyncClose)242 System.Data.SqlClient.TdsParser.TryRun(runBehavior runBehavior、SqlCommandオブジェクトcmdHandler、SqlDataReaderのデータストリーム、BulkCopySimpleResultSet bulkCopyHandler、TdsParserStateObject stateObj、ブール& DATAREADY)1682 System.Data .SqlClient.SqlDataReader.TryConsumeMetaData()+59 System.Data.SqlClient.SqlDataReader.get_MetaData()+90 System.Data.SqlClient.SqlCommand.Finish ExecuteReader(SqlDataReaderのDS、RunBehavior runBehavior、文字列resetOptionsString)365 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehaviorのcmdBehavior、RunBehavior runBehavior、ブールreturnStream、ブール非同期、のInt32のタイムアウト、タスク&タスク、ブールasyncWrite)1325 システム.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmBehavior、RunBehavior runBehavior、Boolean returnStream、Stringメソッド、TaskCompletionSource`1完了、Int32タイムアウト、タスク&タスク、ブールasyncWrite)+175 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehaviorビヘイビア、ストリングメソッド)+134 System.Data.SqlClie nt.SqlCommand.ExecuteDbDataReader(CommandBehaviorビヘイビア)+41 System.Data.Common.DbCommand.ExecuteReader()+12 System.Data.Linq.SqlClient.SqlProvider.Execute(式クエリ、QueryInfo queryInfo、IObjectReaderFactory factory、Object []) +1306 System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(式クエリ、QueryInfo []、queryInfo []、queryObject、IObjectReaderFactory factory、Object [] userArguments、ICompiledSubQuery [])サブクエリ(サブクラス、サブクラス、サブクラス、サブクラス) )+118 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(式クエリ)+342 System.Data.Linq.DataContext.ExecuteMethodCall(Object instance、MethodInfo methodInfo、Object [])パラメータ)+83

他のすべてのストアドプロシージャは同じ方法で呼び出されますが、この問題はありません。リモートのDB管理者は、タイムアウトが発生する前にコールの開始と終了を見ることができるので、Linqがデータを受信した後の手順と関係しているようです。

これを経験したことがありますか?

私はdmblファイルからSPを削除して再追加しようとしました。それは10進数から2倍に変更された値の1つに気付きましたが、それ以外はすべて同じです。

いつものように、それは昨日うまくいきました!

ありがとうございます。

答えて

3

私は最終的にこの問題のREALの答えを発見しました。 SSMSは通常、ARITHABORT ONを使用し、コードは通常ARITHABORT OFFを使用します。これは基本的に、コード内の数学的な行にエラーがある場合の処理​​方法のオプションです。ゼロで割る。

しかし、ここで重要なのは、両方の方法が異なる実行計画を持っていることです。つまり、SSMSよりも同じことが(ランダムに)ウェブサイト上で長くかかることがあります。

実行計画は、最初に使用された見積もりに基づいてコンパイルされるため、ランダムに見つかるものは、実行計画が最初の問合せに適しているが後続の問合せにとって恐ろしい方法でキャッシュされるということです。これはここで起きたことであり、突然再び突然開始した理由です。ストアドプロシージャの変更後に新しいクエリプランが作成されました。

最後に、ストアドプロシージャでWITH RECOMPILEを使用しました。そのため、実行プランを効率的に再利用することはできませんでしたが、とにかく差異に気付かずに問題が発生していません。

0

この問題の原因はLinq.Table < > .Count()に依存していました。開発環境では、基礎となるクエリはほとんど瞬時に行われますが、実稼働では数秒かかりました。 SQLプロファイラーを接続すると、ループの各反復でクエリが実行されたため、「数秒」が加算されて最終的にタイムアウトになりました。

解決策は、Count()の結果をローカル変数に代入してループ内で使用して、Count()が各繰り返しでクエリを再実行しないようにすることでした。私は、遅いクエリを再実行する組み込みのLinq集約関数に依存する場合、他の人がこの問題を経験するだろうと思います。