Linq存储过程超时但SSMS快速

McG*_*Gaz 7 sql linq timeout linq-to-sql

我有一个存储过程,我使用LinqToSQL调用.我根本没做什么特别的事,比如说

MyDataContext db = new MyDataContext()

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

// Do stuff
Run Code Online (Sandbox Code Playgroud)

当我使用完全相同的参数运行存储过程时,我得到2到6秒之间的结果.该数据库是一个远程数据库.

但是,当我运行存储过程时(经过调试......)275秒!在正常情况下,这会产生以下异常:

[Win32Exception(0x80004005):等待操作超时]

[SqlException(0x80131904):超时已过期.操作完成之前经过的超时时间或服务器没有响应.] System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolean breakConnection,Action 1 wrapCloseInAction) +1753346 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction)+5295154 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning( TdsParserStateObject stateObj,Boolean callerHasConnectionLock,Boolean asyncClose)+242 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean&dataReady)+1682 System.Data.SqlClient.SqlDataReader.TryConsumeMetaData ()+59 System.Data.SqlClient.SqlDataReader.get_MetaData()+90 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,String resetOptionsString)+365 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior ,RunBehavior runBehavior,Boolean returnStream,Boolean async,Int32 timeout,Task&task,Boolean asyncWrite)+1325 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method,TaskCompletionSource`1 completion,Int32 timeout,Task&task,Boolean asyncWrite)+175 System.Data.SqlClient.SqlCommand .RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method)+53 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior,String method)+134 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)+41 System.Data.Common.DbCommand.ExecuteReader()+12 System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query,QueryInfo queryInfo,IObjectReaderFactory factory,Object [] parentArgs,Object [] userArgs,ICompiledSubQuery [] subQueries,Object lastResult)+1306 System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query,QueryInfo [] queryInfos,IObjectReaderFactory factory,Object [] userArguments,ICompiledSubQuery [] subQueries)+118 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)+342 System.Data.Linq.DataContext.ExecuteMethodCall(Object instance,MethodInfo methodInfo,Object []参数)+83

所有其他存储过程都以相同的方式调用,但没有一个存在此问题.远程数据库管理员说他可以在超时发生之前看到呼叫开始和结束,所以它似乎与Linq接收数据后的步骤有关.

有没有人经历过这个以及任何想法如何解决它?

我尝试从dmbl文件中删除SP并重新添加它.它注意到其中一个值从十进制变为双精度,但除此之外全部相同.

一如既往,昨天工作正常!

提前致谢.

McG*_*Gaz 4

好吧,我终于找到了这个问题的真正答案。SSMS 通常使用 ARITHABORT ON,代码通常使用 ARITHABORT OFF - 这基本上是一个选项,用于如何处理代码中的数学行出现错误(例如除以零)时发生的情况。

不过,这里最重要的是,两种方法都有不同的执行计划 - 这就是为什么同一件事在网站上(随机)比在 SSMS 中花费更长的时间。

执行计划是根据第一次使用的估计进行编译的,因此您随机发现执行计划的缓存方式很糟糕,适合您的第一个查询,但对于后续查询来说却很糟糕。这就是这里发生的情况,也是它突然再次开始工作的原因 - 在更改存储过程后创建了一个新的查询计划。

最后我们在存储过程中使用了WITH RECOMPILE - 因此没有有效地重用执行计划,但无论如何我们没有注意到任何差异,并且此后问题也没有发生。