2013-04-02 34 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