Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Wewnętrzne elementy SQL Server:Plan Caching Pt. II – Ponowna kompilacja planów

Jest to część serii SQL Server Internals Plan Caching. Koniecznie przeczytaj pierwszy post Kalena na ten temat.

SQL Server istnieje od ponad 30 lat, a ja pracuję z SQL Server prawie tak samo długo. Widziałem wiele zmian na przestrzeni lat (i dziesięcioleci!) i wersji tego niesamowitego produktu. W tych postach podzielę się z Wami tym, jak patrzę na niektóre funkcje lub aspekty SQL Server, czasami wraz z odrobiną perspektywy historycznej

W moim poprzednim artykule , omówiłem diagnostykę serwera SQL, w tym różne opcje, które SQL Server ma do ponownego wykorzystania planu zapytań. Przyjrzeliśmy się trzem rodzajom planów zapytań:adhoc, przygotowanym i proceduralnym. Zakończyłem dyskusję spojrzeniem na niewłaściwe ponowne wykorzystanie planu, które może się zdarzyć, gdy SQL Server zastosuje wąchanie parametrów w niewłaściwych sytuacjach. Jeśli plan jest oparty na wartości początkowej, która powoduje, że optymalizator generuje plan odpowiedni dla tej wartości, a następnie ten sam plan jest używany dla innej wartości, plan może nie być już optymalny.

Co więc możemy zrobić, gdy podsłuchiwanie parametrów jest problemem? Możemy zmusić SQL Server do opracowania nowego planu. Zwykle wymyślanie nowego planu nazywamy „ponowną kompilacją”, ale prawdopodobnie powinno się to nazywać „ponowną optymalizacją”. Jednak większość ludzi używa terminu „rekompilacja”, więc tego właśnie tutaj użyję.

Jeśli problemem jest niewłaściwe użycie funkcji podsłuchiwania parametrów, prostym rozwiązaniem jest po prostu poinformowanie SQL Server, aby opracował nowy plan. W przypadku indywidualnych zestawień, takich jak plany PREPARED, które zostały automatycznie sparametryzowane, możemy dodać do zapytania wskazówkę RECOMPILE. Używając parametryzacji FORCED (omówionej w poprzednim artykule), to zapytanie zostanie sparametryzowane.

WYBIERZ * Z dbo.newsales
GDZIE IDZamówieniaSprzedaży <@num;

Jeśli chcemy mieć pewność, że otrzymujemy nowy plan za każdym razem, gdy uruchamiamy to zapytanie, z potencjalnie bardzo różnymi wartościami @num, możemy dodać wskazówkę RECOMPILE, jak pokazano:

WYBIERZ * Z dbo.newsales
WHERE SalesOrderID <@num
OPCJA (REKOMPILACJA);

W przypadku procedur składowanych mamy trzy opcje. Po pierwsze, możemy sprawdzić, czy ponowna kompilacja rzeczywiście poprawi wydajność, wykonując procedurę z opcją RECOMPILE:

EXEC get_sales_range 66666 WITH RECOMPILE;

Ta opcja spowoduje wygenerowanie nowego planu tylko dla tego jednego wykonania. Nie zostanie zapisany i na pewno nie zostanie ponownie wykorzystany. Wartość usecount pokazana w sp_cacheobjects (opisana w poprzednim poście) dla procedury nie wzrośnie, ponieważ pierwotny plan nie jest ponownie używany.

Po drugie, jeśli uznamy, że wykonanie WITH RECOMPILE pomaga, możemy rozważyć odtworzenie procedury z opcją RECOMPILE, w którym to przypadku nigdy nie zostanie ponownie użyty plan, a procedura w ogóle nie pojawi się w pamięci podręcznej planu.

DROP PROC, JEŚLI ISTNIEJE get_sales_range;GO
UTWÓRZ PROC get_sales_range
@numer int
Z REKOMPILIĄ
JAK
WYBIERZ * Z dbo.newsales
GDZIE IDZamówieniaSprzedaży <@num;
IŚĆ

W przypadku mojej prostej małej procedury użycie opcji WITH RECOMPILE dla całej procedury może mieć sens. Ale jeśli procedura jest bardziej złożona, ponowna kompilacja całej procedury może nie mieć sensu, ponieważ jedna instrukcja powoduje problemy. Tak więc trzecią opcją jest użycie podpowiedzi RECOMPILE dla instrukcji w procedurze, więc wygląda to tak:

DROP PROC JEŚLI ISTNIEJE get_sales_range;
IŚĆ
UTWÓRZ PROC get_sales_range
@numer int
JAK
WYBIERZ * Z dbo.newsales
WHERE SalesOrderID <@num
OPCJA (REKOMPILACJA);
PRZEJDŹ

Użycie jednej z tych opcji RECOMPILE może zmusić SQL Server do opracowania nowego planu na Twoje żądanie. Teraz przyjrzymy się, kiedy diagnostyka SQL Server wygeneruje nowy plan, kiedy go nie zażądasz, tj. kiedy nastąpi automatyczna ponowna kompilacja istniejącego planu?


Automatyczna ponowna kompilacja planu występuje w dwóch typach sytuacji:

  • Po pierwsze, jeśli optymalizator stwierdzi, że istniejący plan nie jest już poprawny, zwykle z powodu zmiany definicji obiektów, będzie musiał opracować nowy plan. Na przykład, jeśli masz plan zapytania, który wybiera z TableA, a następnie upuszczasz kilka kolumn lub zmieniasz typy danych kolumn w TableA, SQL Server ponownie skompiluje zapytanie, aby opracować plan odzwierciedlający zmiany DDL.
  • Druga sytuacja, w której następuje automatyczna ponowna kompilacja, to sytuacja, w której SQL Server stwierdza, że ​​plan może nie być już optymalny ze względu na zmianę statystyk. W większości przypadków, jeśli statystyki dotyczące którejkolwiek z kolumn lub indeksów zostały zaktualizowane od czasu ostatniej kompilacji planu, zostaną one ponownie skompilowane. Ale to prowadzi do innego pytania. Kiedy aktualizowane są statystyki? Statystyki mogą być automatycznie aktualizowane, gdy zmieni się wystarczająca liczba wierszy w odpowiednich kolumnach. Ile wystarczy? Porozmawiamy o tym wkrótce.

Domyślnie SQL Server automatycznie aktualizuje statystyki, ponieważ opcja bazy danych jest domyślnie WŁĄCZONA. Ale jeśli jesteś właścicielem bazy danych (lub SQL „sa”, który pojawia się jako właściciel w każdej bazie danych), możesz zmienić opcje. Jedna z opcji nazywa się AUTO_UPDATE_STATISTICS, a druga nazywa się AUTO_UPDATE_STATISTICS_ASYNC. Opcja AUTO_UPDATE_STATISTICS jest włączona w bazie danych tempdb, więc każda nowa baza danych dziedziczy tę opcję. Gdy ta opcja jest włączona, a aparat wykonywania zapytań wykryje zmiany w wystarczającej liczbie wierszy podczas przetwarzania zapytania, wykonanie zostanie wstrzymane na czas aktualizacji statystyk, a następnie ponownej kompilacji zapytania. Druga opcja, AUTO_UPDATE_STATISTICS_ASYNC, może potencjalnie mieć mniejszy wpływ na czas wykonywania zapytania, ponieważ wykonywanie nie jest wstrzymywane, kosztem użycia możliwego planu nieoptymalnego. W przypadku drugiej opcji, jeśli silnik wykonawczy wykryje potrzebę aktualizacji statystyk, uruchamiany jest wątek w tle w celu wykonania aktualizacji, a wątek główny kontynuuje wykonywanie zapytania z oryginalnymi statystykami i pierwotnym planem. Następne zapytanie, które uzyskuje dostęp do odpowiednich tabel i widzi zaktualizowane statystyki, ponownie skompiluje zapytanie, ale nie zatrzyma i nie zaktualizuje statystyk w trakcie wykonywania.

Jest jeszcze kilka sytuacji, a także kilka wskazówek dotyczących zapytań, które kontrolują, czy plany są ponownie kompilowane, czy nie, więc pokażę Ci schemat blokowy. Podzielę się z Tobą schematem blokowym, który utworzyłem na potrzeby moich zajęć szkoleniowych dotyczących wewnętrznych elementów SQL Server.

Strzałka wskazuje miejsce, w którym SQL Server rozpoczyna przetwarzanie Twojej partii. Najpierw sprawdza, czy w pamięci podręcznej jest już plan dla twojej partii, a jeśli odpowiedź brzmi NIE, podąża za strzałką po prawej i kompiluje plan. Plan jest umieszczany w pamięci podręcznej, a następnie ponownie uruchamiany jest program SQL Server. Tak, tym razem plan powinien znajdować się w pamięci podręcznej, więc podąża za strzałką w dół i pyta, czy użyto podpowiedzi o nazwie KEEP PLAN. Jeśli TAK, SQL Server natychmiast rozpocznie realizację planu i nie wykonuje żadnych dalszych kontroli.

Kolejne pytanie dotyczy tego, czy wprowadzono jakiekolwiek zmiany DDL. Jeśli nie, to pyta o kilka innych sytuacji, o których nie będę mógł mówić w tym artykule. W rzeczywistości naprawdę nie zamierzam tutaj przechodzić przez każdą opcję. Zostawię to tobie. Ale jeśli masz jakieś pytania lub niejasności, możesz je zadać w sekcji komentarzy tutaj lub tweetować do mnie na @sqlqueen. Wskażę pytanie po prawej:czy AUTO_STATS_ASYNC jest WŁĄCZONE? Tutaj widać, że jeśli odpowiedź brzmi TAK, są dwie akcje. Jedna gałąź po prostu rozpoczyna wykonywanie z istniejącym planem, a druga to wątek w tle, który aktualizuje statystyki, ale potem nie robi nic więcej. Następne zapytanie napotka pole decyzyjne pośrodku „Czy są dostępne nowe statystyki” i powinno odpowiedzieć TAK, więc zapytanie zostanie ponownie skompilowane.

Jedyną inną rzeczą, o której powiem, jest pytanie „Czy jakieś statystyki są przestarzałe?”. Oznacza to w zasadzie, że statystyki są nieaktualne, ponieważ wprowadzono zbyt wiele zmian. Więc teraz możemy porozmawiać o tym, ile to za dużo.

Chociaż istnieją różne wartości używane dla bardzo małych tabel, dla każdej tabeli zawierającej więcej niż 500 wierszy, przed SQL Server 2016 statystyki były uważane za „nieaktualne”, gdy liczba zmian w kolumnie, na której opierały się statystyki, przekroczyła 20 % liczby wierszy w tabeli. Tak więc w przypadku tabeli zawierającej 1000 wierszy może to oznaczać 200 wstawień, 200 aktualizacji lub 200 usunięć. Może to być 200 zmian wierszy lub 5 wierszy aktualizowanych 40 razy każdy. SQL Server daje nam nawet funkcję, która raportuje, ile zmian zostało wprowadzonych. Musisz wyszukać numer stats_id dla statystyk, którymi jesteś zainteresowany, czyli index_id, jeśli statystyki należą do indeksu. Stats_id można znaleźć w widoku o nazwie sys.stats. W mojej tabeli newsales używam tego zapytania, aby stwierdzić, że stats_id dla indeksu w kolumnie SubTotal to 3.

SELECT nazwa, stats_id FROM sys.stats
GDZIE object_id =object_id('newsales');

Następnie mogę użyć tej wartości do przyjrzenia się liczbie zmian. Pozwól, że najpierw zaktualizuję niektóre wiersze:

AKTUALIZUJ aktualności
SET Suma pośrednia =Suma pośrednia * 0,9
GDZIE SalesOrderID <45200 (1541 wierszy, których dotyczy)

WYBIERZ * Z sys.dm_db_stats_properties(object_id('newsales'), 3);

W rzeczywistości 20% to DUŻA liczba. W przypadku wielu tabel zapytania mogą korzystać ze zaktualizowanych statystyk, w których zaktualizowano znacznie mniej niż 20% wierszy. Począwszy od 2008R2 SP1, SQL Server zawierał znacznik Traceflag, którego można było użyć do zmiany liczby wierszy na skalę przesuwną, jak pokazano na poniższym wykresie:

Począwszy od SQL Server 2016, ten nowy algorytm ze skalą przesuwną jest używany domyślnie, o ile masz poziom zgodności 130 lub wyższy.

Większość automatycznych ponownych kompilacji planów zapytań wynika ze zmian w statystykach. Ale jak wspomniałem powyżej, nie jest to jedyny powód ponownej kompilacji. Ale ponieważ jest to najbardziej powszechne, warto wiedzieć, kiedy i w jaki sposób aktualizowane są statystyki, a także upewnić się, że statystyki dotyczące krytycznych tabel są aktualizowane wystarczająco często, aby mieć pewność, że masz najlepsze plany!

Automatycznie analizuj dane dotyczące wydajności, aby przeprowadzić diagnostykę serwera SQL, aby szybko rozwiązać problemy i zidentyfikować serwery, na których występuje spadek wydajności. Zacznij korzystać z Spotlight Cloud już dziś:


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak TRY_CAST() działa w SQL Server

  2. Przekaż zmienną do wyzwalacza

  3. Sekwencja jako wartość domyślna dla kolumny

  4. Czy istnieje poważny spadek wydajności korzystania z kluczy obcych w programie SQL Server?

  5. Czy widok jest szybszy niż proste zapytanie?