Zwykle tworzę przewodniki po planach, najpierw konstruując zapytanie, które korzysta z właściwego planu, i kopiując je do podobnego zapytania, które tego nie robi. Jest to jednak czasami trudne, szczególnie jeśli zapytanie nie jest dokładnie takie samo. Jaki jest właściwy sposób tworzenia prowadnic planu od zera?
SQLKiwi wspomniał o opracowywaniu planów w SSIS, czy istnieje sposób lub przydatne narzędzie pomagające w opracowaniu dobrego planu dla SQL Server?
Konkretne wystąpienie to CTE: SQLFiddle
with cte(guid,other) as (
select newid(),1 union all
select newid(),2 union all
select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other;
Czy istnieje jakikolwiek sposób, aby wynik wymyślił dokładnie 3 różne guid
s i nic więcej? Mam nadzieję, że będę w stanie lepiej odpowiadać na pytania w przyszłości, włączając przewodniki po planach z zapytaniami typu CTE, do których wielokrotnie się odwołujemy, aby przezwyciężyć niektóre dziwactwa SQL Server CTE.
źródło
Odpowiedzi:
Nie dzisiaj. Nierekurencyjne wspólne wyrażenia tabelowe (CTE) są traktowane jako wbudowane definicje widoku i są rozszerzane do logicznego drzewa zapytań w każdym miejscu, do którego się odwołują (podobnie jak zwykłe definicje widoku) przed optymalizacją. Drzewo logiczne dla twojego zapytania to:
Zwróć uwagę na dwie kotwice widoku i sześć wywołań funkcji wewnętrznej
newid
przed rozpoczęciem optymalizacji. Niemniej jednak wiele osób uważa, że optymalizator powinien być w stanie stwierdzić, że rozwinięte poddrzewa były pierwotnie pojedynczym obiektem odniesienia i odpowiednio uprościć. Pojawiło się również kilka żądań Connect, aby umożliwić jawne zmaterializowanie CTE lub tabeli pochodnej.Bardziej ogólna implementacja spowodowałaby, że optymalizator rozważyłby zmaterializowanie dowolnych wspólnych wyrażeń w celu poprawy wydajności (
CASE
z podzapytaniem to kolejny przykład, w którym mogą wystąpić problemy dzisiaj). Microsoft Research opublikował artykuł (PDF) na ten temat w 2007 roku, choć do tej pory nie został zaimplementowany. Na razie ograniczamy się do jawnej materializacji przy użyciu takich zmiennych, jak tabele tymczasowe.To było po prostu pobożne życzenie i znacznie wykroczyło poza pomysł modyfikacji przewodników po planach. Zasadniczo możliwe jest napisanie narzędzia do bezpośredniej manipulacji programem XML planu, ale bez konkretnej oprzyrządowania optymalizatora użycie tego narzędzia byłoby prawdopodobnie frustrujące dla użytkownika (i programista pomyślałby o tym).
W szczególnym kontekście tego pytania takie narzędzie nadal nie byłoby w stanie zmaterializować zawartości CTE w sposób, który mógłby być wykorzystany przez wielu konsumentów (w tym przypadku zasilenie obu danych wejściowych łączeniem krzyżowym). Optymalizator i silnik wykonawczy obsługują szpule wielu konsumentów, ale tylko do określonych celów - żadnego z nich nie można zastosować w tym konkretnym przykładzie.
Istnieje tutaj rozsądna elastyczność. Szeroki kształt planu XML służy do kierowania poszukiwanie ostatecznego planu (choć wiele atrybutów są całkowicie ignorowane np typ partycji na giełdach) i normalne zasady wyszukiwania są znacznie złagodzone, jak również. Na przykład wcześniejsze przycinanie alternatyw opartych na kosztach jest wyłączone, dozwolone jest jawne wprowadzenie połączeń krzyżowych, a operacje skalarne są ignorowane.
Jest zbyt wiele szczegółów, aby je zagłębić, ale nie można wymusić umieszczenia filtrów i skalarów obliczeniowych, a predykaty formularza
column = value
są uogólnione, więc plan zawierającyX = 1
lubX = @X
może być zastosowany do zapytania zawierającegoX = 502
lubX = @Y
. Ta szczególna elastyczność może znacznie pomóc w znalezieniu naturalnego planu wymuszenia.W konkretnym przykładzie stałą Union All zawsze można zaimplementować jako skanowanie ciągłe; liczba danych wejściowych do Unii Wszystkie nie ma znaczenia.
źródło
Nie ma możliwości (wersje SQL Server do 2012 r.) Ponownego użycia jednego buforu dla obu wystąpień CTE. Szczegóły można znaleźć w odpowiedzi SQLKiwi. Poniżej znajdują się dwa sposoby dwukrotnego zmaterializowania CTE, co jest nieuniknione ze względu na charakter zapytania. Obie opcje dają wyraźną liczbę przewodników netto równą 6.
Link z komentarza Martina do strony Quassnoi na blogu o planie kierowania CTE był częściowo inspiracją do tego pytania. Opisuje sposób zmaterializowania CTE na potrzeby skorelowanego podzapytania, do którego odwołuje się tylko jeden raz, chociaż korelacja może powodować wielokrotną ocenę. Nie dotyczy to zapytania w pytaniu.
Opcja 1 - przewodnik po planach
Biorąc podpowiedzi z odpowiedzi SQLKiwi, zmniejszyłem przewodnik do absolutnego minimum, które nadal wykona zadanie, np.
ConstantScan
Węzły zawierają tylko 2 operatory skalarne, które mogą wystarczająco rozwinąć się do dowolnej liczby.Opcja 2 - Zdalne skanowanie
Zwiększając koszt zapytania i wprowadzając Zdalne skanowanie, wynik jest materializowany.
źródło
Z całą powagą nie można od początku planów wykonywania XML. Tworzenie ich za pomocą SSIS to science fiction. Tak, to wszystko XML, ale pochodzą one z różnych wszechświatów. Patrząc na bloga Paula na ten temat , mówi on „na wiele sposobów, na jakie pozwala SSIS…”, więc być może źle zrozumiałeś? Nie sądzę, żeby mówił „użyj SSIS do tworzenia planów”, ale raczej „czy nie byłoby wspaniale móc tworzyć plany za pomocą interfejsu przeciągnij i upuść, takiego jak SSIS”. Być może w przypadku bardzo prostego zapytania możesz poradzić sobie z tym, ale jest to odcinek, być może nawet strata czasu. Zajęty, możesz powiedzieć.
Jeśli tworzę plan podpowiedzi PLANU UŻYTKOWANIA lub przewodnika, mam kilka sposobów. Na przykład mogę usunąć rekordy z tabel (np. Na kopii bazy danych), aby wpłynąć na statystyki i zachęcić optymalizator do podjęcia innej decyzji. Użyłem również zmiennych tabeli zamiast całej tabeli w zapytaniu, więc optymalizator uważa, że każda tabela zawiera 1 rekord. Następnie w wygenerowanym planie zastąp wszystkie zmienne tabeli oryginalnymi nazwami tabel i zamień je na plan. Inną opcją byłoby użycie opcji WITH STATS_STREAM UPDATE STATISTICS do fałszowania statystyk, która jest metodą stosowaną przy klonowaniu kopii baz danych zawierających tylko statystyki, np.
W przeszłości spędziłem trochę czasu na majstrowaniu przy planach wykonania xml i odkryłem, że w końcu SQL po prostu mówi „nie używam tego” i uruchamia zapytanie tak, jak chce.
W twoim konkretnym przykładzie jestem pewien, że wiesz, że możesz użyć set rowcount 3 lub TOP 3 w zapytaniu, aby uzyskać ten wynik, ale myślę, że nie o to ci chodzi. Prawidłowa odpowiedź będzie naprawdę być: użyć tabeli temp. Chciałbym pochwalić, że:) Nieprawidłowa odpowiedź brzmiałaby: „spędzić godziny, a nawet dni, wycinając własny niestandardowy plan wykonania XML, w którym próbujesz nakłonić optymalizator do zrobienia leniwej szpuli dla CTE, która i tak może nawet nie działać, wyglądałaby sprytnie ale byłoby również niemożliwe do utrzymania ”.
Nie staram się być niekonstruktywny, tylko moja opinia - nadzieja, która pomaga.
źródło
Wreszcie w SQL 2016 CTP 3.0 istnieje sposób, rodzaj:)
Używanie flagi śledzenia i rozszerzony wydarzenia wyszczególnione przez Dmitrija Pilugin tutaj można (nieco arbitralnie) wyłowić trzy unikalne identyfikatory GUID z pośrednich etapów realizacji zapytań.
Uwaga: Ten kod NIE jest przeznaczony do produkcji lub poważnego użycia w odniesieniu do wymuszania planu CTE, a jedynie lekkiego spojrzenia na nową flagę śledzenia i innego sposobu robienia rzeczy:
Testowane na wersji (CTP3.2) - 13.0.900.73 (x64), tylko dla zabawy.
źródło
Odkryłem, że traceflag 8649 (wymuszony równoległy plan) wywołał to zachowanie dla lewej kolumny prowadzącej w moich instancjach 2008, R2 i 2012. Nie musiałem używać flagi w SQL 2005, gdzie CTE zachowywał się poprawnie. Próbowałem użyć planu wygenerowanego w SQL 2005 w wyższych instancjach, ale nie sprawdził się.
Albo skorzystało z podpowiedzi, przewodnika po planach, w tym podpowiedzi, albo z planu wygenerowanego przez zapytanie z podpowiedzią w PLANU UŻYCIA itd. Wszystko działało.
źródło