2013-04-02 16 views
14

Mam procedura składowana zaimportowana do EF4, a kiedy wywołuję ją z pewnymi parametrami po 30 sekundach, generuje błąd przekroczenia limitu czasu. W programie SQL Server profiler widzę wywołanie procedury przechowywanej z właściwymi parametrami, biorąc pod uwagę nieco ponad 30 sekund, co jest limit czasu w mojej aplikacji.Entity Framework 4 Procedura składowana Czas oczekiwania na wywołanie

JEDNAK, kiedy wykonuję ten sam SQL wysłany do profilera w Query Analyzer, wykonuje podsekund. Co może spowodować tę rozbieżność między wywołaniem z EF a wywołaniem z SQL Server Management Studio?

Pełny ślad stosu .NET error poniżej.

[SqlException (0x80131904): Limit czasu wygasł. Limit okresu czasu upłynął przed zakończeniem operacji, lub serwer jest odpowiadać.]
System.Data.SqlClient.SqlConnection.OnError (wyjątek SQLException, logiczna breakConnection) +2073486
System.Data.SqlClient.SqlInternalConnection .OnError (SQLException wyjątkiem, logiczna 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, logiczna returnStream, logiczna asynchroniczny) +987
System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String metoda wynik DbAsyncResult) +162
System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, logiczna returnStream, String metoda) +32
System.Data.SqlClient.SqlCommand.ExecuteReader (CommandBehavior zachowanie, sposób ciąg) +141
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader (CommandBehavior zachowanie) +12
System.Data.Common.DbCommand.ExecuteReader (zachowanie CommandBehavior) +10 System.Data.EntityClient.EntityCommandDefinition .ExecuteStoreCommands (EntityCommand entityCommand, CommandBehavior be havior) +443

[EntityCommandExecutionException: Wystąpił błąd podczas wykonywania definicji polecenia. Patrz wewnętrzną wyjątek dla szczegółów.]
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand zachowanie CommandBehavior) +479
System.Data.Objects.ObjectContext.CreateFunctionObjectResult (EntityCommand entityCommand, EntitySet EntitySet, EdmType edmType, MergeOption mergeOption) +182
System.Data.Objects.ObjectContext.ExecuteFunction (ciąg functionName, MergeOption mergeOption [] Parametry ObjectParameter) +218
System.Data. Objects.ObjectContext.ExecuteFunction (ciąg functionName, ObjectParameter [] parametry) +53
MetaView.DAL.MFCMData.MFCMDATAEntities.GetTradingOpenPositionCounterParty (Nullable 1 positionDT, Nullable 1 tradingAccountID) w C: \ Projects \ ŚRODKÓW \ wWW \ MetaView \ MetaView.DAL .MFCMData \ MFCMData.Designer.cs: 7064 MetaView.BusinessLayer.Shared.Accounts.CounterParties .GetCounterParties (Int32 tradingAccountID) w C: \ Projects \ CASH \ web \ MetaView \ MetaView.BusinessLayer \ Shared \ Accounts \ CounterParties.cs: 161

+0

Proszę zaksięgować zapytanie i oba plany wykonania. – usr

Odpowiedz

23

Więc miałem podobny problem kilka tygodni temu , który wyjaśnił mi przez jednego z naszych administratorów thusly (parafrazując i dumbed dół do mojego poziomu kształcenia):

Gdy procedura przechowywana SQL Server nazywa, serwer tworzy i buforuje plan wykonania za procedury przechowywanej os object_id. Czasami zły plan wykonania może być utworzony przez SQL Server w zależności od podanej wartości parametru (w naszym przypadku była ona zerowa dla parametru zerowalnego). Kiedy tak się dzieje, szybką poprawką jest uruchomienie sp_recompile 'Schema.Procedure' w SQL Server Management Studio (lub dowolnym narzędziu do zarządzania bazą danych, z którego korzystasz). Wszystko to robi wyczyść pamięć podręczną planu dla tej procedury przechowywanej. Jeśli następny uczestnik procesu przejdzie ponownie w "złej" wartości parametru, utkniesz w tej samej sytuacji: , więc prawdziwa poprawka to podać zapytanie wskazówkę, używając składni OPTIMIZE FOR (patrz http://msdn.microsoft.com/en-gb/library/ms181714.aspx).

W skrócie, jeśli dodasz OPTION (OPTIMIZE FOR (@myParameter = 'Some value that gives you a GOOD execution plan')) po klauzulach WHERE i/lub ORDER BY, powinieneś rozwiązać ten problem.

Ponadto, jeśli zastanawiasz się, dlaczego podczas wykonywania samą SQL w SSMS zawsze uzyskać szybkie rezultaty to dlatego SSMS posiada domyślne ustawienie ON dla opcji o nazwie ARITHABORT (SET ARITHABORT ON), który wszystkie inne aplikacje zostały ustawione na WYŁĄCZONE domyślnie, ale jak to działa i jakie są jego implikacje, są poza moim doświadczeniem i nie zadałem sobie trudu, aby to przeczytać. Powiedziano mi, że nie powinienem tego używać. Jestem pewien, że prawdziwy DBA może lepiej wyjaśnić dlaczego.

+1

Re: ** serwer tworzy i buforuje plan wykonania dla procedury składowanej na aplikację wywołującą (lub na ciąg połączenia.nie pamiętam poprawnie). ** W rzeczywistości nie jest to ani. Plan jest buforowany według "object_id", a w przypadku sql ad hoc "object_id" jest oparty na haszu tekstu zapytania (przy założeniu binarnego porównania wszystkich znaków). –

+1

@ śrutzky dzięki, zmieniłem odpowiedź :) – alimbada

+0

Mam exaclty ten sam problem z FUNCTION (z AS TABLE), ale OPTION (OPTIMIZE ...) nie wydają się działać w tym kontekście. Czy masz jakiś pomysł na rozwiązanie mojego problemu? – toregua

Powiązane problemy