17

我有一个导入 EF4 的存储过程,当我在 30 秒后使用某些参数调用它时,它会引发超时错误。在 SQL Server 探查器中,我可以看到带有正确参数的存储过程调用仅用了 30 多秒,这是我的应用程序的超时时间。

但是,当我在查询分析器中执行发送到探查器的相同 SQL 时,它会在亚秒内执行。什么可能导致从 EF 调用和从 SQL Server Management Studio 调用之间的这种差异?

.NET 错误的完整堆栈跟踪如下。

[SqlException (0x80131904): 超时。操作完成前超时时间已过或服务器没有响应。]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +2073486
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +5064444
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +234
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +2275
System.Data.SqlClient。 SqlDataReader.ConsumeMetaData() +33
System.Data.SqlClient.SqlDataReader.get_MetaData() +86
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +311
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +987
System.Data.SqlClient .SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +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 entityCommand,CommandBehavior 行为)+443

[EntityCommandExecutionException:执行命令定义时发生错误。有关详细信息,请参阅内部异常。]
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +479
System.Data.Objects.ObjectContext.CreateFunctionObjectResult(EntityCommand entityCommand, EntitySet entitySet, EdmType edmType, MergeOption mergeOption) +182
System.Data.Objects.ObjectContext.ExecuteFunction(String functionName, MergeOption mergeOption, ObjectParameter[] parameters) +218
System.Data.Objects.ObjectContext.ExecuteFunction(String functionName, ObjectParameter[] parameters) +53
MetaView.DAL.MFCMData.MFCMDATAEntities .GetTradingOpenPositionCounterParty(可空1 positionDT, Nullable1 tradingAccountID) 在 C:\Projects\CASH\web\MetaView\MetaView.DAL.MFCMData\MFCMData.Designer.cs:7064 MetaView.BusinessLayer.Shared.Accounts.CounterParties.GetCounterParties(Int32 tradingAccountID) 在 C:\Projects\CASH \web\MetaView\MetaView.BusinessLayer\Shared\Accounts\CounterParties.cs:161

4

1 回答 1

24

所以几周前我遇到了一个类似的问题,我们的一位 DBA 向我解释了这个问题(当然是转述并降低到我的水平):

调用 SQL Server 存储过程时,服务器会为每个存储过程创建并缓存一个执行计划object_id。有时,SQL Server 可能会根据传入的参数值创建错误的执行计划(在我们的例子中,可空参数为空)。发生这种情况时,快速解决方法是sp_recompile 'Schema.Procedure'在 SQL Server Management Studio(或您可能使用的任何数据库管理工具)中运行。所有这些都是清除该存储过程的计划缓存。如果 proc 的下一个被调用者再次传入“错误”参数值,您将陷入同样的​​情况,因此真正的解决方法是OPTIMIZE FOR使用语法为查询提供提示(请参阅http://msdn.microsoft.com /en-gb/library/ms181714.aspx)。

简而言之,如果您在and/or子句OPTION (OPTIMIZE FOR (@myParameter = 'Some value that gives you a GOOD execution plan'))之后添加它应该可以解决问题。WHEREORDER BY

另外,如果您想知道为什么在 SSMS 中执行相同的SQL 时总是能得到快速的结果,这是因为 SSMS 有一个名为 ARITHABORT ( ) 的选项的默认设置为 ON SET ARITHABORT ON,所有其他应用程序都默认设置为 OFF,但它是如何设置的作品及其影响超出了我的经验,我没有费心去阅读它。我被告知我不应该使用它。我确信真正的 DBA 可以更好地解释原因。

于 2013-04-02T20:00:09.737 回答