2013-04-02 31 views
14

我有一个存储过程导入到EF4中,当我在30秒后调用某些参数时,它会引发超时错误。在SQL Server分析器中,我可以看到存储过程调用的正确参数只需要超过30秒,这是我的应用程序的超时。实体框架4存储过程调用时序输出

但是,当我执行发送到查询分析器中的分析器的相同SQL时,它会执行亚秒。从EF调用和从SQL Server Management Studio调用之间有什么不同?

.NET错误以下全堆栈跟踪。

[SqlException(0x80131904):超时已过期。超时周期 之前的操作的完成经过或服务器不是 响应。]
System.Data.SqlClient.SqlConnection.OnError(SqlException异常, 布尔breakConnection)2073486
System.Data.SqlClient.SqlInternalConnection .OnError(SQLEXCEPTION 例外,布尔breakConnection)5064444
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()234
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, 的SqlCommand cmdHandler,SqlDataReader的数据流, 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,字符串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 entityCommand,CommandBehavior be havior)+443

[EntityCommandExecutionException:执行 命令定义时发生错误。详情请参阅内部异常。]
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand,行为的CommandBehavior)479
System.Data.Objects.ObjectContext。CreateFunctionObjectResult(EntityCommand entityCommand,EntitySet的EntitySet的,EdmType edmType,MergeOption mergeOption)182
System.Data.Objects.ObjectContext.ExecuteFunction(字符串functionName,而 MergeOption mergeOption,ObjectParameter []参数)218
System.Data。 Objects.ObjectContext.ExecuteFunction(字符串functionName,而 ObjectParameter []参数)53
MetaView.DAL.MFCMData.MFCMDATAEntities.GetTradingOpenPositionCounterParty(可空1 positionDT, Nullable 1 tradingAccountID)在 C:\项目\ CASH \网络\ MetaView \ MetaView.DAL .MFCMData \ MFCMData.Designer.cs:7064 MetaView.BusinessLayer.Shared.Accounts.CounterParties .GetCounterParties(的Int32 tradingAccountID)在 C:\项目\ CASH \网络\ MetaView \ MetaView.BusinessLayer \共享\帐户\ CounterParties.cs:161

+0

请发布查询和两个执行计划。 – usr

回答

23

所以我有一个类似的问题在几个星期前,这是我们的一位DBA向我解释的(当然,我的DBA解释了这一点):

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

总之,如果您在WHERE和/或ORDER BY条款后面添加OPTION (OPTIMIZE FOR (@myParameter = 'Some value that gives you a GOOD execution plan'))它应该解决问题。

另外,如果你想知道为什么在执行中SSMS的相同 SQL时,你总能得到快速的结果,那是因为SSMS有对所有其他应用程序都设置为一个名为ARITHABORT选项(SET ARITHABORT ON)默认设置默认情况下是关闭的,但是它的工作原理及其含义超出了我的经验,我也没有仔细阅读过它。我被告知我不应该使用它。我确信一个真正的DBA可以更好地解释原因。

+1

Re:**服务器为每个调用应用程序(或每个连接字符串)创建并缓存每个存储过程的执行计划,但我没有记错。该计划根据'object_id'进行缓存,对于ad hoc sql,'object_id'基于查询文本的哈希值(假设所有字符都是二进制比较)。 –

+1

@srutzky谢谢,我修改了答案:) – alimbada

+0

我有一个函数(与AS TABLE)相同的问题,但OPTION(OPTIMIZE ...)在这种情况下似乎不起作用。你有什么想法来解决我的问题? – toregua