我有一个导入到 EF4 中的存储过程,当我在 30 秒后使用某些参数调用它时,它会抛出超时错误。在 SQL Server Profiler 中,我可以看到使用正确参数的存储过程调用仅花费了 30 秒多一点,这是我的应用程序的超时时间。
然而,当我执行发送到查询分析器中的探查器的相同 SQL 时,它会执行亚秒。什么可能导致从 EF 调用和从 SQL Server Management Studio 调用之间存在这种差异?
.NET 错误的完整堆栈跟踪如下。
[SqlException (0x80131904):超时已过期。超时时间
操作完成之前已过去或服务器未完成
回应。]
System.Data.SqlClient.SqlConnection.OnError(SqlException异常,
布尔中断连接)+2073486
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
异常,布尔中断连接)+5064444
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +234
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,
SqlCommand cmdHandler、SqlDataReader 数据流、
BulkCopySimpleResultSet BulkCopyHandler、TdsParserStateObject
状态对象)+2275
System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +33
System.Data.SqlClient.SqlDataReader.get_MetaData() +86
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,
RunBehavior runBehavior,字符串resetOptionsString)+311
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior
cmdBehavior、RunBehavior runBehavior、布尔值 returnStream、布尔值
异步)+987
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior、RunBehavior runBehavior、布尔值 returnStream、字符串
方法,DbAsyncResult 结果)+162
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior、RunBehavior runBehavior、布尔值 returnStream、字符串
方法)+32
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior
行为,字符串方法)+141
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior
行为)+12
System.Data.Common.DbCommand.ExecuteReader(CommandBehavior行为)
+10 System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand
实体命令、CommandBehavior 行为)+443
[EntityCommandExecutionException:执行时发生错误
命令定义。有关详细信息,请参阅内部异常。]
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand
实体命令、CommandBehavior 行为)+479
System.Data.Objects.ObjectContext.CreateFunctionObjectResult(EntityCommand
实体命令、实体集实体集、EdmType edmType、MergeOption
合并选项)+182
System.Data.Objects.ObjectContext.ExecuteFunction(字符串函数名,
MergeOption mergeOption、ObjectParameter[] 参数)+218
System.Data.Objects.ObjectContext.ExecuteFunction(字符串函数名,
ObjectParameter[] 参数)+53
MetaView.DAL.MFCMData.MFCMDATAEntities.GetTradingOpenPositionCounterParty(可为空1
positionDT, Nullable
1个交易账户ID)中
C:\Projects\CASH\web\MetaView\MetaView.DAL.MFCMData\MFCMData.Designer.cs:7064
MetaView.BusinessLayer.Shared.Accounts.CounterParties.GetCounterParties(Int32
交易账户ID)中
C:\Projects\CASH\web\MetaView\MetaView.BusinessLayer\Shared\Accounts\CounterParties.cs:161
几周前我遇到了一个类似的问题,我们的一位 DBA 向我解释了这个问题(当然根据我的水平进行了解释和简化):
当调用 SQL Server 存储过程时,服务器会为每个存储过程创建并缓存一个执行计划per object_id
。有时,SQL Server 可能会根据传入的参数值创建错误的执行计划(在我们的示例中,对于可为空的参数,它为 null)。发生这种情况时,快速修复方法是运行sp_recompile 'Schema.Procedure'
在 SQL Server Management Studio(或您可能使用的任何数据库管理工具)中。这一切所做的就是清除该存储过程的计划缓存。如果过程的下一个被调用者再次传入“坏”参数值,您将陷入相同的情况所以真正的解决方法是使用以下命令给查询一个提示OPTIMIZE FOR
语法(参见http://msdn.microsoft.com/en-gb/library/ms181714.aspx http://msdn.microsoft.com/en-gb/library/ms181714.aspx).
简而言之,如果您添加OPTION (OPTIMIZE FOR (@myParameter = 'Some value that gives you a GOOD execution plan'))
在你之后WHERE
and/or ORDER BY
条款应该解决这个问题。
另外,如果您想知道为什么执行时sameSSMS 中的 SQL 总是能快速获得结果,这是因为 SSMS 的 ARITHABORT 选项的默认设置为 ON(SET ARITHABORT ON
),所有其他应用程序默认设置为关闭,但它的工作原理及其影响超出了我的经验,我没有费心去阅读它。我被告知我不应该使用它。我确信真正的 DBA 可以更好地解释原因。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)