it-swarm.com.de

Gibt es eine Möglichkeit, zu verhindern, dass skalare UDFs in berechneten Spalten die Parallelität hemmen?

Es wurde viel über die Gefahren von skalaren UDFs in SQL Server geschrieben. Eine gelegentliche Suche liefert Unmengen von Ergebnissen.

Es gibt jedoch einige Stellen, an denen eine skalare UDF die einzige Option ist.

Als Beispiel: Beim Umgang mit XML: XQuery kann nicht als berechnete Spaltendefinition verwendet werden. Eine von Microsoft dokumentierte Option besteht darin, eine Scalar UDF zu verwenden, um Ihre XQuery in eine Scalar UDF zu kapseln, und sie dann in einer berechneten Spalte zu verwenden.

Dies hat verschiedene Auswirkungen und einige Problemumgehungen.

  • Wird zeilenweise ausgeführt, wenn die Tabelle abgefragt wird
  • Erzwingt, dass alle Abfragen für die Tabelle seriell ausgeführt werden

Sie können die zeilenweise Ausführung umgehen, indem Sie die Funktion schemabinden und entweder die berechnete Spalte beibehalten oder indizieren. Keine dieser Methoden kann die erzwungene Serialisierung von Abfragen verhindern, die in die Tabelle gelangen, selbst wenn nicht auf die skalare UDF verwiesen wird.

Gibt es einen bekannten Weg, das zu tun?

29
Erik Darling

Ja wenn Sie:

  • führen SQL Server 2014 oder höher aus; und
  • können die Abfrage mit aktivem Trace-Flag 176 ausführen; und
  • die berechnete Spalte lautet PERSISTED

Insbesondere sind mindestens die folgenden Versionen erforderlich :

  • Kumulatives Update 2 für SQL Server 2016 SP1
  • Kumulatives Update 4 für SQL Server 2016 RTM
  • Kumulatives Update 6 für SQL Server 2014 SP2

[~ # ~] aber [~ # ~] , um einen Fehler zu vermeiden (siehe 2014 und 2016 und 2017 ), die in diesen Fixes eingeführt wurden, gelten stattdessen:

Das Ablaufverfolgungsflag ist als Startoption –T Sowohl im globalen als auch im Sitzungsbereich mit DBCC TRACEON Und pro Abfrage mit OPTION (QUERYTRACEON) oder einer Plananleitung wirksam.

Das Ablaufverfolgungsflag 176 verhindert die dauerhafte Erweiterung der berechneten Spalte.

Das anfängliche Laden der Metadaten beim Kompilieren einer Abfrage führt zu allen Spalten, nicht nur zu den Spalten, auf die direkt verwiesen wird. Dadurch werden alle berechneten Spaltendefinitionen für den Abgleich verfügbar, was im Allgemeinen eine gute Sache ist.

Als unglücklicher Nebeneffekt deaktiviert das Vorhandensein der Parallelität für die gesamte Abfrage, wenn eine der geladenen (berechneten) Spalten eine skalare benutzerdefinierte Funktion verwendet , auch wenn die berechnete Spalte nicht tatsächlich verwendet wird .

Das Ablaufverfolgungsflag 176 hilft dabei, wenn die Spalte beibehalten wird, indem die Definition nicht geladen wird (da die Erweiterung übersprungen wird). Auf diese Weise ist im kompilierten Abfragebaum niemals eine skalare benutzerdefinierte Funktion vorhanden, sodass die Parallelität nicht deaktiviert wird.

Der Hauptnachteil des Ablaufverfolgungsflags 176 (abgesehen davon, dass es nur leicht dokumentiert ist) besteht darin, dass es auch die Übereinstimmung von Abfrageausdrücken mit persistierten berechneten Spalten verhindert: Wenn die Abfrage einen Ausdruck enthält, der mit einer persistierten berechneten Spalte übereinstimmt, verhindert das Ablaufverfolgungsflag 176, dass der Ausdruck durch ersetzt wird ein Verweis auf die berechnete Spalte.

Weitere Informationen finden Sie in meinem SQLPerformance.com-Artikel ordnungsgemäß persistierte berechnete Spalten .

Da in der Frage XML als Alternative zur Förderung von Werten mithilfe einer berechneten Spalten- und Skalarfunktion erwähnt wird, können Sie auch die Verwendung eines selektiven XML-Index in Betracht ziehen, wie Sie in Selektive XML-Indizes: Überhaupt nicht schlecht beschrieben haben =.

31
Paul White 9

Zusätzlich zu @ Pauls ausgezeichnetem Ja # 1 gibt es tatsächlich ein Ja # 2 dass:

  • funktioniert bereits in SQL Server 2005,
  • erfordert kein Setzen eines Trace-Flags,
  • erfordert nicht, dass die berechnete Spalte PERSISTED ist, und
  • (da kein Trace-Flag 176 erforderlich ist), verhindert nicht den Abgleich von Abfrageausdrücken mit persistierten berechneten Spalten

Die einzigen Nachteile (soweit ich das beurteilen kann) sind:

  • funktioniert nicht in der Azure SQL-Datenbank (zumindest noch nicht, obwohl es sowohl in Amazon RDS SQL Server als auch in SQL Server unter Linux funktioniert) und
  • liegt etwas außerhalb der Komfortzone vieler DBAs

Und diese Option ist: [~ # ~] sqlclr [~ # ~]

Das stimmt. Ein cooler Aspekt von SQLCLR Scalar UDFs ist, dass wenn sie keinen any Datenzugriff haben (weder Benutzer noch System), dann verbieten sie keine Parallelität. Und das ist nicht nur Theorie oder Marketing. Obwohl ich (im Moment) keine Zeit habe, die ausführliche Beschreibung zu erstellen, habe ich dies getestet und bewiesen.

Ich habe das anfängliche Setup aus dem folgenden Blog-Beitrag verwendet (hoffentlich betrachtet die O.P. dies nicht als unzuverlässige Quelle ????):

Bad Idea Jeans: Mehrere Index-Hinweise

Und führte die folgenden Tests durch:

  1. Die erste Abfrage wurde wie folgt ausgeführt: ─⇾ Parallelität (wie erwartet)
  2. Es wurde eine nicht persistierte berechnete Spalte hinzugefügt, die als ([c2] * [c3]) Definiert ist. ─⇾ Parallelität (wie erwartet)
  3. Diese berechnete Spalte wurde entfernt und eine nicht persistierte berechnete Spalte hinzugefügt, die auf eine T-SQL-skalare UDF (erstellt mit SCHEMABINDING) verweist, die als RETURN (@First * @Second); ─⇾ NO Parallelism (wie erwartet) definiert ist.
  4. Die berechnete T-SQL UDF-Spalte wurde entfernt und eine nicht persistierte berechnete Spalte hinzugefügt, die auf eine skalare SQLCLR-UDF verweist (versucht mit IsDeterministic = true Und = false), Definiert als return SqlInt32.Multiply(First, Second); ─ ⇾ Parallelität (woo hoo !!)

Obwohl SQLCLR nicht für alle geeignet ist, hat es sicherlich seine Vorteile für diejenigen Personen/Situationen/Umgebungen, die gut zusammenpassen. Und da es sich um diese spezielle Frage handelt - das Beispiel für die Verwendung von XQuery -, würde dies sicher funktionieren (und je nachdem, was speziell getan wird, könnte es sogar etwas schneller sein ????).

10
Solomon Rutzky