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

Ustalanie i identyfikacja celów rzędów w planach wykonawczych

Wprowadzenie

Dokumentacja produktu SQL Server jest nieco lekka na temat rzędów celów . Główne oficjalne odniesienia znajdują się w:

  • Wskazówki (języka Transact-SQL) — Zapytanie (FAST i DISABLE_OPTIMIZER_ROWGOAL poradnik)
  • DBCC TRACEON — flagi śledzenia (języka Transact-SQL) (flaga śledzenia 4138)
  • Uruchomienie zapytania może zająć dużo czasu, jeśli optymalizator zapytań używa operatora Top (KB 2667211)

Kiedy ludzie proszą o więcej informacji, niż jest tam zawarte, zwykle odsyłam im jedno lub więcej z poniższych:

  • Cele wierszy w działaniu zespołu ds. optymalizacji zapytań programu SQL Server
  • Ponownie przeanalizowano cele wierszy — wskazówki dotyczące FAST, również opracowane przez zespół ds. optymalizacji zapytań programu SQL Server
  • Rzeczowe bramki przeminęły przez Barta Duncana
  • Wewnątrz Optymalizatora:Głębokość rzędów bramek według mnie
  • Wskazówka dotycząca tuningu SSIS, której wszyscy tęsknią, autorstwa Roba Farleya

Podsumowując krótko:Funkcja celu wiersza umożliwia optymalizatorowi wygenerowanie planu wykonania (lub części planu wykonania) w celu szybkiego zwrócenia określonej liczby wierszy. Jest to sprzeczne z normalnym zachowaniem (bez celu w wierszu), którego celem jest znalezienie planu zoptymalizowanego pod kątem pełnego potencjalnego zestawu wyników.

Strategia celu wiersza ogólnie oznacza faworyzowanie nieblokujących operacji nawigacyjnych (na przykład sprzężenia zagnieżdżonych pętli, wyszukiwania indeksu i wyszukiwania) w stosunku do operacji blokujących opartych na zestawach, takich jak sortowanie i mieszanie. Może to być przydatne, gdy klient może skorzystać na szybkim uruchomieniu i stałym strumieniu wierszy (z być może dłuższym całkowitym czasem wykonania – patrz post Roba Farleya powyżej). Są też bardziej oczywiste i tradycyjne zastosowania, m.in. w prezentowaniu wyników po jednej stronie na raz.

Oczywiście istnieje element ryzyka związany z planem celów z rzędu. Jeśli wszystko rozgrywa się ogólnie zgodnie z oczekiwaniami optymalizatora (biorąc pod uwagę dostępne informacje i przyjęte założenia modelowania), plan wykonania rozpocznie przesyłanie strumieniowe żądanej liczby wierszy szybciej i wydajniej niż miałoby to miejsce bez celu dotyczącego wiersza.

Niestety, gdy strategia celu rzędu nie powiedzie się, może to być katastrofa wydajności (patrz post Barta Duncana). Może się to zdarzyć, na przykład, gdy optymalizator ma niekompletne informacje, napotka niekorzystną dystrybucję danych lub przyjmuje niebezpieczne założenie. W każdym razie przyczyną słabej wydajności prawie zawsze jest to, że w czasie wykonywania trzeba przetworzyć o wiele więcej wierszy niż oczekiwał optymalizator.

Identyfikacja obszarów planu wykonania, na które ma wpływ cel w postaci wiersza, może być bardzo przydatna, ponieważ pomaga nam zrozumieć, dlaczego optymalizator dokonał odpowiednich wyborów. Jest to szczególnie ważne, gdy logika celu wiersza daje niekorzystny wynik. Bez zrozumienia roli, jaką odgrywa cel wiersza, może się wydawać, że optymalizator po prostu nie doszacował liczby wierszy, co prowadzi do szukania przyczyny źródłowej w niewłaściwych miejscach (np. statystykach).

Ustawianie celów wierszy

O wiele łatwiej jest szukać efektów celu w wierszu, jeśli wiadomo, jakie czynniki mogą spowodować, że cel w wierszu zostanie ustawiony w pierwszej kolejności. Oficjalna dokumentacja często mówi o powiązaniu celów wierszy ze słowami kluczowymi TOP , FAST , IN i EXISTS . Może to pozostawić czytelnika z niepełnym lub mylącym zrozumieniem, dlatego warto poświęcić chwilę na wyjaśnienie niektórych aspektów.

Chcę od razu podkreślić, że używanie określonych słów kluczowych T-SQL w zapytaniu nie gwarantuje, że zostanie ustawiony cel wiersza . Oficjalna dokumentacja wymienia pewne słowa kluczowe, aby pomóc ludziom zidentyfikować typowe scenariusze, w których cele wierszy mogą być wprowadzone, bez zbytniego wchodzenia w szczegóły techniczne.

Drugą ogólną kwestią, o której należy pamiętać, jest to, że cel w wierszu jest ustalany tylko wtedy, gdy cel byłby niższy niż zwykłe oszacowanie . W końcu nie ma sensu generować fragmentu planu zoptymalizowanego dla 100 wierszy, jeśli całość i tak ma wyprodukować tylko 50 wierszy. Aby było bardziej jasne, ten punkt zawsze dotyczy wszystkich sposobów, w jakie można ustawić cel rzędu. Jeśli spodziewasz się celu w rzędzie, ale go nie widzisz, jest to prawdopodobna przyczyna.

Na koniec, we wstępie, zwróć uwagę, że cele wierszowe są optymalizacją opartą na kosztach; cel w wierszu wpływa na wybory optymalizatora, więc jeśli nie ma wyborów do dokonania (tj. trywialny plan), nie ma efektu celu w wierszu.

Przyjrzyjmy się teraz rzeczom, które mogą wyznaczać cel wiersza:

SZYBKO i GÓRNIE

Korzystanie z FAST wskazówka zapytania to niezawodny sposób na ustawienie celu wiersza w głównym planu wykonawczego (z zastrzeżeniem ogólnych wyjątków wskazanych powyżej). SET ROWCOUNT n instrukcja ustawia również podobny cel najwyższego poziomu wiersza (gdy n nie jest oczywiście zerem) dla stwierdzeń, których dotyczy.

Pisanie TOP klauzula w zapytaniu również bardzo często skutkuje celem w wierszu. Dopóki ukończony plan wykonania zawiera fizyczny operator Top, prawdopodobne jest, że przynajmniej część planu poniżej operatora Top została poddana celowi w wierszu (ponownie, obowiązują ogólne warunki).

Zwróć uwagę, że główne operatory wprowadzone przez optymalizator zapytań (bez określonego zapytania TOP klauzuli) można również ustawić cel wiersza. Jest to ważne, ponieważ może się to zdarzyć na wiele sposobów, na przykład podczas filtrowania według prostego numeru wiersza, jak pokazano w następującym zapytaniu AdventureWorks:

SELECT
    THN.RowNum,
    THN.TransactionID 
FROM 
(
    SELECT 
        TH.TransactionID, 
        RowNum = 
            ROW_NUMBER() OVER (
                ORDER BY TH.TransactionID ASC)
    FROM Production.TransactionHistory AS TH
    WHERE
        TH.ProductID = 400
) AS THN
WHERE
    THN.RowNum >= 10
    AND THN.RowNum < 20
ORDER BY
    THN.RowNum ASC;

Plan wykonania dla tego zapytania zawiera operator Top dodany przez optymalizator (w celu ograniczenia liczby przetwarzanych wierszy do 20):