Database
 sql >> Baza danych >  >> RDS >> Database

Objawy narzutu obserwatora i typu oczekiwania

Wiele osób używa statystyk oczekiwania jako części ogólnej metodologii rozwiązywania problemów z wydajnością, podobnie jak ja, więc pytanie, które chciałem zbadać w tym poście, dotyczy typów oczekiwania związanych z obciążeniem obserwatora. Przez obciążenie obserwatora rozumiem wpływ na przepustowość obciążenia SQL Server powodowany przez SQL Profiler, śledzenie po stronie serwera lub sesje Extended Event. Więcej informacji na temat narzutu obserwatora można znaleźć w następujących dwóch postach mojego kolegi Jonathana Kehayiasa :

  • Pomiar „narzutu obserwatora” śledzenia SQL w porównaniu z rozszerzonymi zdarzeniami
  • Wpływ rozszerzonego zdarzenia query_post_execution_showplan w SQL Server 2012
  • Tak więc w tym poście chciałbym przejść przez kilka odmian obserwatora narzutu i zobaczyć, czy możemy znaleźć spójne typy oczekiwania związane z mierzoną degradacją. Istnieje wiele sposobów, w jakie użytkownicy SQL Server implementują śledzenie w swoich środowiskach produkcyjnych, więc wyniki mogą się różnić, ale chciałem omówić kilka ogólnych kategorii i zrelacjonować to, co znalazłem:

    • Użycie sesji SQL Profiler
    • Użycie śledzenia po stronie serwera
    • Użycie śledzenia po stronie serwera, zapis do wolnej ścieżki we/wy
    • Rozszerzone użycie zdarzeń z celem bufora pierścieniowego
    • Rozszerzone użycie zdarzeń z plikiem docelowym
    • Rozszerzone użycie zdarzeń z plikiem docelowym na wolnej ścieżce we/wy
    • Rozszerzone użycie zdarzeń z plikiem docelowym na wolnej ścieżce we/wy bez utraty zdarzeń

    Prawdopodobnie możesz wymyślić inne wariacje na ten temat. Zapraszam Cię do podzielenia się interesującymi odkryciami dotyczącymi ogólnych obserwatorów i statystykami oczekiwania jako komentarz w tym poście.

    Podstawa

    Do testu użyłem maszyny wirtualnej VMware z czterema vCPU i 4 GB pamięci RAM. Mój gość maszyny wirtualnej był na dyskach SSD firmy OCZ Vertex. System operacyjny to Windows Server 2008 R2 Enterprise, a wersja SQL Server to 2012, SP1 CU4.

    Jeśli chodzi o „obciążenie”, używam zapytania tylko do odczytu w pętli względem przykładowej bazy danych kredytów 2008, ustawionej na GO 10 000 000 razy.

    USE [Credit];
    GO
     
    SELECT TOP 1 
         [member].[member_no],
         [member].[lastname],
         [payment].[payment_no],
         [payment].[payment_dt],
         [payment].[payment_amt]
    FROM [dbo].[payment]
    INNER JOIN [dbo].[member]
    ON [member].[member_no] = [payment].[member_no];
    GO 10000000

    Wykonuję również to zapytanie przez 16 równoległych sesji. Końcowym wynikiem w moim systemie testowym jest 100% wykorzystanie procesora we wszystkich procesorach wirtualnych na wirtualnym gościu i średnio 14 492 żądań wsadowych na sekundę w okresie 2 minut.

    Jeśli chodzi o śledzenie zdarzeń, w każdym teście używałem Showplan XML Statistics Profile dla testów SQL Profiler i śledzenia po stronie serwera – oraz query_post_execution_showplan dla sesji Extended Event. Zdarzenia planu wykonania są bardzo drogie, właśnie dlatego wybrałem je, aby sprawdzić, czy w ekstremalnych okolicznościach mogę wyprowadzić motywy typu oczekiwania.

    Do testowania akumulacji typu oczekiwania w okresie testowym użyłem następującego zapytania. Nic nadzwyczajnego — wystarczy wyczyścić statystyki, odczekać 2 minuty, a następnie zebrać 10 największych akumulacji oczekiwania dla instancji SQL Server w okresie testu degradacji:

    -- Clearing the wait stats
     
    DBCC SQLPERF('waitstats', clear);
     
    WAITFOR DELAY '00:02:00';
    GO
     
    SELECT TOP 10
         [wait_type],
         [waiting_tasks_count],
         [wait_time_ms]
    FROM sys.[dm_os_wait_stats] AS [ws]
    ORDER BY [wait_time_ms] DESC;

    Zauważ, że nie odfiltrowywanie typów oczekiwania w tle, które zwykle są odfiltrowywane, a to dlatego, że nie chciałem eliminować czegoś, co zwykle jest łagodne – ale w tej sytuacji wskazuje na rzeczywisty obszar do dalszego zbadania.

    Sesja programu SQL Profiler

    W poniższej tabeli przedstawiono żądania wsadowe przed i po na sekundę podczas włączania śledzenia śledzenia lokalnego programu SQL Profiler Showplan XML Statistics Profile (działa na tej samej maszynie wirtualnej, co instancja SQL Server):

    Podstawowe żądania partii na sekundę
    (średnia z 2 minut)
    Żądania wsadowe sesji programu SQL Profiler na sekundę
    (średnia z 2 minut)
    14 492 1416

    Widać, że ślad programu SQL Profiler powoduje znaczny spadek przepustowości.

    Jeśli chodzi o skumulowany czas oczekiwania w tym samym okresie, najważniejsze typy oczekiwania były następujące (podobnie jak w przypadku pozostałych testów w tym artykule, wykonałem kilka przebiegów testowych i wynik był ogólnie spójny):

    wait_type waiting_tasks_count wait_time_ms
    TRACEWPISZ 67 142 1149 824
    FT_IFTS_SCHEDULER_IDLE_WAIT 4 237003
    SLEEP_TASK 313 180 449
    REQUEST_FOR_DEADLOCK_SEARCH 24 120 111
    HADR_FILESTREAM_IOMGR_IOCOMPLETION 240 120 086
    LAZYWRITER_SLEEP 120 120 059
    DIRTY_PAGE_POLL 1198 120 038
    HADR_WORK_QUEUE 12 120 015
    LOGMGR_QUEUE 937 120 011
    SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120,006

    Typ oczekiwania, który mi wyskakuje, to TRACEWRITE — który jest zdefiniowany przez Books Online jako typ oczekiwania, który „występuje, gdy dostawca śledzenia zestawu wierszy SQL Trace czeka na wolny bufor lub bufor ze zdarzeniami do przetworzenia”. Pozostałe typy oczekiwania wyglądają jak standardowe typy oczekiwania w tle, które zwykle są odfiltrowywane z zestawu wyników. Co więcej, mówiłem o podobnym problemie z nadmiernym śledzeniem w artykule z 2011 roku zatytułowanym Obciążenie obserwatora — niebezpieczeństwa związane ze zbyt dużym śledzeniem — więc znałem ten typ oczekiwania czasami prawidłowo wskazując na ogólne problemy obserwatora. Teraz w tym konkretnym przypadku, o którym pisałem na blogu, nie był to SQL Profiler, ale inna aplikacja korzystająca z dostawcy śledzenia zestawu wierszy (nieefektywnie).

    Śledzenie po stronie serwera

    To było w przypadku programu SQL Profiler, ale co z obciążeniem śledzenia po stronie serwera? Poniższa tabela przedstawia żądania wsadowe przed i po na sekundę podczas włączania lokalnego śledzenia po stronie serwera zapisywania do pliku:

    Podstawowe żądania partii na sekundę
    (średnia z 2 minut)
    Żądania wsadowe programu SQL Profiler na sekundę
    (średnia z 2 minut)
    14 492 4015

    Najczęstsze typy oczekiwania były następujące (zrobiłem kilka przebiegów testowych i wynik był spójny):

    wait_type waiting_tasks_count wait_time_ms
    FT_IFTS_SCHEDULER_IDLE_WAIT 4 237.015
    SLEEP_TASK 253 180 871
    SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 046
    HADR_WORK_QUEUE 12 120 042
    REQUEST_FOR_DEADLOCK_SEARCH 24 120 021
    XE_DISPATCHER_WAIT 3 120,006
    CZEKAJ NA 1 120 000
    LOGMGR_QUEUE 931 119 993
    DIRTY_PAGE_POLL 1193 119.958
    XE_TIMER_EVENT 55 119.954

    Tym razem nie widzimy TRACEWRITE (teraz używamy dostawcy plików) i innego typu oczekiwania związanego ze śledzeniem, nieudokumentowanego SQLTRACE_INCREMENTAL_FLUSH_SLEEP wspiął się w górę – ale w porównaniu do pierwszego testu, ma bardzo podobny skumulowany czas oczekiwania (120 046 vs 120 006) – a moja koleżanka Erin Stellato (@erinstellato) mówiła o tym konkretnym typie oczekiwania w swoim poście Jak ustalić, kiedy statystyki oczekiwania zostały ostatnio wyczyszczone . Więc patrząc na inne typy czekania, żaden nie wyskakuje jako niezawodny sygnał ostrzegawczy.

    Zapis śledzenia po stronie serwera do wolnej ścieżki we/wy

    Co jeśli umieścimy plik śledzenia po stronie serwera na wolnym dysku? Poniższa tabela przedstawia żądania wsadowe przed i po na sekundę podczas włączania lokalnego śledzenia po stronie serwera, które zapisuje do pliku na pamięci USB:

    Podstawowe żądania partii na sekundę
    (średnia z 2 minut)
    Żądania wsadowe programu SQL Profiler na sekundę
    (średnia z 2 minut)
    14 492 260

    Jak widać – wydajność jest znacznie obniżona – nawet w porównaniu z poprzednim testem.

    Najczęstsze typy oczekiwania były następujące:

    wait_type waiting_tasks_count wait_time_ms
    SQLTRACE_FILE_BUFFER 357 351.174
    SP_SERVER_DIAGNOSTICS_SLEEP 2273 299995
    SLEEP_TASK 240 194 264
    FT_IFTS_SCHEDULER_IDLE_WAIT 2 181 458
    REQUEST_FOR_DEADLOCK_SEARCH 25 125 007
    LAZYWRITER_SLEEP 63 124.437
    LOGMGR_QUEUE 941 120 559
    HADR_FILESTREAM_IOMGR_IOCOMPLETION 67 120 516
    CZEKAJ NA 1 120 515
    DIRTY_PAGE_POLL 1204 120 513

    Jednym z typów oczekiwania, który wyskakuje w tym teście, jest nieudokumentowany SQLTRACE_FILE_BUFFER . Niewiele udokumentowane na ten temat, ale na podstawie nazwy możemy zgadywać (szczególnie biorąc pod uwagę konfigurację tego konkretnego testu).

    Rozszerzone zdarzenia do celu bufora pierścieniowego

    Następnie przejrzyjmy wyniki dotyczące odpowiedników sesji Extended Event. Użyłem następującej definicji sesji:

    CREATE EVENT SESSION [ApplicationXYZ] ON SERVER
      ADD EVENT sqlserver.query_post_execution_showplan,
      ADD TARGET package0.ring_buffer(SET max_events_limit=(1000))
      WITH (STARTUP_STATE=ON);
    GO

    W poniższej tabeli przedstawiono żądania wsadowe przed i po na sekundę podczas włączania sesji XE z docelowym buforem pierścieniowym (przechwytywanie query_post_execution_showplan wydarzenie):

    Podstawowe żądania partii na sekundę
    (średnia z 2 minut)
    Żądania wsadowe programu SQL Profiler na sekundę
    (średnia z 2 minut)
    14 492 4737

    Najczęstsze typy oczekiwania były następujące:

    wait_type waiting_tasks_count wait_time_ms
    SP_SERVER_DIAGNOSTICS_SLEEP 612 299992
    FT_IFTS_SCHEDULER_IDLE_WAIT 4 237.006
    SLEEP_TASK 240 181 739
    LAZYWRITER_SLEEP 120 120 219
    HADR_WORK_QUEUE 12 120 038
    DIRTY_PAGE_POLL 1198 120 035
    REQUEST_FOR_DEADLOCK_SEARCH 24 120 017
    SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 011
    LOGMGR_QUEUE 936 120,008
    CZEKAJ NA 1 120,001

    Nic nie wyskoczyło jako związane z XE, tylko „hałas” zadania w tle.

    Rozszerzone zdarzenia do pliku docelowego

    Co powiesz na zmianę sesji, aby używała pliku docelowego zamiast docelowego bufora pierścieniowego? Poniższa tabela przedstawia żądania wsadowe przed i po na sekundę podczas włączania sesji XE z plikiem docelowym zamiast docelowym buforem pierścieniowym:

    Podstawowe żądania partii na sekundę
    (średnia z 2 minut)
    Żądania wsadowe programu SQL Profiler na sekundę
    (średnia z 2 minut)
    14 492 4299

    Najczęstsze typy oczekiwania były następujące:

    wait_type waiting_tasks_count wait_time_ms
    SP_SERVER_DIAGNOSTICS_SLEEP 2103 299996
    FT_IFTS_SCHEDULER_IDLE_WAIT 4 237003
    SLEEP_TASK 253 180 663
    LAZYWRITER_SLEEP 120 120 187
    HADR_WORK_QUEUE 12 120 029
    SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 019
    REQUEST_FOR_DEADLOCK_SEARCH 24 120 011
    CZEKAJ NA 1 120,001
    XE_TIMER_EVENT 59 119 966
    LOGMGR_QUEUE 935 119.957

    Nic, z wyjątkiem XE_TIMER_EVENT , wyskoczył jako związany z XE. Repozytorium typu oczekiwania Boba Warda odnosi się do tego jako bezpiecznego do zignorowania, chyba że coś jest możliwe nie tak – ale realistycznie, czy zauważyłbyś ten zwykle łagodny typ oczekiwania, gdyby znajdował się na 9 miejscu w twoim systemie podczas spadku wydajności? A co, jeśli już to odfiltrowujesz ze względu na jego zwykle łagodny charakter?

    Rozszerzone zdarzenia do powolnego docelowego pliku ścieżki we/wy

    A co, jeśli umieszczę plik na wolnej ścieżce we/wy? Poniższa tabela przedstawia żądania wsadowe przed i po na sekundę podczas włączania sesji XE z plikiem docelowym na pamięci USB:

    Podstawowe żądania partii na sekundę
    (średnia z 2 minut)
    Żądania wsadowe programu SQL Profiler na sekundę
    (średnia z 2 minut)
    14 492 4386

    Najczęstsze typy oczekiwania były następujące:

    wait_type waiting_tasks_count wait_time_ms
    FT_IFTS_SCHEDULER_IDLE_WAIT 4 237.046
    SLEEP_TASK 253 180 719
    HADR_FILESTREAM_IOMGR_IOCOMPLETION 240 120 427
    LAZYWRITER_SLEEP 120 120 190
    HADR_WORK_QUEUE 12 120 025
    SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120 013
    REQUEST_FOR_DEADLOCK_SEARCH 24 120 011
    CZEKAJ NA 1 120,002
    DIRTY_PAGE_POLL 1197 119 977
    XE_TIMER_EVENT 59 119 949

    Ponownie, nic związanego z XE nie wyskakuje z wyjątkiem XE_TIMER_EVENT .

    Rozszerzone zdarzenia do docelowego pliku ścieżki we/wy, bez utraty zdarzeń

    Poniższa tabela przedstawia żądania wsadowe przed i po na sekundę podczas włączania sesji XE z obiektem docelowym pliku na pamięci USB, ale tym razem bez zezwolenia na utratę zdarzeń (EVENT_RETENTION_MODE=NO_EVENT_LOSS) — co nie jest zalecane, a zobaczysz w wynikach, dlaczego może to być:

    Podstawowe żądania partii na sekundę
    (średnia z 2 minut)
    Żądania wsadowe programu SQL Profiler na sekundę
    (średnia z 2 minut)
    14 492 539

    Najczęstsze typy oczekiwania były następujące:

    wait_type waiting_tasks_count wait_time_ms
    XE_BUFFERMGR_FREEBUF_EVENT 8773 1707,845
    FT_IFTS_SCHEDULER_IDLE_WAIT 4 237003
    SLEEP_TASK 337 180 446
    LAZYWRITER_SLEEP 120 120 032
    DIRTY_PAGE_POLL 1198 120 026
    HADR_WORK_QUEUE 12 120 0009
    REQUEST_FOR_DEADLOCK_SEARCH 24 120,007
    SQLTRACE_INCREMENTAL_FLUSH_SLEEP 30 120,006
    CZEKAJ NA 1 120 000
    XE_TIMER_EVENT 59 119.944

    Dzięki ekstremalnej redukcji przepustowości widzimy XE_BUFFERMGR_FREEBUF_EVENT przejdź na pozycję numer jeden w naszych wynikach skumulowanego czasu oczekiwania. Ten jest udokumentowane w Books Online, a Microsoft mówi nam, że to zdarzenie jest powiązane z sesjami XE skonfigurowanymi na brak utraty zdarzeń i gdzie wszystkie bufory w sesji są pełne.

    Wpływ obserwatora

    Pomijając typy oczekiwania, warto było zauważyć, jaki wpływ każda metoda obserwacji miała na zdolność przetwarzania żądań wsadowych przez obciążenie:


    Wpływ różnych metod obserwacji na żądania grupowe na sekundę

    W przypadku wszystkich podejść wystąpiło znaczące – ale nie szokujące – trafienie w porównaniu z naszą linią bazową (brak obserwacji); jednak najwięcej bólu odczuwano podczas korzystania z programu Profiler, śledzenia po stronie serwera do wolnej ścieżki we/wy lub zdarzeń rozszerzonych do obiektu docelowego pliku na wolnej ścieżce we/wy — ale tylko wtedy, gdy skonfigurowano brak utraty zdarzeń. W przypadku utraty zdarzeń ta konfiguracja faktycznie działała na równi z docelowym plikiem do szybkiej ścieżki we/wy, prawdopodobnie dlatego, że była w stanie odrzucić znacznie więcej zdarzeń.

    Podsumowanie

    Nie testowałem każdego możliwego scenariusza i na pewno są inne ciekawe kombinacje (nie wspominając o różnych zachowaniach opartych na wersji SQL Server), ale kluczowy wniosek, który wyciągam z tej eksploracji jest taki, że nie zawsze można polegać na oczywistej kumulacji typu wait wskaźnik w obliczu ogólnego scenariusza obserwatora. Na podstawie testów przedstawionych w tym poście tylko trzy z siedmiu scenariuszy wykazywały określony typ oczekiwania, który potencjalnie może pomóc wskazać właściwy kierunek. Nawet wtedy – te testy były prowadzone w kontrolowanym systemie – i często ludzie odfiltrowują wyżej wymienione typy oczekiwania jako łagodne typy tła – więc możesz ich w ogóle nie widzieć.

    Biorąc to pod uwagę, co możesz zrobić? W przypadku pogorszenia wydajności bez wyraźnych lub oczywistych objawów, zalecam poszerzenie zakresu, aby zapytać o ślady i sesje XE (na marginesie – zalecam również poszerzenie zakresu, jeśli system jest zwirtualizowany lub może mieć nieprawidłowe opcje zasilania). Na przykład, w ramach rozwiązywania problemów z systemem, sprawdź sys.[traces] i sys.[dm_xe_sessions] aby sprawdzić, czy w systemie działa coś, co jest nieoczekiwane. Jest to dodatkowa warstwa do tego, o co musisz się martwić, ale wykonanie kilku szybkich walidacji może zaoszczędzić znaczną ilość czasu.


    1. Database
    2.   
    3. Mysql
    4.   
    5. Oracle
    6.   
    7. Sqlserver
    8.   
    9. PostgreSQL
    10.   
    11. Access
    12.   
    13. SQLite
    14.   
    15. MariaDB
    1. Trendy sprzętowe serwera baz danych

    2. Jak uzyskać wczorajszą datę w T-SQL

    3. Upuść vs Obcinaj w SQL

    4. Mity dotyczące wydajności:Obcięcie nie może zostać wycofane

    5. Wyspy T-SQL Wyzwanie