7

我有一个使用 LinqToSQL 调用的存储过程。我根本没有做任何特别的事情,例如

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 exception, Boolean breakConnection, Action1 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 stateObjHandler, TdsParser , 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 方法, TaskCompletionSource`1 完成, Int32 超时, Task& 任务, Boolean asyncWrite) +175 System.Data.SqlClient.SqlCommand .RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String 方法) +53 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior 行为, String 方法) +134 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior 行为) +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,对象 lastResult)+1306 System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(表达式查询,QueryInfo[] queryInfos,IObjectReaderFactory 工厂,Object[] userArguments,ICompiledSubQuery[] subQueries)+118 System.Data.Linq.SqlClient.SqlProvider。 System.Data.Linq.Provider.IProvider.Execute(表达式查询)+342 System.Data.Linq.DataContext.ExecuteMethodCall(对象实例,MethodInfo methodInfo,Object[]参数)+83对象[] 参数)+83对象[] 参数)+83

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

以前有没有人经历过这种情况以及如何解决它的任何想法?

我尝试从 dmbl 文件中删除 SP 并重新添加它。它注意到其中一个值从十进制变为双精度,但除此之外都是一样的。

和往常一样,昨天工作正常!

提前致谢。

4

2 回答 2

4

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

不过,这里的主要问题是两种方法都有不同的执行计划——这就是为什么同样的事情在网站上可能(随机)花费比在 SSMS 中更长的时间。

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

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

于 2013-07-18T15:04:53.407 回答
0

对我来说导致这个问题的原因是一个依赖于 Linq.Table< >.Count() 的循环。在开发环境中,底层查询几乎是即时的,但在生产环境中需要几秒钟。连接 SQL Profiler 显示查询是在循环的每次迭代中执行的,因此那些“几秒钟”开始累加,最终超时。

我的解决方案是将 Count() 结果分配给局部变量,并在循环中使用它,这样 Count() 就不会在每次迭代时重新执行查询。我想如果其他人依赖内置的 Linq 聚合函数来重新执行慢速查询,他们会遇到这个问题。

于 2013-03-03T18:10:04.647 回答