Mam procedurę składowaną, która niesamowicie przekracza limit czasu za każdym razem, gdy jest wywoływana z aplikacji internetowej.
Uruchomiłem Sql Profiler i prześledziłem wywołania, które wygasły, i w końcu odkryłem następujące rzeczy:
- Po wykonaniu instrukcji z poziomu MS SQL Management Studio, z tymi samymi argumentami (w rzeczywistości skopiowałem wywołanie procedury ze śledzenia profilu sql i uruchomiłem je): Kończy się średnio za 5 ~ 6 sekund.
- Jednak wywołanie z aplikacji internetowej zajmuje ponad 30 sekund (w śledzeniu), więc moja strona internetowa faktycznie wygasa do tego czasu.
Poza tym, że moja aplikacja internetowa ma własnego użytkownika, wszystko jest takie samo (ta sama baza danych, połączenie, serwer itp.) Próbowałem również uruchomić zapytanie bezpośrednio w studio z użytkownikiem aplikacji internetowej i nie zajmuje to więcej niż 6 sek.
Jak dowiedzieć się, co się dzieje?
Zakładam, że nie ma to nic wspólnego z faktem, że używamy warstw BLL> DAL lub adapterów tabeli, ponieważ ślad wyraźnie pokazuje, że opóźnienie występuje w rzeczywistej procedurze. To wszystko, o czym mogę myśleć.
EDYCJA Dowiedziałem się z tego linku, że ADO.NET ustawia wartość ARITHABORT
na true - co jest dobre przez większość czasu, ale czasami tak się dzieje, a sugerowanym obejściem jest dodanie with recompile
opcji do przechowywanego proc. W moim przypadku to nie działa, ale podejrzewam, że jest to coś bardzo podobnego do tego. Czy ktoś wie, co jeszcze robi ADO.NET lub gdzie mogę znaleźć specyfikację?
źródło
Odpowiedzi:
W przeszłości miałem podobny problem, więc nie mogę się doczekać rozwiązania tego pytania. Komentarz Aarona Bertranda na temat OP doprowadził do przekroczenia limitu czasu Query podczas wykonywania z sieci, ale bardzo szybkiego w przypadku wykonywania z SSMS i chociaż pytanie nie jest powtórzeniem, odpowiedź może bardzo dobrze dotyczyć Twojej sytuacji.
Zasadniczo wygląda na to, że SQL Server może mieć uszkodzony plan wykonania w pamięci podręcznej. Uderzasz w zły plan ze swoim serwerem sieciowym, ale SSMS ląduje na innym planie, ponieważ jest inne ustawienie flagi ARITHABORT (która w przeciwnym razie nie miałaby wpływu na twoje konkretne zapytanie / przechowywane proc).
Zobacz ADO.NET wywołanie procedury składowanej T-SQL powoduje SqlTimeoutException dla innego przykładu z pełniejszym wyjaśnieniem i rozwiązaniem.
źródło
DBCC DROPCLEANBUFFERS
iDBCC FREEPROCCACHE
załatwiłem sprawę! Domyślam się, że plan wykonania był w jakiś sposób uszkodzony lub nie został zaktualizowany. Wątpię, czy jest to trwała poprawka, gdyby raz mogła ulec uszkodzeniu, mogłaby to zrobić ponownie. Więc wciąż szukam prawdopodobnych przyczyn. Ponieważ aplikacja internetowa znów działa, nie muszę czuć presji. Dzięki wielkie.OPTIMIZE FOR
lubOPTION(Recompile)
zapytać o wskazówki dotyczące zapytań, które powodują problemy. W tym artykule szczegółowo omówiono problem. Jeśli Entity Framework generuje zapytania, ten wpis wydaje się zapewniać sposób dodawania wskazówki dotyczącej zapytania do zapytań.Doświadczam również, że zapytania działały powoli z sieci i szybko w SSMS i ostatecznie odkryłem, że problem był czymś, co nazywa się wykrywaniem parametrów.
Rozwiązaniem dla mnie była zmiana wszystkich parametrów używanych w sproc na zmienne lokalne.
na przykład. zmiana:
do:
Wydaje się dziwne, ale rozwiązało mój problem.
źródło
Nie po to, by spamować, ale jako miejmy nadzieję pomocne rozwiązanie dla innych, nasz system doświadczył wielu przekroczeń czasu.
Próbowałem ustawić procedurę składowaną do ponownej kompilacji przy użyciu
sp_recompile
i rozwiązało to problem z jednym SP.Ostatecznie istniała większa liczba SP, które przekraczały limit czasu, z których wiele nigdy wcześniej tego nie robiło, przez używanie,
DBCC DROPCLEANBUFFERS
aDBBC FREEPROCCACHE
wskaźnik przekroczenia czasu incydentu znacznie spadł - nadal istnieją odosobnione zdarzenia, niektóre, w których podejrzewam, że trwa regeneracja planu jakiś czas, a niektóre, w których PS są naprawdę słabe i wymagają ponownej oceny.źródło
DBCC DROPCLEANBUFFERS
iDBCC FREEPROCCACHE
nie robiły różnicy.Czy może być tak, że niektóre inne wywołania bazy danych wykonane przed wywołaniem aplikacji internetowej, SP utrzymują transakcję otwartą? Może to być powód, dla którego ten SP musi czekać na wywołanie przez aplikację internetową. Mówię, że wyodrębnij połączenie w aplikacji internetowej (umieść je na nowej stronie), aby upewnić się, że przyczyną tego problemu jest jakieś wcześniejsze działanie w aplikacji internetowej.
źródło
Po prostu rekompilacja procedury składowanej (w moim przypadku funkcja tabeli) zadziałała
źródło
jak @Zane powiedział, że może to być spowodowane wykrywaniem parametrów. Doświadczyłem tego samego zachowania i przyjrzałem się planowi wykonania procedury i wszystkim oświadczeniom sp w wierszu (skopiowałem wszystkie instrukcje z procedury, zadeklarowałem parametry jako zmienne i przypisałem te same wartości do zmiennej jako parametry miały). Jednak plan wykonania wyglądał zupełnie inaczej. Wykonanie sp trwało 3-4 sekundy, a instrukcje z rzędu z dokładnie tymi samymi wartościami zostały natychmiast zwrócone.
Po pewnym googlowaniu znalazłem interesującą lekturę na temat tego zachowania: Wolno w aplikacji, Szybko w SSMS?
Problem polegał na tym, że miałem parametry, które można było pozostawić puste i jeśli zostałyby przekazane jako null, zostałyby zainicjalizowane z wartością domyślną.
Po zmianie na
znowu zadziałało jak urok.
źródło