Ist die Unterstützung von Parallel Scalar UDF eine vernünftige Funktionsanforderung?

10

Es ist ziemlich gut dokumentiert, dass skalare UDFs einen allgemeinen Serienplan erzwingen.

Funktionen parallel ausführen

Warum kann die Engine angesichts einer großen Anzahl von Zeilen, die an einen Punkt in der Pipeline gelangen, an dem eine UDF berechnet werden muss, diese nicht einfach auf die Prozessoren verteilen? Wenn es innerhalb einer UDF keinen Status gibt, sollte die Reihenfolge keine Rolle spielen.

Es gibt Behauptungen, dass UDFs als Blackbox den Cursor verwenden müssen. Ich kann sehen, dass ein Benutzercursor innerhalb eines SP nicht parallelisiert werden kann, wenn zwischen den Iterationen ein bestimmter Status beibehalten wird, der ansonsten jedoch parallelisierbar sein sollte.

Zusätzliche Punkte zur Erklärung, warum der Motor den gesamten Plan als seriell erzwingt, anstatt nur die UDF-Berechnungsstufe.

Ist die Unterstützung von paralleler UDF eine sinnvolle Funktion?

crokusek
quelle
1
Die in der akzeptierten Antwort auf Ihren Link angegebene Reaktion scheint darin zu bestehen, skalare benutzerdefinierte Funktionen als einspaltige Inline-Funktionen mit Tabellenwerten neu zu schreiben . Diese werden wie eine Ansicht erweitert und somit vollständig optimiert. Hat Ihre Frage in diesem Licht noch einen Wert?
Pieter Geerkens
1
Ja zum Erfolg mit der TVF-Problemumgehung. Ich fragte, weil es falsch erscheint, die Verwendung eines solchen natürlichen Konstrukts zu vermeiden. Es erscheint auch unpraktisch zu erwarten, dass neue SQL-Entwickler UDF-Interna lernen.
Crokusek
Klarstellender Kommentar. Erfolg mit ITVF, aber nicht mit TVF mit mehreren Aussagen.
Crokusek

Antworten:

17

Es ist ziemlich gut dokumentiert, dass UDFs einen seriellen Gesamtplan erzwingen.

Ich bin mir nicht sicher, ob das alles so gut dokumentiert ist.

  • Eine skalare T-SQL-Funktion verhindert Parallelität an einer beliebigen Stelle im Plan.
  • Eine skalare CLR-Funktion kann parallel ausgeführt werden, solange sie nicht auf die Datenbank zugreift.
  • Eine T-SQL-Funktion mit mehreren Anweisungen und Tabellen erzwingt eine serielle Zone in einem Plan, die möglicherweise an anderer Stelle Parallelität verwendet.
  • Eine Inline-T-SQL-Funktion mit Tabellenwert wird wie eine Ansicht erweitert und hat daher keine direkten Auswirkungen.

Siehe Erzwingen eines parallelen Ausführungsplans und / oder Craig Freedmans Präsentation zur parallelen Ausführung .

Es gibt Behauptungen, dass UDFs als Blackbox den Cursor verwenden müssen.

Diese Behauptungen sind nicht korrekt.

Zusätzliche Punkte zur Erklärung, warum der Motor den gesamten Plan als seriell erzwingt, anstatt nur die UDF-Berechnungsstufe.

Nach meinem Verständnis sind die aktuellen Einschränkungen lediglich das Ergebnis bestimmter Implementierungsdetails. Es gibt keinen fundamentalen Grund, warum Funktionen nicht parallel ausgeführt werden könnten.

Insbesondere werden T-SQL-Skalarfunktionen in einem separaten T-SQL-Kontext ausgeführt, was den korrekten Betrieb, die Koordination und das Herunterfahren (insbesondere im Fehlerfall) erheblich erschwert.

Ebenso unterstützen Tabellenvariablen im Allgemeinen parallele Lesevorgänge (aber keine Schreibvorgänge), aber die Tabellenvariable, die von einer Tabellenwertfunktion verfügbar gemacht wird, kann aus implementierungsspezifischen Gründen keine parallelen Lesevorgänge unterstützen. Ich fürchte, Sie benötigen jemanden mit Quellcode-Zugriff (und der Freiheit, Details auszutauschen), um eine maßgebliche Antwort zu geben.

Ist die Unterstützung von paralleler UDF eine sinnvolle Funktion?

Natürlich, wenn Sie stark genug argumentieren können. Mein eigenes Gefühl ist, dass die damit verbundene Arbeit umfangreich wäre, sodass Ihr Vorschlag eine extrem hohe Messlatte erreichen müsste . Zum Beispiel hat eine verwandte (und viel einfachere) Anforderung , Inline-Skalarfunktionen bereitzustellen, große Unterstützung, ist jedoch seit Jahren nicht mehr implementiert.


Vielleicht möchten Sie das Microsoft-Papier lesen:

... beschreibt den Ansatz, den Microsoft bei der Behebung von Leistungsproblemen mit T-SQL-Skalarfunktionen in der Version nach SQL Server 2017 verfolgen möchte.

Das Ziel von Froid ist es, Entwicklern die Verwendung der Abstraktionen von UDFs und Prozeduren zu ermöglichen, ohne die Leistung zu beeinträchtigen. Froid erreicht dieses Ziel mithilfe einer neuartigen Technik, um imperative Programme nach Möglichkeit automatisch in äquivalente relationale algebraische Formen umzuwandeln. Froid modelliert Blöcke imperativen Codes als relationale Ausdrücke und kombiniert sie mithilfe des Apply-Operators systematisch zu einem einzigen Ausdruck. Dadurch kann der Abfrageoptimierer effiziente satzorientierte parallele Abfragepläne auswählen .

(Hervorhebung von mir)


Inline-skalare T-SQL-Funktionen sind jetzt in SQL Server 2019 implementiert .

Paul White 9
quelle
11

Wie Paulus in seiner Antwort zu Recht erwähnt hat, gibt es keinen fundamentalen Grund, warum skalare UDFs nicht mit Parallelität ausgeführt werden könnten. Abgesehen von den Implementierungsproblemen gibt es jedoch noch einen weiteren Grund, sie zur Serialisierung zu zwingen. Das von Paul zitierte Froid- Papier enthält weitere Informationen dazu.

Zitat aus dem Papier (Abschnitt 2.3):

Derzeit verwendet SQL Server keine Abfrage-Parallelität in Abfragen, die UDFs aufrufen. Methoden können entwickelt werden, um diese Einschränkung zu mildern, sie bringen jedoch zusätzliche Herausforderungen mit sich, z. B. die Auswahl des richtigen Parallelitätsgrads für jeden Aufruf der UDF.

Stellen Sie sich zum Beispiel eine UDF vor, die andere SQL-Abfragen aufruft, wie die in Abbildung 1. Jede dieser Abfragen verwendet möglicherweise selbst Parallelität. Daher kann der Optimierer nicht wissen, wie Threads zwischen ihnen geteilt werden sollen, es sei denn, er untersucht die UDF und entscheidet über den Grad der Parallelität für jede Abfrage innerhalb (die sich möglicherweise von einem Aufruf zum anderen ändern kann). Mit verschachtelten und rekursiven UDFs wird dieses Problem noch schwieriger zu verwalten.

Der in diesem Artikel beschriebene Ansatz von Froid führt nicht nur zu parallelen Plänen, sondern bietet auch viele weitere Vorteile für Abfragen mit UDFs. Im Wesentlichen wird Ihre Anforderung zur parallelen Ausführung von UDFs zusammengefasst.

Update: Froid ist jetzt als Funktion der SQL Server 2019-Vorschau verfügbar. Die Funktion heißt "Scalar UDF Inlining". Weitere Details hier: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2018/11/07/introducing-scalar-udf-inlining/

[Offenlegung: Ich bin Mitautor des Froid-Papiers]

Karthik
quelle
Sehr gut! Wenn ich das richtig verstehe, wird die UDF intern effektiv automatisch in eine ITVF konvertiert. Wir hatten dies für ein paar gemacht (w / deklariert / if / else) und machten ein schönes Durcheinander. Wir hatten sogar eine Debug- "Spalte".
Crokusek
1
Die UDF wird nicht in eine ITVF konvertiert, aber Ihre Intuition ist korrekt. Dies manuell auf SQL-Abfrageebene zu tun, ist für komplexe UDFs sehr umständlich. Froid macht diese Transformation auf dem relationalen Algebra-Baum, der das Durcheinander vermeidet :)
Karthik
@Karthik könnten Sie einen Blick auf dba.stackexchange.com/questions/202211/… werfen . Ich würde wirklich gerne wissen, wie Froid in dem beschriebenen Fall abschneiden wird
Roman Pekar
@ Roman Ich habe Ihre Frage kommentiert.
Karthik
1
Vielen Dank, @Karthik, für die Arbeit, die Sie am Froid-Papier geleistet haben, und für Ihre (und die der Gruppen) Bemühungen, die Benutzerfreundlichkeit skalarer UDFs zu verbessern :-)
Solomon Rutzky