Dlaczego moje zapytanie jest nagle wolniejsze niż wczoraj?

76

[Pozdrowienia]

(Sprawdź jeden)

[ ] Well trained professional, [ ] Casual reader, [ ] Hapless wanderer,

Mam (zaznacz wszystkie, które dotyczą)

[ ] query [ ] stored procedure [ ] database thing maybe  

działało dobrze (jeśli dotyczy)

[ ] yesterday [ ] in recent memory [ ] at some point 

ale nagle jest teraz wolniejszy.

Już sprawdziłem, aby upewnić się, że nie jest blokowany i że nie jest ofiarą jakiegoś długotrwałego zadania konserwacyjnego, raportu lub innego procesu poza pasmem.

Na czym polega problem, co powinienem zrobić i jakie informacje mogę podać, aby uzyskać pomoc?

[*Insert appropriate closing remarks*]
Erik Darling
źródło

Odpowiedzi:

88

Drogi [tu twoje imię]!

Och nie, przykro mi to słyszeć! Zacznijmy od podstaw, aby szybko naprawić problem.

Rzecz, na którą się napotykasz, nazywa się wąchaniem parametrów

To wyjście dziwnie dziwny problem. Nazwa zjeżdża z języka. Jak niemieckie słowo wiewiórka.

I zwykle jest to twój przyjaciel.

Gdy zapytanie trafi na twój serwer, plan musi zostać skompilowany. Aby zaoszczędzić czas i zasoby później, plan wykonania jest buforowany na podstawie szacunkowych wierszy, które parametr spowoduje przetworzenie i zwrócenie kodu.

Najłatwiejszym sposobem na zobrazowanie tego, co się psuje, jest wyobrażenie sobie procedury składowanej, która musi liczyć rzeczy z dwóch krzywych populacji.

Na przykład:

  • Ludzie noszący koszulki CrossFit, którzy nie są ranni: zero

  • Ludzie w koszulach CrossFit, którzy skrzywią się, gdy skrzywią się: Wszyscy

Oczywiście, jedno wykonanie tego kodu musiałoby wykonać znacznie więcej pracy niż inne, a plany zapytań, które chcielibyście wykonać zupełnie inaczej, wyglądałyby zupełnie inaczej.

Co mam przeciwko?

Jest to naprawdę trudny problem do znalezienia, przetestowania i rozwiązania.

  • Trudno go znaleźć, ponieważ nie dzieje się to konsekwentnie
  • Trudno to przetestować, ponieważ musisz wiedzieć, które parametry powodują różne plany
  • Trudno to naprawić, ponieważ czasami wymaga strojenia zapytań i indeksów
  • Trudno to naprawić, ponieważ zmiana zapytań lub indeksów może być niemożliwa
  • Trudno to naprawić, ponieważ nawet jeśli zmienisz zapytania lub indeksy, nadal może wrócić

Szybkie poprawki

Czasami wszystko czego potrzebujesz to odrobina jasności. A raczej pamięć podręczna planu działa.

Jeśli jest to procedura składowana

Spróbuj uruchomić EXEC sys.sp_recompile @objname = N'schema.procname'. Spowoduje to, że procedura ponownie skompiluje nowy plan przy następnym uruchomieniu.

Czego to nie naprawi:

  • Procesy aktualnie go uruchamiające.

Czego to nie gwarantuje:

  • Następny proces, który zostanie uruchomiony po ponownej kompilacji, użyje parametru, który daje dobry plan.

Możesz także wskazać sp_recompiletabelę lub widok, ale ostrzegaj, że cały kod, który dotyka tej tabeli lub widoku, zostanie ponownie skompilowany. To może znacznie utrudnić problem.

Jeśli jest to sparametryzowane zapytanie

Twoja praca jest trochę trudniejsza. Musisz wyśledzić uchwyt SQL. Nie chcesz zwolnić całej pamięci podręcznej planu - tak jak przy użyciu sp_recompiletabeli lub widoku, możesz wywołać (ha ha ha) całą masę niezamierzonych konsekwencji.

Najłatwiejszym sposobem wymyślenia tego polecenia jest uruchomienie sp_BlitzWho *! Istnieje kolumna o nazwie „sniffing parametru naprawy”, który zawiera polecenie usunięcia pojedynczego planu z pamięci podręcznej. Ma to jednak te same wady co podczas ponownej kompilacji.

Czego to nie naprawi:

  • Procesy aktualnie go uruchamiające.

Czego to nie gwarantuje:

  • Następny proces, który zostanie uruchomiony po ponownej kompilacji, użyje parametru, który daje dobry plan.

Nadal potrzebuję pomocy!

Będziemy potrzebować następujących rzeczy:

  • Dobry plan zapytań, jeśli to możliwe
  • Zły plan zapytań
  • Zastosowane parametry
  • Zapytanie, o którym mowa
  • Definicje tabel i indeksów

Uzyskiwanie planów zapytań i zapytania

Jeśli zapytanie jest uruchomione, możesz użyć sp_BlitzWho * lub sp_WhoIsActive do przechwytywania aktualnie wykonywanych zapytań.

EXEC sp_BlitzWho;

EXEC sp_WhoIsActive @get_plans = 1;

ORZECHY

Jeśli zapytanie nie jest aktualnie wykonywane, możesz je sprawdzić w pamięci podręcznej planu, używając sp_BlitzCache *.

Jeśli korzystasz z SQL Server 2016+ i masz włączony Query Store, możesz użyć sp_BlitzQueryStore *.

EXEC dbo.sp_BlitzCache @StoredProcName = 'Your Mom';

EXEC dbo.sp_BlitzQueryStore @StoredProcName = 'Your Mom';

Pomogą ci one wyśledzić buforowane wersje procedury składowanej. Jeśli jest to tylko sparametryzowany kod, wyszukiwanie jest nieco trudniejsze. Może to jednak pomóc:

EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';

Powinieneś zobaczyć dość podobny wynik z każdego z nich. Ponownie, plan zapytań zapraszający do fajnej niebieskiej, klikalnej kolumny jest twoim przyjacielem.

ORZECHY

Najłatwiejszym sposobem udostępniania planów jest użycie opcji Wklej plan * lub zrzucenie pliku XML do pastebinu. Aby to uzyskać, kliknij jedną z zaproszonych niebieskich, klikalnych kolumn. Twój plan zapytań powinien pojawić się na nowej karcie SSMS.

ORZECHY

Jeśli masz problem z udostępnianiem kodu i zapytania swojej firmy, możesz użyć bezpłatnego narzędzia Eksploratora planów Sentry One do anonimizacji swojego planu. Pamiętaj, że utrudnia to uzyskanie pomocy - anonimowy kod jest znacznie trudniejszy do odczytania i zrozumienia.

Wszystkie te narzędzia, o których mówiliśmy, powinny zwrócić tekst zapytania. Nie musisz tutaj nic więcej robić.

Uzyskanie parametrów jest nieco trudniejsze. Jeśli korzystasz z Eksploratora planu , na dole znajduje się karta z listą wszystkich dostępnych opcji.

ORZECHY

Jeśli używasz sp_BlitzCache *, istnieje klikalna kolumna, która zawiera instrukcję wykonania dla procedur przechowywanych.

ORZECHY

Uzyskiwanie definicji tabel i indeksów

Możesz łatwo kliknąć prawym przyciskiem myszy w SSMS, aby wykonać skrypt.

ORZECHY

Jeśli chcesz uzyskać wszystko w jednym ujęciu, sp_BlitzIndex * może pomóc, jeśli skierujesz go bezpośrednio na stół.

EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
                       @SchemaName = 'dbo',
                       @TableName = 'Users';

To da ci definicję tabeli (choć nie jako instrukcję create) i tworzy instrukcje dla wszystkich twoich indeksów.

Zbieranie i dodawanie tych informacji do pytania powinno zapewnić ludziom wystarczającą ilość informacji, aby pomóc, lub skierować cię w dobrym kierunku.

Chcę to zrobić sam!

Cóż, spoko. Cieszę się z ciebie Jesteś szaloną osobą.

Istnieje wiele sposobów, w jakie ludzie myślą, że „naprawiają” wąchanie parametrów:

Ale tak naprawdę po prostu wyłączają wąchanie parametrów na różne sposoby. Nie oznacza to, że nie mogą rozwiązać problemu, po prostu tak naprawdę nie docierają do pierwotnej przyczyny.

To dlatego, że dotarcie do pierwotnej przyczyny jest zwykle trochę trudne. Musisz szukać tych irytujących „problemów z jakością planu”.

Zaczynając od szybkich i wolnych planów, poszukaj różnic takich jak:

  • Zastosowane indeksy
  • Dołącz do zamówienia
  • Szeregowy a równoległy

Poszukaj także różnych operatorów, które uwrażliwiają twój kod na wąchanie parametrów:

  • Wyszukiwania
  • Sortuje
  • Wpisz typ
  • Przydziały pamięci (i przez rozszerzenie, wycieki)
  • Szpule

Nie skupiaj się zbytnio na wyszukiwaniu kontra skanowaniu, fragmentacji indeksów ani żadnej z kultowych rzeczy, którymi ludzie się zajmują.

Zwykle istnieje dość podstawowy problem z indeksowaniem. Czasami kod wymaga trochę przepisania.

Jeśli chcesz dowiedzieć się więcej o węszeniu parametrów:

Jeśli to czytasz i uważasz, że przegapiłem link lub pomocne narzędzie, zostaw komentarz. Zrobię co w mojej mocy, aby to aktualizować.


Erik Darling
źródło
28

Wąchanie parametrów nie jest jedyną możliwą przyczyną zróżnicowanej wydajności zapytania. Każdy z następujących typowych powodów może wykazywać te same objawy:

  1. Zmieniono rozkład / objętość danych, przekraczając punkt krytyczny decyzji drzewa wyszukiwania optymalizatora
  2. Indeksy / pliki uległy fragmentacji
  3. Statystyki zostały zaktualizowane / dodane / usunięte lub stały się nieaktualne i mylące z powodu zmian danych
  4. Zmieniono wykorzystanie pamięci systemu Windows
  5. Dzienniki transakcji są pełne i nie są obcinane, co powoduje wielokrotne fizyczne rozszerzanie plików
  6. Schemat zmieniony - indeks / indeksowany widok / kolumna / ograniczenie dodane, zmodyfikowane lub usunięte, zmieniony typ danych itp.
  7. Ustawienia flagi śledzenia zostały zmienione
  8. Zastosowano aktualizację systemu Windows
  9. Ustawienia bazy danych lub serwera zostały zmienione
  10. Zmieniono poziom CU serwera
  11. Ustawienia sesji aplikacji klienta uległy zmianie

Pozycje 6–11 na tej liście mogą nastąpić dopiero po podjęciu wyraźnych działań. Wydaje mi się, że chciałeś je wykluczyć, ale wiele razy ten, który doświadcza wyzwania, nie zdaje sobie sprawy z tego, że ktoś dokonał zmian i warto to sprawdzić, zanim wyruszasz na ścieżkę czyszczenia wpisów w pamięci podręcznej planu.

SQLRaptor
źródło
1
Dzięki za edycję Paul. @sp_BlitzErik - Nie miałem zamiaru udzielać porad na określone tematy, tylko po to, aby podnieść świadomość ich istnienia i być może warto je sprawdzić. Nie ma to w żaden sposób umniejszyć twojego świetnego posta. Z parametrami wąchałeś dogłębnie, profesjonalnie i z dobrym humorem. Lubiłem to czytać. Chcę się tylko upewnić, że jeśli ktoś tutaj odwiedzi ten post, po chwytliwym tytule, dowie się o alternatywnych potencjalnych przyczynach. IMHO dodaje wartość Twojemu wpisowi, ale jeśli nadal chcesz, żebym go usunął, daj mi znać.
SQLRaptor
Nie, wcale nie. Nigdy nie prosiłbym kogoś o usunięcie odpowiedzi, która nie jest niepoprawna ani szkodliwa. Nadal uważam, że możesz dodać trochę szczegółów, ale to ostatecznie zależy od ciebie.
Erik Darling,
10

Aby dodać do istniejących odpowiedzi na wypadek, gdyby nie pomogły, gdy „nagle” Twoje zapytania zachowają się inaczej następnego dnia, sprawdź:

  • Czy schemat używanych tabel zmienił się od ostatniego razu? W przypadku SSMS możesz kliknąć prawym przyciskiem myszy serwer w Eksploratorze obiektów i wybrać Reports → Standard Reports → Schema Changes History.
  • Czy liczba przedmiotów gwałtownie wzrosła? Być może twoje zapytanie jest o wiele wolniejsze, gdy w używanych tabelach jest dużo danych.
  • Czy ktoś korzysta z bazy danych w tym samym czasie co Ty? Może wybierz przedziały czasowe, w których nie kolidujesz ze sobą.
  • Jak wyglądają statystyki systemowe? Być może serwer jest gorący i dławi procesor lub na dyskach twardych kończy się miejsce lub miejsce wymiany. Być może w serwerowni występuje inny problem sprzętowy, taki jak pożar lub powódź.
użytkownik1306322
źródło
7

Inną możliwością jest to, że zespół ds. Infrastruktury korzysta z narzędzi takich jak vMotion na VMware, a maszyna wirtualna obsługująca instancję SQL jest płynnie przenoszona z hosta na hosta bez wiedzy DBA na ten temat.

To prawdziwy problem, kiedy twoja infrastruktura jest zlecana na zewnątrz ... Mam z tym prawdziwy koszmar.

spokojnie
źródło