Condividi tramite


Hint per la query (Transact-SQL)

Gli hint per la query consentono di modificare il comportamento predefinito di Query Optimizer per la durata dell'istruzione di query. È possibile utilizzare gli hint di tabella per specificare un metodo di blocco nelle tabelle interessate, uno o più indici, un'operazione di elaborazione di query, quale un'analisi di tabella o una ricerca nell'indice, oppure altre opzioni. Gli hint per la query vengono applicati all'intera query.

Nota di attenzioneAttenzione

Poiché Query Optimizer di SQL Server in genere seleziona il piano di esecuzione migliore per una query, è consigliabile utilizzare hint solo se strettamente necessario e sempre da parte di sviluppatori e amministratori esperti di database.

Si applica a:

DELETE

INSERT

SELECT

UPDATE

MERGE

Icona di collegamento a un argomentoConvenzioni della sintassi Transact-SQL

Sintassi

        <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 
}

Argomenti

  • { HASH | ORDER } GROUP
    Specifica che nelle funzioni di aggregazione elencate nella clausola GROUP BY, DISTINCT o COMPUTE della query devono essere utilizzate operazioni di hashing o di ordinamento.

  • { MERGE | HASH | CONCAT } UNION
    Specifica che per tutte le operazioni UNION vengono eseguite operazioni di unione, hashing o concatenazione dei set UNION. Se viene specificato più di un hint UNION, Query Optimizer seleziona la strategia meno onerosa tra gli hint specificati.

  • { LOOP | MERGE | HASH } JOIN
    Specifica che tutte le operazioni JOIN vengono eseguite da LOOP JOIN, MERGE JOIN o HASH JOIN nell'intera query. Se vengono specificati più hint di join, Query Optimizer seleziona la strategia di join meno onerosa tra i join consentiti.

    Se nella stessa query un hint di join viene specificato nella clausola FROM anche per una particolare coppia di tabelle, tale hint risulta prioritario rispetto all'unione in join delle due tabelle. Gli hint per la query devono essere comunque rispettati. L'hint di join della coppia di tabelle pertanto consente di limitare solo la selezione dei metodi di join consentiti nell'hint per la query. Per ulteriori informazioni, vedere Hint di join (Transact-SQL).

  • FAST number_rows
    Specifica che la query è ottimizzata per il recupero rapido delle prime righe specificate in number_rows. Si tratta di un numero intero non negativo. Dopo la restituzione del primo numero di righe definito da number_rows, l'esecuzione della query continua e viene generato il set di risultati completo.

  • FORCE ORDER
    Specifica che l'ordine di join indicato dalla sintassi della query viene conservato durante l'ottimizzazione della query. L'utilizzo dell'hint FORCE ORDER non ha alcun effetto sulla possibile inversione dei ruoli in Query Optimizer. Per ulteriori informazioni, vedere Informazioni sugli hash join.

    In un'istruzione MERGE l'accesso alla tabella di origine viene eseguito prima della tabella di destinazione come ordine di join predefinito, a meno che non sia specificata la clausola WHEN SOURCE NOT MATCHED. Specificando FORCE ORDER viene conservato questo comportamento predefinito.

    Per ulteriori informazioni su come Query Optimizer di SQL Server applica l'hint FORCE ORDER quando una query include una vista, vedere Risoluzione delle viste.

  • MAXDOP number
    Prioritario rispetto all'opzione di configurazione max degree of parallelism della stored procedure sp_configure e Resource Governor per la query che specifica tale opzione. L'hint per la query MAXDOP può superare il valore configurato con sp_configure. Se MAXDOP supera il valore configurato con Resource Governor, il Motore di database utilizza il valore MAXDOP di Resource Governor descritto in ALTER WORKLOAD GROUP (Transact-SQL). Quando si utilizza l'hint per la query MAXDOP sono valide tutte le regole semantiche utilizzate con l'opzione di configurazione max degree of parallelism. Per ulteriori informazioni, vedere Opzione max degree of parallelism.

    Nota di attenzioneAttenzione

    Se MAXDOP è impostato su zero, il server sceglie il grado massimo di parallelismo.

  • OPTIMIZE FOR ( @variable_name { UNKNOWN | = literal_constant } [ , ...n ] )
    Imposta Query Optimizer in modo che utilizzi un valore specifico per una variabile locale quando la query viene compilata e ottimizzata. Il valore viene utilizzato durante l'ottimizzazione della query e non durante l'esecuzione di questa.

    • @variable_name
      Nome di una variabile locale utilizzata in una query alla quale è possibile assegnare un valore da utilizzare con l'hint per la query OPTIMIZE FOR.

    • UNKNOWN
      Specifica che Query Optimizer utilizza dati statistici anziché il valore iniziale per determinare il valore per una variabile locale durante l'ottimizzazione della query.

    • literal_constant
      Valore letterale costante da assegnare a @variable_name per l'utilizzo con l'hint per la query OPTIMIZE FOR. literal_constant viene utilizzato solo durante l'ottimizzazione della query e non come valore di @variable_name durante l'esecuzione della query. literal_constant può essere di un tipo di dati di sistema qualsiasi di SQL Server che sia possibile esprimere come costante letterale. Il tipo di dati di literal_constant deve supportare la conversione implicita nel tipo di dati a cui @variable_name fa riferimento nella query.

    OPTIMIZE FOR può annullare la funzionalità di rilevamento predefinita dei parametri di Query Optimizer oppure può essere utilizzato durante la creazione delle guide di piano. Per ulteriori informazioni, vedere Ricompilazione di stored procedure e Ottimizzazione delle query nelle applicazioni distribuite tramite le guide di piano.

  • OPTIMIZE FOR UNKNOWN
    Indica a Query Optimizer di utilizzare dati statistici anziché i valori iniziali per tutte le variabili locali quando la query viene compilata e ottimizzata, includendo parametri creati con parametrizzazione forzata. Per ulteriori informazioni sulla parametrizzazione forzata, vedere Parametrizzazione forzata.

    Se OPTIMIZE FOR @variable_name = literal_constant e OPTIMIZE FOR UNKNOWN sono utilizzati nello stesso hint per la query, Query Optimizer utilizzerà il valore literal_constant indicato per un valore specifico e UNKNOWN per i valori di variabile rimanenti. I valori vengono utilizzati durante l'ottimizzazione della query e non durante l'esecuzione di questa.

  • PARAMETERIZATION { SIMPLE | FORCED }
    Specifica le regole di parametrizzazione applicate da Query Optimizer di SQL Server alla query durante la compilazione di questa.

    Nota importanteImportante

    L'hint per la query PARAMETERIZATION può essere specificato solo all'interno di una guida di piano e non direttamente all'interno di una query.

    SIMPLE indica a Query Optimizer di tentare la parametrizzazione semplice. FORCED indica a Query Optimizer di tentare la parametrizzazione forzata. L'hint per la query PARAMETERIZATION viene utilizzato per sostituire l'impostazione corrente dell'opzione SET dell'hint di database PARAMETERIZATION all'interno di una guida di piano. Per ulteriori informazioni, vedere Definizione delle funzionalità di parametrizzazione delle query tramite guide di piano.

  • RECOMPILE
    Indica a Motore di database di SQL Server di eliminare il piano generato per la query dopo che questa è stata eseguita e forza Query Optimizer a ricompilare un piano di query alla successiva esecuzione della stessa query. Se RECOMPILE non viene specificato, i piani di query vengono inseriti nella cache e riutilizzati da Motore di database. Durante la compilazione dei piani di query, l'hint per la query RECOMPILE utilizza i valori correnti delle variabili locali incluse nella query e, se la query è contenuta in una stored procedure, i valori correnti vengono passati ai parametri.

    RECOMPILE rappresenta una valida alternativa alla creazione di una stored procedure che utilizza la clausola WITH RECOMPILE quando è necessario ricompilare solo un subset di query all'interno della stored procedure, anziché l'intera stored procedure. Per ulteriori informazioni, vedere Ricompilazione di stored procedure. RECOMPILE risulta utile anche durante la creazione delle guide di piano. Per ulteriori informazioni, vedere Ottimizzazione delle query nelle applicazioni distribuite tramite le guide di piano.

  • ROBUST PLAN
    Impone in Query Optimizer l'applicazione di un piano che funziona anche con dimensioni di riga massime, eventualmente a scapito delle prestazioni. Quando la query viene elaborata, è possibile che tabelle e operatori intermedi debbano archiviare ed elaborare righe con dimensioni maggiori rispetto a qualsiasi riga di input. Talvolta le righe possono essere talmente estese che l'operatore specificato non è in grado di elaborarle. In questi casi, Motore di database genera un errore durante l'esecuzione della query. Grazie alla clausola ROBUST PLAN, i piani di query in cui potrebbe verificarsi questo problema vengono ignorati da Query Optimizer.

    Se non è possibile implementare tale piano, viene restituito un errore anziché posticipare il rilevamento dell'errore fino all'esecuzione della query. Le righe possono includere colonne di lunghezza variabile. In Motore di database è consentito definire righe con dimensioni massime superiori alla capacità di elaborazione di Motore di database. In un'applicazione tuttavia vengono in genere archiviate righe le cui dimensioni effettive rientrano nei limiti della capacità di elaborazione di Motore di database. Se in Motore di database viene rilevata una riga di lunghezza eccessiva, viene restituito un errore di esecuzione.

  • KEEP PLAN
    Impone in Query Optimizer l'impostazione di una soglia di ricompilazione stimata meno restrittiva per una query. La soglia di ricompilazione stimata è il punto in corrispondenza del quale una query viene automaticamente ricompilata quando in una tabella è stato apportato il numero stabilito di modifiche a livello di colonne indicizzate mediante l'esecuzione delle istruzioni UPDATE, DELETE, MERGE o INSERT. Specificando KEEP PLAN è possibile assicurarsi che una query non venga ricompilata troppo frequentemente in caso di più aggiornamenti di una tabella.

  • KEEPFIXED PLAN
    Impedisce a Query Optimizer di ricompilare una query in seguito a modifiche alle statistiche. Se si specifica KEEPFIXED PLAN, una query viene ricompilata solo se lo schema delle tabelle sottostanti viene modificato oppure se in tali tabelle si esegue sp_recompile.

  • EXPAND VIEWS
    Specifica che le viste indicizzate vengono espanse e che in Query Optimizer non viene presa in considerazione alcuna vista indicizzata per la sostituzione di una parte della query. Una vista viene espansa quando nel testo della query il nome della vista viene sostituito dalla definizione della vista stessa.

    Con questo hint per la query viene praticamente disabilitato l'utilizzo diretto di viste indicizzate e di relativi indici nel piano di query.

    La vista indicizzata non viene espansa solo se nella sezione SELECT della query viene fatto riferimento diretto alla vista e se viene specificato l'hint WITH (NOEXPAND) o WITH (NOEXPAND, INDEX( index_value [ ,...n ] ) ). Per ulteriori informazioni sull'hint per la query WITH (NOEXPAND), vedere FROM.

    L'hint influisce solo sulle viste nella sezione SELECT delle istruzioni, comprese le sezioni delle istruzioni INSERT, UPDATE, MERGE e DELETE.

  • MAXRECURSION number
    Specifica il numero massimo di ricorsioni consentite per la query corrente. number è un numero intero non negativo compreso tra 0 e 32767. Se è specificato 0, non viene applicato alcun limite. Se questa opzione non viene specificata, il limite predefinito per il server è 100.

    Se durante l'esecuzione della query viene raggiunto il valore specificato o predefinito per il limite MAXRECURSION, la query viene terminata e viene restituito un errore.

    A causa di questo errore, verrà eseguito il rollback di tutti gli effetti dell'istruzione. Se l'istruzione è un'istruzione SELECT, è possibile che vengano restituiti risultati parziali oppure nessun risultato. È possibile che eventuali risultati parziali non includano tutte le righe nei livelli di ricorsione che superano il livello di ricorsione massimo specificato.

    Per ulteriori informazioni, vedere WITH common_table_expression (Transact-SQL).

  • USE PLAN N**'xml_plan'**
    Impone in Query Optimizer l'utilizzo di un piano di query esistente per una query specificata da 'xml_plan'. Per ulteriori informazioni, vedere Definizione dei piani di query tramite l'utilizzo forzato. USE PLAN non può essere specificato nelle istruzioni INSERT, UPDATE, MERGE o DELETE.

  • TABLE HINT (exposed_object_name [ , <table_hint> [ [, ]...n ] ] )
    Applica l'hint di tabella specificato alla tabella o alla vista che corrisponde a exposed_object_name. È consigliabile utilizzare un hint di tabella come hint per la query solo nel contesto di una guida di piano.

    exposed_object_name può essere uno dei seguenti riferimenti:

    • Quando viene utilizzato un alias per la tabella o la vista nella clausola FROM della query, exposed_object_name è l'alias.

    • Quando non viene utilizzato un alias, exposed_object_name è la corrispondenza esatta della tabella o della vista cui si fa riferimento nella clausola FROM. Se, ad esempio, si fa riferimento alla tabella o alla vista utilizzando un nome in due parti, exposed_object_name è lo stesso nome in due parti.

    Quando viene specificato exposed_object_name senza specificare anche un hint di tabella, qualsiasi indice specificato nella query come parte di un hint di tabella per l'oggetto viene ignorato e l'utilizzo di indici è determinato da Query Optimizer. È possibile utilizzare questa tecnica per eliminare l'effetto di un hint di tabella INDEX quando non è possibile modificare la query originale. Vedere l'esempio 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 }
    Hint di tabella da applicare alla tabella o alla vista corrispondente a exposed_object_name come hint per la query. Per una descrizione di questi hint, vedere Hint di tabella (Transact-SQL).

    Gli hint di tabella diversi da INDEX, FORCESCAN e FORCESEEK non sono consentiti come hint per la query, a meno che la query non disponga già di una clausola WITH che specifica l'hint di tabella. Per ulteriori informazioni, vedere Osservazioni.

    Nota di attenzioneAttenzione

    Se si specifica FORCESEEK con parametri, il numero di piani che possono essere considerati da Query Optimizer viene limitato più di quanto avvenga se si specifica FORCESEEK senza parametri. In questo caso potrebbe venire generato un errore "Impossibile generare il piano" con maggiore frequenza. In una versione futura, le modifiche interne a Query Optimizer potrebbero consentire di prendere in considerazione più piani.

Osservazioni

Gli hint per la query influiscono su tutti gli operatori della query.

Gli hint per la query non possono essere specificati in un'istruzione INSERT, eccetto quando una clausola SELECT viene utilizzata all'interno dell'istruzione.

È possibile specificare gli hint per la query solo nella query di livello principale e non nelle sottoquery. Quando un hint di tabella viene specificato come hint per la query, l'hint può essere specificato nella query di livello superiore o in una sottoquery, tuttavia il valore specificato per exposed_object_name nella clausola TABLE HINT deve corrispondere esattamente al nome esposto nella query o nella sottoquery.

Se la query principale include l'operatore UNION, la clausola OPTION può essere specificata solo nell'ultima query che prevede un'operazione di tipo UNION. Gli hint per la query vengono specificati come parte della clausola OPTION. Se uno o più hint per la query impediscono a Query Optimizer di generare un piano valido, viene generato l'errore 8622.

Specifica di hint di tabella come hint per la query

È consigliabile utilizzare l'hint di tabella INDEX o FORCESEEK come hint per la query solo nel contesto di una guida di piano. Le guide di piano sono utili quando non è possibile modificare la query originale, ad esempio perché si tratta di un'applicazione di terze parti. L'hint per la query specificato nella guida di piano viene aggiunto alla query prima della compilazione e dell'ottimizzazione. Per le query ad hoc, utilizzare la clausola TABLE HINT solo quando si testano istruzioni della guida di piano. Per tutte le altre query ad hoc, è consigliabile specificare tali hint solo come hint di tabella.

Se specificati come hint per la query, gli hint di tabella INDEX, FORCESCAN e FORCESEEK sono validi per gli oggetti seguenti:

  • Tabelle

  • Viste

  • Viste indicizzate

  • Espressioni di tabella comuni. L'hint deve essere specificato nell'istruzione SELECT il cui set di risultati popola l'espressione di tabella comune.

  • DMV

  • Sottoquery denominate

Gli hint di tabella INDEX, FORCESCAN e FORCESEEK possono essere specificati come hint per una query senza hint di tabella esistenti oppure possono essere utilizzati per sostituire uno o più hint INDEX, FORCESCAN o FORCESEEK esistenti nella query. Gli hint di tabella diversi da INDEX, FORCESCAN e FORCESEEK non sono consentiti come hint per la query, a meno che la query non disponga già di una clausola WITH che specifica l'hint di tabella. In questo caso è necessario specificare inoltre un hint corrispondente come un hint per la query utilizzando TABLE HINT nella clausola OPTION per mantenere la semantica della query. Ad esempio, se la query contiene l'hint di tabella NOLOCK, la clausola OPTION nel parametro @hints della guida di piano deve contenere anch'essa l'hint NOLOCK. Vedere l'esempio K. Quando un hint di tabella diverso da INDEX, FORCESCAN o FORCESEEK viene specificato utilizzando TABLE HINT nella clausola OPTION senza un hint per la query corrispondente, o viceversa, viene generato l'errore 8702, che indica che la clausola OPTION può comportare la modifica della semantica della query, e la query ha esito negativo. Per ulteriori informazioni, vedere Utilizzo degli hint per le query INDEX e FORCESEEK nelle guide di piano.

Esempi

A. Utilizzo di MERGE JOIN

Nell'esempio seguente viene specificato che l'operazione JOIN nella query viene eseguita da MERGE JOIN.

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. Utilizzo di OPTIMIZE FOR

Nell'esempio seguente viene indicato a Query Optimizer di utilizzare il valore 'Seattle' per la variabile locale @city_name e di utilizzare dati statistici per determinare il valore per la variabile locale @postal_code durante l'ottimizzazione della query.

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. Utilizzo di MAXRECURSION

È possibile utilizzare MAXRECURSION per evitare che un'espressione di tabella comune (CTE) ricorsiva non corretta provochi un ciclo infinito. Nell'esempio seguente viene creato intenzionalmente un ciclo infinito e viene utilizzato l'hint MAXRECURSION per limitare a due il numero di livelli di ricorsione.

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

Dopo la correzione dell'errore del codice, l'hint MAXRECURSION non è più necessario.

D. Utilizzo di MERGE UNION

Nell'esempio seguente viene utilizzato l'hint per la query MERGE UNION.

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

E. Utilizzo di HASH GROUP e FAST

Nell'esempio seguente vengono utilizzati gli hint per la query HASH GROUP e FAST.

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. Utilizzo di MAXDOP

Nell'esempio seguente viene utilizzato l'hint per la query MAXDOP.

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. Utilizzo di INDEX

Nell'esempio seguente viene utilizzato l'hint INDEX. Nel primo esempio viene specificato un singolo indice. Nel secondo esempio vengono specificati più indici per un singolo riferimento alla tabella. In entrambi gli esempi, dal momento che l'hint INDEX è applicato a una tabella che utilizza un alias, anche la clausola TABLE HINT deve specificare lo stesso alias del nome dell'oggetto esposto.

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. Utilizzo di FORCESEEK

Nell'esempio seguente viene utilizzato l'hint di tabella FORCESEEK. Dal momento che l'hint INDEX è applicato a una tabella che utilizza un nome in due parti, anche la clausola TABLE HINT deve specificare lo stesso nome in due parti del nome dell'oggetto esposto.

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. Utilizzo di più hint di tabella

Nell'esempio seguente vengono applicati l'hint INDEX a una tabella e l'hint FORCESEEK a un'altra.

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. Utilizzo di TABLE HINT per eseguire l'override di un hint di tabella esistente

Nell'esempio seguente viene illustrato come utilizzare l'hint TABLE HINT senza specificare un hint per eseguire l'override del comportamento dell'hint di tabella INDEX specificato nella clausola FROM della query.

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. Specifica di hint di tabella che influiscono sulla semantica

Nell'esempio seguente sono contenuti due hint di tabella nella query: NOLOCK, che influisce sulla semantica, e INDEX, che non influisce sulla semantica. Per mantenere la semantica della query l’hint NOLOCK viene specificato nella clausola OPTIONS della guida di piano. Oltre all'hint NOLOCK, vengono specificati gli hint INDEX e FORCESEEK che sostituiscono l'hint INDEX che non influisce sulla semantica nella query quando l'istruzione viene compilata e ottimizzata.

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

Nell'esempio seguente viene illustrato un metodo alternativo per mantenere la semantica della query e consentire a Query Optimizer di scegliere un indice diverso da quello specificato nell'hint di tabella. A tale scopo occorre specificare l'hint NOLOCK nella clausola OPTIONS (poiché influisce sulla semantica) e la parola chiave TABLE HINT con solo un riferimento alla tabella e nessun hint INDEX.

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