Abfragehinweise (Transact-SQL)

Abfragehinweise setzen das Standardverhalten des Abfrageoptimierers für die Dauer der Abfrageanweisung außer Kraft. Mit Abfragehinweisen können Sie eine Sperrmethode für die betreffenden Tabellen, einen Index oder mehrere Indizes, einen Abfrageverarbeitungsvorgang, beispielsweise einen Tabellenscan oder eine Indexsuche, oder andere Optionen angeben. Abfragehinweise werden auf die gesamte Abfrage angewendet.

VorsichtshinweisVorsicht

Da der SQL Server-Abfrageoptimierer in der Regel den optimalen Ausführungsplan für eine Abfrage auswählt, wird empfohlen, dass nur erfahrene Entwickler und Datenbankadministratoren Hinweise verwenden, wenn alle anderen Möglichkeiten sich als unbefriedigend erwiesen haben.

Betrifft:

DELETE

INSERT

SELECT

UPDATE

MERGE

Themenlink (Symbol)Transact-SQL-Syntaxkonventionen

Syntax

        <query_hint > ::= 
{ { HASH | ORDER } GROUP 
  | { CONCAT | HASH | MERGE } UNION 
  | { LOOP | MERGE | HASH } JOIN 
  | FAST number_rows 
  | FORCE ORDER 
  | MAXDOP number_of_processors 
  | OPTIMIZE FOR ( @variable_name { UNKNOWN | = literal_constant } [ , ...n ] )
  | OPTIMIZE FOR UNKNOWN
  | PARAMETERIZATION { SIMPLE | FORCED }
  | RECOMPILE
  | ROBUST PLAN 
  | KEEP PLAN 
  | KEEPFIXED PLAN
  | EXPAND VIEWS 
  | MAXRECURSION number 
  | USE PLAN N'xml_plan'
  | TABLE HINT ( exposed_object_name [ , <table_hint> [ [, ]...n ] ] )
}

<table_hint> ::=
[ NOEXPAND ] { 
    INDEX (index_value [ ,...n ] ) | INDEX = (index_value)
  | FASTFIRSTROW 
  | FORCESEEK [(index_value(index_column_name [,... ] )) ]
  | FORCESCAN
  | HOLDLOCK 
  | NOLOCK 
  | NOWAIT
  | PAGLOCK 
  | READCOMMITTED 
  | READCOMMITTEDLOCK 
  | READPAST 
  | READUNCOMMITTED 
  | REPEATABLEREAD 
  | ROWLOCK 
  | SERIALIZABLE 
  | TABLOCK 
  | TABLOCKX 
  | UPDLOCK 
  | XLOCK 
}

Argumente

  • { HASH | ORDER } GROUP
    Gibt an, dass die in der GROUP BY-, DISTINCT- oder der COMPUTE-Klausel der Abfrage beschriebenen Aggregationen Hash- oder Sortiervorgänge verwenden sollen.

  • { MERGE | HASH | CONCAT } UNION
    Gibt an, dass alle UNION-Vorgänge mithilfe von Merge-, Hash- oder Verkettungsvorgängen für die bei UNION vorkommenden Mengen ausgeführt werden. Wenn mehr als ein UNION-Hinweis angegeben wird, wählt der Abfrageoptimierer unter den angegebenen Hinweisen die Strategie mit dem geringsten Aufwand aus.

  • { LOOP | MERGE | HASH } JOIN
    Gibt an, dass alle Verknüpfungsvorgänge per LOOP JOIN, MERGE JOIN oder HASH JOIN in der gesamten Abfrage ausgeführt werden. Wenn mehr als ein Joinhinweis angegeben wird, wählt der Optimierer unter den zulässigen Hinweisen die Strategie mit dem geringsten Aufwand aus.

    Wenn in derselben Abfrage auch ein Joinhinweis in der FROM-Klausel für ein bestimmtes Tabellenpaar angegeben ist, hat dieser Joinhinweis Vorrang bei der Verknüpfung der beiden Tabellen; die Abfragehinweise müssen jedoch auch berücksichtigt werden. Deshalb kann der Joinhinweis für das Tabellenpaar nur die Auswahl der zulässigen Joinmethoden für den Abfragehinweis einschränken. Weitere Informationen finden Sie unter Joinhinweise (Transact-SQL).

  • FAST number_rows
    Gibt an, dass die Abfrage für den schnellen Abruf der ersten number_rows. (eine nicht negative ganze Zahl) optimiert wird. Nachdem die ersten number_rows zurückgegeben wurden, wird die Abfrage fortgesetzt und das vollständige Resultset erstellt.

  • FORCE ORDER
    Gibt an, dass die von der Abfragesyntax angegebene Joinreihenfolge während der Abfrageoptimierung beibehalten wird. Die Verwendung von FORCE ORDER hat keine Auswirkung auf das mögliche Rollentauschverhalten des Abfrageoptimierers. Weitere Informationen finden Sie unter Grundlegendes zu Hashverknüpfungen.

    In einer MERGE-Anweisung wird als Standard-Joinreihenfolge zunächst auf die Quelltabelle und dann auf die Zieltabelle zugegriffen, es sei denn, die WHEN SOURCE NOT MATCHED-Klausel wurde angegeben. Wenn Sie FORCE ORDER angeben, wird dieses Standardverhalten beibehalten.

    Informationen zur Vorgehensweise des Abfrageoptimierers von SQL Server beim Erzwingen des FORCE ORDER-Hinweises, wenn eine Abfrage eine Sicht enthält, finden Sie unter Sichtauflösung.

  • MAXDOP number
    Setzt die Konfigurationsoption max degree of parallelism von sp_configure und die Ressourcenkontrolle für die Abfrage außer Kraft, in der diese Option angegeben wird. Der MAXDOP-Abfragehinweis kann den mit sp_configure konfigurierten Wert überschreiten. Wenn MAXDOP den mit der Ressourcenkontrolle konfigurierten Wert überschreitet, verwendet Database Engine (Datenbankmodul) den in ALTER WORKLOAD GROUP (Transact-SQL) beschriebenen MAXDOP-Wert der Ressourcenkontrolle. Alle semantischen Regeln, die mit der Konfigurationsoption max degree of parallelism verwendet werden können, stehen beim Verwenden des MAXDOP-Abfragehinweises zur Verfügung. Weitere Informationen finden Sie unter max degree of parallelism (Option).

    VorsichtshinweisVorsicht

    Wenn MAXDOP auf 0 (Null) festgelegt wird, wählt der Server den maximalen Grad an Parallelität aus.

  • OPTIMIZE FOR ( @variable_name { UNKNOWN | = literal_constant } [ , ...n ] )
    Weist den Abfrageoptimierer an, einen bestimmten Wert für eine lokale Variable zu verwenden, wenn die Abfrage kompiliert und optimiert wird. Dieser Wert wird nur während der Abfrageoptimierung verwendet, nicht während der Abfrageausführung.

    • @variable_name
      Der Name einer lokalen Variablen, die in einer Abfrage verwendet wird und der ein Wert für die Verwendung mit dem OPTIMIZE FOR-Abfragehinweis zugewiesen werden kann.

    • UNKNOWN
      Gibt an, dass der Abfrageoptimierer statistische Daten statt des Anfangswerts verwenden soll, um während der Abfrageoptimierung den Wert einer lokalen Variablen zu bestimmen.

    • literal_constant
      Ein Literalkonstantenwert, dem @variable_name für die Verwendung mit dem OPTIMIZE FOR-Abfragehinweis zugewiesen werden soll. literal_constant wird nur während der Abfrageoptimierung verwendet, nicht während der Abfrageausführung als Wert von @variable_name. Für literal_constant ist jeder SQL Server-Systemdatentyp möglich, der als Literalkonstante ausgedrückt werden kann. Der Datentyp von literal_constant muss implizit in den Datentyp konvertierbar sein, auf den @variable_name in der Abfrage verweist.

    OPTIMIZE FOR kann dem Standard-Parametererkennungsverhalten des Abfrageoptimierers entgegenwirken oder kann beim Erstellen von Planhinweislisten verwendet werden. Weitere Informationen finden Sie unter Erneutes Kompilieren gespeicherter Prozeduren und Optimieren von Abfragen in bereitgestellten Anwendungen mit Planhinweislisten.

  • OPTIMIZE FOR UNKNOWN
    Weist den Abfrageoptimierer an, beim Kompilieren und Optimieren der Abfrage für alle lokalen Variablen, einschließlich der Parameter, die mit erzwungener Parametrisierung erstellt werden, statistische Daten statt der Anfangswerte zu verwenden. Weitere Informationen zu erzwungener Parametrisierung finden Sie unter Erzwungene Parametrisierung.

    Werden OPTIMIZE FOR @variable_name = literal_constant und OPTIMIZE FOR UNKNOWN im selben Abfragehinweis verwendet, verwendet der Abfrageoptimierer die literal_constant, die für einen bestimmten Wert angegeben wurde, und UNKNOWN für die übrigen Variablenwerte. Diese Werte werden nur während der Abfrageoptimierung verwendet, nicht während der Abfrageausführung.

  • PARAMETERIZATION { SIMPLE | FORCED }
    Gibt die Parametrisierungsregeln an, die der SQL Server-Abfrageoptimierer bei der Kompilierung auf die Abfrage anwendet.

    Wichtiger HinweisWichtig

    Der PARAMETERIZATION-Abfragehinweis kann nur innerhalb einer Planhinweisliste angegeben werden. Er kann nicht direkt innerhalb einer Abfrage angegeben werden.

    Mit SIMPLE wird der Abfrageoptimierer angewiesen, einfache Parametrisierung auszuführen. Mit FORCED wird der Optimierer angewiesen, erzwungene Parametrisierung auszuführen. Mit dem PARAMETERIZATION-Abfragehinweis wird die aktuelle Einstellung der Option PARAMETERIZATION database SET innerhalb einer Planhinweisliste außer Kraft gesetzt. Weitere Informationen finden Sie unter Angeben des Abfrageparametrisierungsverhaltens mithilfe von Planhinweislisten.

  • RECOMPILE
    Weist SQL Server Database Engine (Datenbankmodul) an, den für die Abfrage generierten Abfrageplan nach der Ausführung zu verwerfen. Dadurch wird der Abfrageoptimierer gezwungen, erneut einen Abfrageplan zu kompilieren, wenn dieselbe Abfrage das nächste Mal ausgeführt wird. Ohne das Angeben von RECOMPILE werden Abfragepläne von Database Engine (Datenbankmodul) zwischengespeichert und wiederverwendet. Beim Kompilieren von Abfrageplänen verwendet der RECOMPILE-Abfragehinweis die aktuellen Werte von lokalen Variablen in der Abfrage und, falls sich die Abfrage innerhalb einer gespeicherten Prozedur befindet, die an Parameter übergebenen aktuellen Werte.

    RECOMPILE ist eine hilfreiche Alternative zum Erstellen einer gespeicherten Prozedur, die die WITH RECOMPILE-Klausel verwendet, wenn nicht die gesamte gespeicherte Prozedur, sondern nur eine Teilmenge davon erneut kompiliert werden muss. Weitere Informationen finden Sie unter Erneutes Kompilieren gespeicherter Prozeduren. RECOMPILE ist auch beim Erstellen von Planhinweislisten hilfreich. Weitere Informationen finden Sie unter Optimieren von Abfragen in bereitgestellten Anwendungen mit Planhinweislisten.

  • ROBUST PLAN
    Zwingt den Abfrageoptimierer zu einer Vorgehensweise, bei der der Schwerpunkt auf der maximalen potenziellen Zeilengröße liegt. Dies geht möglicherweise zu Lasten der Leistung. Bei der Verarbeitung der Abfrage müssen möglicherweise Zwischentabellen und Operatoren Zeilen speichern und verarbeiten, die größer sind als alle Eingabezeilen. Die Zeilen können so groß sein, dass der jeweilige Operator in einigen Fällen die Zeile nicht verarbeiten kann. In diesem Fall gibt Database Engine (Datenbankmodul) während der Ausführung der Abfrage einen Fehler aus. Durch das Verwenden von ROBUST PLAN weisen Sie den Abfrageoptimierer an, keine Abfragepläne in Betracht zu ziehen, für die möglicherweise dieses Problem auftritt.

    Ist eine solche Vorgehensweise nicht möglich, gibt der Abfrageoptimierer einen Fehler zurück, statt die Fehlererkennung auf die Abfrageausführung zu verschieben. Die Zeilen können Spalten variabler Länge aufweisen. Database Engine (Datenbankmodul) läßt die Definition von Zeilen zu, deren maximale potenzielle Größe von Database Engine (Datenbankmodul) nicht mehr verarbeitet werden kann. Trotz der maximalen potenziellen Größe speichert eine Anwendung im Allgemeinen Zeilen, deren tatsächliche Größe innerhalb der Höchstwerte liegen, die Database Engine (Datenbankmodul) verarbeiten kann. Wenn Database Engine (Datenbankmodul) eine Zeile ermittelt, die zu lang ist, wird ein Ausführungsfehler zurückgegeben.

  • KEEP PLAN
    Zwingt den Abfrageoptimierer, den geschätzten Neukompilierungsschwellenwert für eine Abfrage zu lockern. Der geschätzte Neukompilierungsschwellenwert gibt den Punkt an, bei dem eine Abfrage automatisch erneut kompiliert wird, wenn für eine Tabelle die geschätzte Anzahl von Änderungen für indizierte Spalten durch Ausführen der Anweisungen UPDATE, DELETE, MERGE oder INSERT vorgenommen wurden. Durch Angeben von KEEP PLAN wird sichergestellt, dass eine Abfrage nicht zu häufig erneut kompiliert wird, wenn an einer Tabelle mehrere Aktualisierungen ausgeführt werden.

  • KEEPFIXED PLAN
    Zwingt den Abfrageoptimierer, die Abfrage aufgrund von Änderungen in den Statistiken nicht erneut zu kompilieren. Durch Angeben von KEEPFIXED PLAN wird sichergestellt, dass eine Abfrage nur dann erneut kompiliert wird, wenn das Schema der zugrunde liegenden Tabellen geändert wird oder für diese Tabellen sp_recompile ausgeführt wird.

  • EXPAND VIEWS
    Gibt an, dass die indizierten Sichten erweitert werden und dass der Abfrageoptimierer eine indizierte Sicht nicht als Ersatz für irgendeinen Teil der Abfrage ansieht. Eine Sicht wird erweitert, indem der Sichtname im Abfragetext durch die Sichtdefinition ersetzt wird.

    Dieser Abfragehinweis lässt die direkte Verwendung von indizierten Sichten und Indizes für indizierte Sichten im Abfrageplan praktisch nicht zu.

    Die indizierte Sicht wird nur dann nicht erweitert, wenn auf die Sicht im SELECT-Teil der Abfrage direkt verwiesen wird und WITH (NOEXPAND) oder WITH (NOEXPAND, INDEX( index_value [ ,...n ] ) ) angegeben ist. Weitere Informationen zum Abfragehinweis WITH (NOEXPAND) finden Sie unter FROM.

    Der Hinweis wirkt sich nur auf die Sichten im SELECT-Teil von Anweisungen aus, einschließlich der Sichten in den Anweisungen INSERT, UPDATE, MERGE und DELETE.

  • MAXRECURSION number
    Gibt die maximale Anzahl zugelassener Rekursionen für diese Abfrage an. number ist eine nicht negative ganze Zahl zwischen 0 und 32.767. Wenn 0 angegeben wird, wird keine Beschränkung angewendet. Wenn diese Option nicht angegeben wird, beträgt das Standardlimit für den Server 100.

    Wenn der angegebene Wert bzw. der Standardwert für MAXRECURSION während der Ausführung der Abfrage erreicht wird, wird die Abfrage beendet und ein Fehler wird zurückgegeben.

    Aufgrund dieses Fehlers wird für alle Änderungen aufgrund der Anweisung ein Rollback ausgeführt. Falls es sich hierbei um eine SELECT-Anweisung handelt, können Teilergebnisse oder keine Ergebnisse zurückgegeben werden. Teilergebnisse schließen möglicherweise nicht alle Zeilen auf Rekursionsebenen ein, die über die angegebene maximale Rekursionsebene hinausgehen.

    Weitere Informationen finden Sie unter WITH common_table_expression (Transact-SQL).

  • USE PLAN N**'xml_plan'**
    Zwingt den Abfrageoptimierer, einen vorhandenen Abfrageplan für eine Abfrage zu verwenden, die mit 'xml_plan' angegeben ist. Weitere Informationen finden Sie unter Angeben von Abfrageplänen mit Planerzwingung. USE PLAN kann nicht für die Anweisungen INSERT, UPDATE, MERGE oder DELETE angegeben werden.

  • TABLE HINT (exposed_object_name [ , <table_hint> [ [, ]...n ] ] )
    Wendet den angegebenen Tabellenhinweis auf die Tabelle oder die Sicht an, die exposed_object_name entspricht. Es wird empfohlen, einen Tabellenhinweis nur im Kontext einer Planhinweisliste als einen Abfragehinweis zu verwenden.

    exposed_object_name kann einer der folgenden Verweise sein:

    • Wenn ein Alias für die Tabelle oder die Sicht in der FROM-Klausel der Abfrage verwendet wird, ist exposed_object_name der Alias.

    • Wenn kein Alias verwendet wird, entspricht exposed_object_name genau der Tabelle oder der Sicht, auf die in der FROM-Klausel verwiesen wird. Wenn z. B. mit einem zweiteiligen Namen auf die Tabelle oder die Sicht verwiesen wird, ist exposed_object_name der gleiche zweiteilige Name.

    Wenn exposed_object_name angegeben wird, ohne dass auch ein Tabellenhinweis angegeben wird, werden alle in der Abfrage als Teil eines Tabellenhinweises für das Objekt festgelegten Indizes ignoriert, und die Indexverwendung wird vom Abfrageoptimierer bestimmt. Sie können diese Vorgehensweise verwenden, um die Auswirkung eines INDEX-Tabellenhinweises zu eliminieren, wenn Sie die ursprüngliche Abfrage nicht ändern können. Siehe Beispiel J.

  • <table_hint> ::= { [ NOEXPAND ] { INDEX ( index_value [ ,...n ] ) | INDEX = ( index_value ) | FASTFIRSTROW | FORCESEEK [(index_value(index_column_name [,... ] )) ]| FORCESCAN | HOLDLOCK | NOLOCK | NOWAIT | PAGLOCK | READCOMMITTED | READCOMMITTEDLOCK | READPAST | READUNCOMMITTED | REPEATABLEREAD | ROWLOCK | SERIALIZABLE | TABLOCK | TABLOCKX | UPDLOCK | XLOCK }
    Der Tabellenhinweis, der auf die Tabelle oder die Sicht anzuwenden ist, die exposed_object_name als Abfragehinweis entspricht. Eine Beschreibung dieser Hinweise finden Sie unter Tabellenhinweise (Transact-SQL).

    Andere Tabellenhinweise als INDEX, FORCESCAN und FORCESEEK sind als Abfragehinweise nicht zulässig, es sei denn, die Abfrage enthält bereits eine WITH-Klausel, die einen Tabellenhinweis angibt. Weitere Informationen finden Sie in den Hinweisen.

    VorsichtshinweisVorsicht

    Bei Angabe von FORCESEEK mit Parametern wird die Anzahl von Plänen, die vom Optimierer berücksichtigt werden können, stärker eingeschränkt als bei Angabe von FORCESEEK ohne Parameter. Dies kann in mehreren Fällen zu dem Fehler führen, dass der Plan nicht generiert werden kann. In zukünftigen Versionen können möglicherweise mehr Pläne berücksichtigt werden.

Hinweise

Abfragehinweise wirken sich auf alle Operatoren in der Abfrage aus.

Abfragehinweise können nicht in einer INSERT-Anweisung angegeben werden, es sei denn, eine SELECT-Klausel wird innerhalb der Anweisung verwendet.

Abfragehinweise können nur in der Abfrage der obersten Ebene angegeben werden, nicht in Unterabfragen. Wenn ein Tabellenhinweis als Abfragehinweis angegeben ist, kann der Hinweis in der Abfrage der obersten Ebene oder in einer Unterabfrage angegeben werden. Der für exposed_object_name in der TABLE HINT-Klausel angegebene Wert muss jedoch genau dem verfügbar gemachten Namen in der Abfrage oder Unterabfrage entsprechen.

Falls UNION in der Hauptabfrage vorkommt, kann nur die letzte Abfrage, die eine UNION-Operation enthält, die OPTION-Klausel aufweisen. Abfragehinweise werden als Teil der OPTION-Klausel angegeben. Wenn mindestens ein Abfragehinweis dazu führt, dass der Abfrageoptimierer keinen gültigen Plan generiert, wird der Fehler 8622 ausgelöst.

Angeben von Tabellenhinweisen als Abfragehinweise

Es wird empfohlen, den INDEX- oder den FORCESEEK-Tabellenhinweis nur im Zusammenhang mit einer Planhinweisliste als Abfragehinweis zu verwenden. Planhinweislisten sind nützlich, wenn Sie die ursprüngliche Abfrage nicht ändern können, beispielsweise bei Anwendungen von Drittanbietern. Der in der Planhinweisliste angegebene Abfragehinweis wird vor dem Kompilieren und Optimieren zur Abfrage hinzugefügt. Verwenden Sie für Ad-hoc-Abfragen die TABLE HINT-Klausel nur dann, wenn Sie Planhinweislisten-Anweisungen testen. Es wird empfohlen, für alle anderen Ad-hoc-Abfragen diese Hinweise nur als Tabellenhinweise anzugeben.

Wenn die INDEX-, FORCESCAN- und FORCESEEK-Tabellenhinweise als Abfragehinweise angegeben werden, sind sie für die folgenden Objekte gültig:

  • Tabellen

  • Sichten

  • Indizierte Sichten

  • Allgemeine Tabellenausdrücke (Der Hinweis muss in der SELECT-Anweisung angegeben sein, mit deren Resultset der allgemeine Tabellenausdruck aufgefüllt wird.)

  • Dynamische Verwaltungssichten

  • Benannte Unterabfragen

Die INDEX-, FORCESCAN- und FORCESEEK-Tabellenhinweis können als Abfragehinweise für eine Abfrage angegeben werden, die nicht über vorhandene Tabellenhinweise verfügt, oder sie können verwendet werden, um vorhandene INDEX-, FORCESCAN- oder FORCESEEK-Hinweise in der Abfrage zu ersetzen. Andere Tabellenhinweise als INDEX, FORCESCAN und FORCESEEK sind als Abfragehinweise nicht zulässig, es sei denn, die Abfrage enthält bereits eine WITH-Klausel, die einen Tabellenhinweis angibt. In diesem Fall muss, um die Semantik der Abfrage beizubehalten, mithilfe von TABLE HINT in der OPTION-Klausel auch ein übereinstimmender Hinweis als Abfragehinweis angegeben werden. Wenn die Abfrage beispielsweise den Tabellenhinweis NOLOCK enthält, muss die OPTION-Klausel in dem @hints-Parameter der Planhinweisliste ebenfalls den NOLOCK-Hinweis enthalten. Siehe Beispiel K. Wenn ein anderer Tabellenhinweis als INDEX, FORCESCAN oder FORCESEEK mithilfe von TABLE HINT in der OPTION-Klausel ohne übereinstimmenden Abfragehinweis angegeben wurde (oder umgekehrt), wird der Fehler 8702 ausgelöst (als Hinweis darauf, dass die OPTION-Klausel bewirken kann, dass sich die Semantik der Abfrage ändert), und die Abfrage schlägt fehl. Weitere Informationen finden Sie unter Verwenden der INDEX- und FORCESEEK-Abfragehinweise in Planhinweislisten.

Beispiele

A. Verwenden von MERGE JOIN

Im folgenden Beispiel wird der JOIN-Vorgang in der Abfrage durch MERGE JOIN ausgeführt.

USE AdventureWorks2008R2;
GO
SELECT * 
FROM Sales.Customer AS c
INNER JOIN Sales.vStoreWithAddresses AS sa 
    ON c.CustomerID = sa.BusinessEntityID
WHERE TerritoryID = 5
OPTION (MERGE JOIN);
GO

B. Verwenden von OPTIMIZE FOR

Im folgenden Beispiel wird der Abfrageoptimierer angewiesen, den Wert 'Seattle' für die lokale Variable @city_name zu verwenden, und statistische Daten zu verwenden, um während der Abfrageoptimierung den Wert der lokalen Variablen @postal_code zu bestimmen.

USE AdventureWorks2008R2;
GO
DECLARE @city_name nvarchar(30);
DECLARE @postal_code nvarchar(15);
SET @city_name = 'Ascheim';
SET @postal_code = 86171;
SELECT * FROM Person.Address
WHERE City = @city_name AND PostalCode = @postal_code
OPTION ( OPTIMIZE FOR (@city_name = 'Seattle', @postal_code UNKNOWN) );
GO

C. Verwenden von MAXRECURSION

MAXRECURSION kann verwendet werden, um zu verhindern, dass ein fehlerhaft formatierter allgemeiner Tabellenausdruck in eine Endlosschleife gerät. Im folgenden Beispiel wird absichtlich eine Endlosschleife erstellt. Außerdem wird MAXRECURSION verwendet, um die Anzahl der Rekursionsebenen auf zwei zu beschränken.

USE AdventureWorks2008R2;
GO
--Creates an infinite loop
WITH cte (CustomerID, PersonID, StoreID) AS
(
    SELECT CustomerID, PersonID, StoreID
    FROM Sales.Customer
    WHERE PersonID IS NOT NULL
  UNION ALL
    SELECT cte.CustomerID, cte.PersonID, cte.StoreID
    FROM cte 
    JOIN  Sales.Customer AS e 
        ON cte.PersonID = e.CustomerID
)
--Uses MAXRECURSION to limit the recursive levels to 2
SELECT CustomerID, PersonID, StoreID
FROM cte
OPTION (MAXRECURSION 2);
GO

Nach dem Beheben des Codierungsfehlers ist MAXRECURSION nicht mehr erforderlich.

D. Verwenden von MERGE UNION

Im folgenden Beispiel wird der MERGE UNION-Abfragehinweis verwendet.

USE AdventureWorks2008R2;
GO
SELECT *
FROM HumanResources.Employee AS e1
UNION
SELECT *
FROM HumanResources.Employee AS e2
OPTION (MERGE UNION);
GO

E. Verwenden von HASH GROUP und FAST

Im folgenden Beispiel werden die Abfragehinweise HASH GROUP und FAST verwendet.

USE AdventureWorks2008R2;
GO
SELECT ProductID, OrderQty, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
WHERE UnitPrice < $5.00
GROUP BY ProductID, OrderQty
ORDER BY ProductID, OrderQty
OPTION (HASH GROUP, FAST 10);
GO

F. Verwenden von MAXDOP

Im folgenden Beispiel wird der MAXDOP-Abfragehinweis verwendet.

USE AdventureWorks2008R2 ;
GO
SELECT ProductID, OrderQty, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
WHERE UnitPrice < $5.00
GROUP BY ProductID, OrderQty
ORDER BY ProductID, OrderQty
OPTION (MAXDOP 2);
GO

G. Verwenden von INDEX

In den folgenden Beispielen wird der INDEX-Hinweis verwendet. Im ersten Beispiel wird ein einzelner Index angegeben. Im zweiten Beispiel werden mehrere Indizes für einen einzelnen Tabellenverweis angegeben. Da der INDEX-Hinweis auf eine Tabelle angewendet wird, die einen Alias verwendet, muss in beiden Beispielen in der TABLE HINT-Klausel auch der gleiche Alias wie der verfügbare Objektname angegeben werden.

USE AdventureWorks2008R2;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide1', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.JobTitle
              FROM HumanResources.Employee AS e 
              JOIN Person.Person AS c ON e.BusinessEntityID = c.BusinessEntityID
              WHERE e.OrganizationLevel = 2;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e, INDEX (IX_Employee_OrganizationLevel_OrganizationNode)))';
GO
EXEC sp_create_plan_guide 
    @name = N'Guide2', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.JobTitle
              FROM HumanResources.Employee AS e 
              JOIN Person.Person AS c ON e.BusinessEntityID = c.BusinessEntityID
              WHERE e.OrganizationLevel = 2;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e, INDEX(PK_Employee_BusinessEntityID, IX_Employee_OrganizationLevel_OrganizationNode)))';
GO

H. Verwenden von FORCESEEK

Im folgenden Beispiel wird der FORCESEEK-Tabellenhinweis verwendet. Da der INDEX-Hinweis auf eine Tabelle angewendet wird, die einen zweiteiligen Namen verwendet, muss in der TABLE HINT-Klausel auch der gleiche zweiteilige Name wie der verfügbare Objektname angegeben werden.

USE AdventureWorks2008R2;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide3', 
    @stmt = N'SELECT c.LastName, c.FirstName, HumanResources.Employee.JobTitle
              FROM HumanResources.Employee
              JOIN Person.Person AS c ON HumanResources.Employee.BusinessEntityID = c.BusinessEntityID
              WHERE HumanResources.Employee.OrganizationLevel = 3
              ORDER BY c.LastName, c.FirstName;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT( HumanResources.Employee, FORCESEEK))';
GO

I. Verwenden von mehreren Tabellenhinweisen

Im folgenden Beispiel wird der INDEX-Hinweis auf eine Tabelle angewendet, und der FORCESEEK-Hinweis wird auf eine andere Tabelle angewendet.

USE AdventureWorks2008R2;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide4', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.JobTitle
              FROM HumanResources.Employee AS e 
              JOIN Person.Person AS c ON e.BusinessEntityID = c.BusinessEntityID
              WHERE OrganizationLevel = 3;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, INDEX( IX_Employee_OrganizationLevel_OrganizationNode ) ) 
                       , TABLE HINT ( c, FORCESEEK) )';
GO

J. Verwenden von TABLE HINT zum Überschreiben eines vorhandenen Tabellenhinweises

Das folgende Beispiel zeigt, wie der TABLE HINT-Hinweis ohne Angabe eines Hinweises verwendet wird, um das Verhalten des INDEX-Tabellenhinweises zu überschreiben, der in der FROM-Klausel der Abfrage angegeben ist.

USE AdventureWorks2008R2;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide5', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.JobTitle
              FROM HumanResources.Employee AS e WITH (INDEX (IX_Employee_OrganizationLevel_OrganizationNode))
              JOIN Person.Person AS c ON e.BusinessEntityID = c.BusinessEntityID
              WHERE OrganizationLevel = 3;', 
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT(e))';
GO

K. Angeben von Tabellenhinweisen, die die Semantik beeinflussen

Das folgende Beispiel enthält in der Abfrage zwei Tabellenhinweise: den NOLOCK-Hinweis, der die Semantik beeinflusst, und den INDEX-Hinweis, der die Semantik nicht beeinflusst. Der NOLOCK-Hinweis wird in der OPTIONS-Klausel der Planhinweisliste angegeben, um die Semantik der Abfrage beizubehalten. Neben dem NOLOCK-Hinweis werden auch der INDEX-Hinweis und der FORCESEEK-Hinweis angegeben, die den die Semantik nicht beeinflussenden INDEX-Hinweis in der Abfrage ersetzen, wenn die Anweisung kompiliert und optimiert wird.

USE AdventureWorks2008R2;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide6', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.JobTitle
              FROM HumanResources.Employee AS e 
              JOIN Person.Person AS c ON e.BusinessEntityID = c.BusinessEntityID
              WHERE OrganizationLevel = 3;',
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, INDEX( IX_Employee_OrganizationLevel_OrganizationNode) , NOLOCK, FORCESEEK ))';
GO

Das folgende Beispiel zeigt eine alternative Methode, um die Semantik der Abfrage beizubehalten und zu ermöglichen, dass der Abfrageoptimierer einen anderen als den im Tabellenhinweis angegebenen Index verwendet. Dies erfolgt durch Angabe des NOLOCK-Hinweises in der OPTIONS-Klausel (da dieser die Semantik beeinflusst) und durch Angabe des TABLE HINT-Schlüsselworts nur mit einem Tabellenverweis und ohne INDEX-Hinweis.

USE AdventureWorks2008R2;
GO
EXEC sp_create_plan_guide 
    @name = N'Guide7', 
    @stmt = N'SELECT c.LastName, c.FirstName, e.JobTitle
              FROM HumanResources.Employee AS e 
              JOIN Person.Person AS c ON e.BusinessEntityID = c.BusinessEntityID
              WHERE OrganizationLevel = 2;',
    @type = N'SQL',
    @module_or_batch = NULL, 
    @params = NULL, 
    @hints = N'OPTION (TABLE HINT ( e, NOLOCK))';
GO