Hat die SCHEMABINDING-Funktion einen Vorteil, der über den Halloween-Schutz hinausgeht?


52

Es ist bekannt, dass SCHEMABINDINGeine Funktion in Aktualisierungsplänen einen unnötigen Spool vermeiden kann :

Wenn Sie einfache T-SQL-UDFs verwenden, die keine Tabellen berühren (dh nicht auf Daten zugreifen), müssen Sie die SCHEMABINDINGOption beim Erstellen der UDFs angeben . Dadurch werden die UDFs schemagebunden und es wird sichergestellt, dass das Abfrageoptimierungsprogramm keine unnötigen Spool-Operatoren für Abfragepläne generiert, an denen diese UDFs beteiligt sind.

Gibt es andere Vorteile SCHEMABINDINGeiner Funktion, auch wenn sie nicht auf Daten zugreift?

Antworten:


78

Ja.

Wenn Sie nichts angeben WITH SCHEMABINDING, überspringt SQL Server die detaillierten Prüfungen, die normalerweise für den Funktionskörper durchgeführt werden. Es markiert lediglich die Funktion als Zugriff auf Daten (wie in dem in der Frage angegebenen Link angegeben).

Dies ist eine Leistungsoptimierung. Wenn dies nicht der Fall wäre, müsste SQL Server die detaillierten Prüfungen für jeden Funktionsaufruf durchführen (da sich die ungebundene Funktion jederzeit ändern könnte).

Es gibt fünf wichtige Funktionseigenschaften:

  • Determinismus
  • Präzision
  • Datenzugriff
  • Systemdatenzugriff
  • Systemüberprüfung

Nehmen Sie zum Beispiel die folgende ungebundene Skalarfunktion:

CREATE FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
AS
BEGIN
    RETURN '19000101';
END;

Wir können die fünf Eigenschaften mit einer Metadatenfunktion betrachten:

SELECT 
    IsDeterministic = OBJECTPROPERTYEX(Func.ID, 'IsDeterministic'),
    IsPrecise = OBJECTPROPERTYEX(Func.ID, 'IsPrecise'),
    IsSystemVerified = OBJECTPROPERTYEX(Func.ID, 'IsSystemVerified'),
    UserDataAccess = OBJECTPROPERTYEX(Func.ID, 'UserDataAccess'),
    SystemDataAccess = OBJECTPROPERTYEX(Func.ID, 'SystemDataAccess')
FROM (VALUES(OBJECT_ID(N'dbo.F', N'FN'))) AS Func (ID);

Ergebnis

Die beiden Datenzugriffseigenschaften wurden auf "true" und die anderen drei auf "false" gesetzt .

Dies hat Auswirkungen, die über die erwarteten hinausgehen (z. B. Verwendung in indizierten Ansichten oder indizierten berechneten Spalten).

Auswirkungen auf den Abfrageoptimierer

Die Determinism- Eigenschaft wirkt sich insbesondere auf das Abfrageoptimierungsprogramm aus. Es enthält detaillierte Regeln für die Arten von Umschreibungen und Manipulationen, die für nicht deterministische Elemente sehr eingeschränkt sind. Die Nebenwirkungen können sehr subtil sein.

Betrachten Sie beispielsweise die folgenden beiden Tabellen:

CREATE TABLE dbo.T1
(
    SomeInteger integer PRIMARY KEY
);
GO
CREATE TABLE dbo.T2
(
    SomeDate datetime PRIMARY KEY
);

... und eine Abfrage, die die Funktion verwendet (wie zuvor definiert):

SELECT * 
FROM dbo.T1 AS T1
JOIN dbo.T2 AS T2
    ON T2.SomeDate = dbo.F(T1.SomeInteger);

Der Abfrageplan ist wie erwartet und enthält eine Suche in Tabelle T2:

Plan suchen

Wenn dieselbe logische Abfrage jedoch mithilfe einer abgeleiteten Tabelle oder eines allgemeinen Tabellenausdrucks geschrieben wird:

WITH CTE AS
(
    SELECT *, dt = dbo.F(T1.SomeInteger) 
    FROM dbo.T1 AS T1
)
SELECT * 
FROM CTE
JOIN dbo.T2 AS T2
    ON T2.SomeDate = CTE.dt;

-- Derived table
SELECT
    *
FROM 
(
    SELECT *, dt = dbo.F(T1.SomeInteger)
    FROM dbo.T1 AS T1
) AS T1
JOIN dbo.T2 AS T2
    ON T2.SomeDate = T1.dt;

Der Ausführungsplan enthält jetzt einen Scan, wobei das Prädikat die in einem Filter festgelegte Funktion enthält:

Plan scannen

Dies ist auch der Fall, wenn die abgeleitete Tabelle oder der allgemeine Tabellenausdruck durch eine Ansicht oder eine Inline-Funktion ersetzt wird. Ein FORCESEEKHinweis (und andere ähnliche Versuche) wird nicht erfolgreich sein:

Fehlermeldung

Das grundlegende Problem besteht darin, dass das Abfrageoptimierungsprogramm nicht deterministische Abfrageelemente nicht so frei neu anordnen kann .

Um eine Suche zu erzeugen, müsste das Filter-Prädikat im Plan in den T2-Datenzugriff verschoben werden. Diese Bewegung wird verhindert, wenn die Funktion nicht deterministisch ist.

Fix

Das Update für dieses Beispiel umfasst zwei Schritte:

  1. Hinzufügen WITH SCHEMABINDING
  2. Machen Sie die Funktion deterministisch

Der erste Schritt ist trivial. Die zweite beinhaltet das Entfernen des nicht deterministischen impliziten Casts von string to datetime; Ersetzen Sie es mit einem deterministischen CONVERT. Beides allein reicht nicht aus .

ALTER FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    -- Convert with a deterministic style
    RETURN CONVERT(datetime, '19000101', 112);
END;

Die Funktionseigenschaften sind jetzt:

Neue Eigenschaften

Wenn der Optimierer freigegeben ist, erzeugen alle Beispiele jetzt den gewünschten Suchplan .


Beachten Sie, dass die Verwendung eines CASTto datetimein der Funktion nicht funktioniert, da in dieser Syntax kein Konvertierungsstil angegeben werden kann:

ALTER FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    -- Convert with a deterministic style
    RETURN CAST('19000101' AS datetime);
END;

Diese Funktionsdefinition erzeugt den Scanplan und die Eigenschaften zeigen, dass er nicht deterministisch bleibt:

Eigenschaften der CAST-Funktion

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.