Czy obsługa Parallel Scalar UDF jest uzasadnionym żądaniem funkcji?

10

Jest dość dobrze udokumentowane, że skalarne UDF wymuszają ogólny plan szeregowy.

Uruchamianie funkcji równolegle

Biorąc pod uwagę dużą liczbę wierszy wchodzących w punkt w rurociągu, w którym należy obliczyć współczynnik UDF, dlaczego silnik nie może po prostu rozdzielić ich między procesory? Jeśli nie ma stanu w UDF, kolejność nie powinna mieć znaczenia.

Istnieją twierdzenia, że ​​UDF jest czarne pudełko musi używać kursora. Widzę, że kursor użytkownika nie może być zrównoleglony w SP dla przypadków, w których pewien stan jest utrzymywany między iteracjami, ale wydaje się, że w przeciwnym razie powinien być równoległy.

Dodatkowe punkty za wyjaśnienie, dlaczego silnik wymusza szeregowanie całego planu zamiast samego etapu obliczeń UDF.

Czy wsparcie dla równoległego UDF jest rozsądną funkcją, o którą można poprosić?

Crokusek
źródło
1
Wydaje się, że odpowiednią reakcją jest, jak zauważono w zaakceptowanej odpowiedzi na twój link, przepisanie dowolnych Skalarnych Funkcji Zdefiniowanych przez Użytkownika jako jednokolumnowe Funkcje Inline-Valued Table . Są one rozszerzane w taki sam sposób jak widok, a zatem są w pełni zoptymalizowane. Czy w tym świetle twoje pytanie wciąż ma wartość?
Pieter Geerkens
1
Tak po sukcesie z obejściem TVF. Zapytałem, ponieważ niewłaściwe wydaje się unikanie stosowania takiego naturalnego konstruktu. Wydaje się również, że niepraktyczne jest oczekiwanie, że nowi programiści SQL nauczą się wewnętrznych funkcji UDF.
crokusek
Wyjaśniający komentarz. Sukces z ITVF, ale nie z wieloma deklaracjami TVF.
crokusek

Odpowiedzi:

17

Jest dość dobrze udokumentowane, że UDF wymuszają ogólny plan szeregowy.

Nie jestem pewien, czy to wszystko jest tak dobrze udokumentowane.

  • Skalarna funkcja T-SQL zapobiega równoległości w dowolnym miejscu w planie.
  • Skalarną funkcję CLR można wykonywać równolegle, o ile nie ma ona dostępu do bazy danych.
  • Funkcja T-SQL o wielu instrukcjach o wartości tabeli wymusza strefę szeregową w planie, który może wykorzystywać równoległość w innym miejscu.
  • Wbudowana w tabelę funkcja T-SQL jest rozwinięta jak widok, więc nie ma bezpośredniego efektu.

Zobacz Wymuszanie planu równoległego wykonywania i / lub prezentację równoległego wykonywania Craiga Freedmana .

Istnieją twierdzenia, że ​​UDF jako czarna skrzynka muszą używać kursora.

Twierdzenia te są nieprawidłowe.

Dodatkowe punkty za wyjaśnienie, dlaczego silnik wymusza szeregowanie całego planu zamiast samego etapu obliczeń UDF.

Rozumiem, że obecne ograniczenia są wyłącznie wynikiem pewnych szczegółów implementacyjnych. Nie ma podstawowego powodu, dla którego funkcje nie mogłyby być wykonywane przy użyciu równoległości.

W szczególności funkcje skalarne T-SQL wykonują się w osobnym kontekście T-SQL, co znacznie komplikuje prawidłowe działanie, koordynację i zamknięcie (szczególnie w przypadku błędu).

Podobnie, zmienne tabelowe ogólnie obsługują odczyty równoległe (ale nie zapisują), ale zmienna tabelowa ujawniona przez funkcję wycenioną w tabeli nie jest w stanie obsługiwać odczytów równoległych z powodów specyficznych dla implementacji. Obawiam się, że potrzebujesz kogoś z dostępem do kodu źródłowego (i swobodą udostępniania szczegółów), aby udzielić wiarygodnej odpowiedzi.

Czy wsparcie dla równoległego UDF jest rozsądną funkcją, o którą można poprosić?

Oczywiście, jeśli potrafisz zrobić wystarczająco mocną skrzynkę. Uważam, że zaangażowana praca byłaby obszerna, więc twoja propozycja musiałaby spełnić bardzo wysoki poziom. Na przykład powiązane (i znacznie prostsze) żądanie dostarczenia wbudowanych funkcji skalarnych ma świetne wsparcie, ale od lat nie funkcjonuje.


Może chcesz przeczytać artykuł Microsoft:

... który przedstawia podejście, jakie Microsoft zamierza zastosować w celu rozwiązania problemów z wydajnością funkcji skalarnej T-SQL w wydaniu po SQL Server 2017.

Celem Froid jest umożliwienie programistom korzystania z abstrakcji funkcji UDF i procedur bez uszczerbku dla wydajności. Froid osiąga ten cel za pomocą nowatorskiej techniki automatycznego przekształcania programów imperatywnych w równoważne relacyjne formy algebraiczne, gdy tylko jest to możliwe. Froid modeluje bloki kodu imperatywnego jako wyrażenia relacyjne i systematycznie łączy je w jedno wyrażenie za pomocą operatora Zastosuj, umożliwiając w ten sposób optymalizatorowi zapytań wybranie wydajnych, równoległych planów zapytań zorientowanych na zestaw .

(moje podkreślenie)


Wbudowane funkcje skalarne T-SQL są teraz zaimplementowane w SQL Server 2019 .

Paul White 9
źródło
11

Jak słusznie wspomniał Paul w swojej odpowiedzi, nie ma podstawowego powodu, dla którego skalarne UDF nie mogą być wykonywane przy użyciu równoległości. Jednak oprócz wyzwań związanych z implementacją istnieje jeszcze jeden powód, aby wymusić ich szeregowość. Artykuł Froida cytowany przez Paula daje więcej informacji na ten temat.

Cytowanie z pracy (sekcja 2.3):

Obecnie SQL Server nie stosuje równoległości wewnątrz zapytań w zapytaniach wywołujących UDF. Można zaprojektować metody łagodzące to ograniczenie, ale wprowadzają one dodatkowe wyzwania, takie jak wybranie odpowiedniego stopnia równoległości dla każdego wywołania UDF.

Rozważmy na przykład UDF, który wywołuje inne zapytania SQL, takie jak te z rysunku 1. Każde takie zapytanie może korzystać z równoległości, dlatego optymalizator nie może wiedzieć, jak współdzielić wątki między nimi, chyba że zajrzy do UDF i decyduje o stopniu równoległości dla każdego zapytania w obrębie (które może potencjalnie zmienić się z jednego wywołania na drugie). W przypadku zagnieżdżonych i rekurencyjnych UDF ten problem staje się jeszcze trudniejszy do zarządzania.

Podejście Froid, jak opisano w artykule, przyniesie nie tylko równoległe plany, ale także doda wiele innych korzyści dla zapytań z UDF. W gruncie rzeczy obejmuje twoje żądanie równoległego wykonywania UDF.

Aktualizacja: Froid jest teraz dostępny jako funkcja podglądu SQL Server 2019. Funkcja nosi nazwę „Skalarne wstawianie UDF”. Więcej informacji tutaj: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2018/11/07/introducing-scalar-udf-inlining/

[Ujawnienie: Jestem współautorem artykułu Froid]

Karthik
źródło
Bardzo dobre! Jeśli dobrze rozumiem, to będzie skutecznie wewnętrznie automatycznie konwertować UDF na ITVF. Zrobiliśmy to przez kilka (w / deklaruje / if / else) i zrobiliśmy niezły bałagan. Mieliśmy nawet „kolumnę” debugowania.
crokusek
1
W rzeczywistości nie przekształca UDF w ITVF, ale twoja intuicja jest prawidłowa. Wykonanie tego ręcznie na poziomie zapytań SQL jest naprawdę skomplikowane w przypadku złożonych UDF. Froid dokonuje tej transformacji na relacyjnym drzewie algebry, co pozwala uniknąć bałaganu :)
Karthik
@Karthik mógłbyś spojrzeć na dba.stackexchange.com/questions/202211/… . Naprawdę chciałbym wiedzieć, jak Froid poradzi sobie w opisanej sprawie
Roman Pekar
@Roman Skomentowałem twoje pytanie.
Karthik
1
Dziękuję, @Karthik, za pracę, którą wykonałeś na papierze Froid i za twoje (i grupy) wysiłki w celu poprawy użyteczności skalarnych UDF :-)
Solomon Rutzky