Hint di tabella (Transact-SQL)

Gli hint di tabella consentono di modificare il comportamento predefinito di Query Optimizer per la durata dell'istruzione DML (Data Manipulation Language) specificando un metodo di blocco, uno o più indici, un'operazione di elaborazione di query, quale un'analisi di tabella (Table Scan) o una ricerca nell'indice (Index Seek), oppure altre opzioni. Gli hint di tabella sono specificati nella clausola FROM dell'istruzione DML e influiscono solo sulla tabella o sulla vista a cui viene fatto riferimento nella clausola.

Nota di attenzioneAttenzione

Poiché Query Optimizer di SQL Server consente in genere di selezionare il piano di esecuzione migliore per una query, gli hint devono essere utilizzati solo se strettamente necessario da sviluppatori e amministratori di database esperti.

Si applica a:

DELETE

INSERT

SELECT

UPDATE

MERGE

Icona di collegamento a un argomentoConvenzioni della sintassi Transact-SQL

Sintassi

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

<table_hint_limited> ::=
{
    KEEPIDENTITY 
  | KEEPDEFAULTS 
  | FASTFIRSTROW 
  | HOLDLOCK 
  | IGNORE_CONSTRAINTS 
  | IGNORE_TRIGGERS 
  | NOLOCK 
  | NOWAIT
  | PAGLOCK 
  | READCOMMITTED 
  | READCOMMITTEDLOCK 
  | READPAST 
  | REPEATABLEREAD 
  | ROWLOCK 
  | SERIALIZABLE 
  | TABLOCK 
  | TABLOCKX 
  | UPDLOCK 
  | XLOCK 
} 

Argomenti

  • WITH ( <table_hint> ) [ [ , ]...n ]
    Con alcune eccezioni, gli hint di tabella sono supportati solo se vengono specificati con la parola chiave WITH. Le parentesi sono obbligatorie.

    Nota importanteImportante

    L'omissione della parola chiave WITH è una caratteristica deprecata e sarà rimossa a partire da una versione futura di Microsoft SQL Server. Specificare sempre WITH in un nuovo progetto di sviluppo e modificare le applicazioni che attualmente prevedono l'omissione di questa parola chiave.

    L'utilizzo di spazi anziché di virgole per separare gli hint è una caratteristica deprecata e sarà rimossa a partire da una versione futura di Microsoft SQL Server. Specificare sempre le virgole in un nuovo progetto di sviluppo e modificare le applicazioni che attualmente ne prevedono l'omissione.

    Gli hint di tabella seguenti sono supportati sia con, sia senza la parola chiave WITH: NOLOCK, READUNCOMMITTED, UPDLOCK, REPEATABLEREAD, SERIALIZABLE, READCOMMITTED, FASTFIRSTROW, TABLOCK, TABLOCKX, PAGLOCK, ROWLOCK, NOWAIT, READPAST, XLOCK e NOEXPAND. Se vengono specificati senza la parola chiave WITH, questi hint devono essere specificati da soli, ad esempio FROM t WITH (TABLOCK). Se l'hint viene specificato con un'altra opzione, è necessario utilizzare la parola chiave WITH, ad esempio FROM t WITH (TABLOCK, INDEX(myindex)).

    Queste restrizioni sono valide quando gli hint vengono utilizzati in query eseguite su database con livello di compatibilità maggiore o uguale a 90.

  • NOEXPAND
    Specifica che qualsiasi vista indicizzata non verrà espansa per accedere alle tabelle sottostanti quando Query Optimizer elabora la query. In Query Optimizer la vista viene gestita come una tabella con indici cluster. L'hint NOEXPAND è applicabile solo alle viste indicizzate. Per ulteriori informazioni, vedere Osservazioni.

  • INDEX (index_value [,... n ] ) | INDEX = (index_value)
    La sintassi INDEX(index_value) specifica il nome o l'ID di uno o più indici che verranno utilizzati in Query Optimizer durante l'elaborazione dell'istruzione. La sintassi alternativa INDEX = (index_value) consente l'utilizzo di un singolo valore di indice.

    Se esiste un indice cluster, INDEX(0) forza un'analisi degli indici cluster, mentre INDEX(1) forza un'analisi o una ricerca negli indici cluster. Se non esiste alcun indice cluster, INDEX(0) forza un'analisi di tabella, mentre INDEX(1) viene interpretato come errore.

    Se in un unico elenco di hint vengono utilizzati più indici, eventuali duplicati vengono ignorati, mentre gli altri indici vengono utilizzati per recuperare le righe della tabella. L'ordine degli indici nell'hint è significativo. Un hint per più indici impone inoltre il collegamento degli indici tramite operatore AND e Query Optimizer applica il numero massimo di condizioni possibili a ogni indice a cui viene effettuato l'accesso. Se la raccolta di indici con hint non include tutte le colonne a cui la query fa riferimento, viene eseguita un'operazione di recupero delle colonne rimanenti dopo che tutte le colonne indicizzate sono state recuperate dal Motore di database di SQL Server.

    Nota

    Se in una tabella dei fatti in un join a stella viene utilizzato un hint per l'indice che fa riferimento a più indici, l'hint per l'indice viene ignorato e verrà restituito un messaggio di avviso. Non è inoltre consentito il collegamento degli indici tramite OR per una tabella per la quale è stato specificato un hint per l'indice.

    Per l'hint di tabella può essere specificato un numero massimo di 250 indici non cluster.

  • KEEPIDENTITY
    Applicabile solo in un'istruzione INSERT se viene utilizzata l'opzione BULK con OPENROWSET.

    Specifica che i valori Identity presenti nel file di dati importato devono essere utilizzati per la colonna Identity. Se KEEPIDENTITY viene omesso, i valori Identity per questa colonna vengono verificati ma non importati e Query Optimizer assegna automaticamente valori univoci in base ai valori di inizializzazione e di incremento specificati in fase di creazione della tabella.

    Nota importanteImportante

    Se il file di dati non contiene valori per la colonna Identity nella tabella o nella vista, tale colonna deve essere ignorata, a meno che non sia l'ultima colonna della tabella. Per ulteriori informazioni, vedere Utilizzo di un file di formato per escludere un campo di dati. Se una colonna Identity viene ignorata correttamente, Query Optimizer assegna automaticamente valori univoci per la colonna Identity nelle righe importate della tabella.

    Per un esempio di utilizzo di questo hint in un'istruzione INSERT ... SELECT * FROM OPENROWSET(BULK...), vedere Mantenimento dei valori Identity durante l'importazione bulk dei dati.

    Per ulteriori informazioni sul controllo del valore Identity per una tabella, vedere DBCC CHECKIDENT (Transact-SQL).

  • KEEPDEFAULTS
    Applicabile solo in un'istruzione INSERT se viene utilizzata l'opzione BULK con OPENROWSET.

    Specifica l'inserimento di un valore predefinito per la colonna della tabella, se disponibile, al posto del valore NULL quando nel record di dati non è presente un valore per la colonna.

    Per un esempio di utilizzo di questo hint in un'istruzione INSERT ... SELECT <columns> FROM OPENROWSET(BULK...), vedere Mantenimento dei valori Null o utilizzo dei valori predefiniti durante un'importazione bulk.

  • FASTFIRSTROW
    Equivale a OPTION (FAST 1). Per ulteriori informazioni, vedere Hint per la query (Transact-SQL).

    Nota importanteImportante

    Questa caratteristica verrà rimossa a partire dalla prossima versione di Microsoft SQL Server. Non utilizzare questa caratteristica in un nuovo progetto di sviluppo e modificare non appena possibile le applicazioni in cui è attualmente implementata.

  • FORCESEEK [ **(index_value(**index_column_name [ ,... n ] )) ]
    Specifica che Query Optimizer deve utilizzare solo un'operazione di ricerca nell'indice come percorso di accesso ai dati della tabella o della vista. A partire da SQL Server 2008 R2 SP1, è inoltre possibile specificare i parametri di indice. L'utilizzo di FORCESEEK con i parametri di indice è analogo all'utilizzo di FORCESEEK con un hint INDEX. È tuttavia possibile ottenere un maggior controllo sul percorso di accesso utilizzato da Query Optimizer specificando sia l'indice su cui eseguire la ricerca, sia le colonne dell'indice da prendere in considerazione durante l'operazione di ricerca.

    • index_value
      Nome o valore ID dell'indice. Non è possibile specificare un ID di indice pari a 0 (heap). Per restituire l'ID o il nome dell'indice, eseguire una query sulla vista del catalogo sys.indexes.

    • index_column_name
      Nome della colonna dell'indice da includere nell'operazione di ricerca. In Query Optimizer vengono considerate solo le operazioni di ricerca nell'indice specificato, utilizzando almeno le colonne dell'indice specificate. Se necessario, possono essere considerate ulteriori colonne. A esempio, se si specifica un indice non cluster, è possibile che in Query Optimizer vengano utilizzate le colonne chiave dell'indice cluster oltre alle colonne specificate.

    È possibile specificare l'hint FORCESEEK nei modi riportati di seguito.

    Sintassi

    Esempio

    Descrizione

    Senza un indice o un hint INDEX

    FROM dbo.MyTable WITH (FORCESEEK)

    In Query Optimizer vengono considerate solo le operazioni di ricerca nell'indice per accedere alla tabella o alla vista in un indice rilevante.

    In combinazione con un hint INDEX

    FROM dbo.MyTable WITH (FORCESEEK, INDEX (MyIndex))

    In Query Optimizer vengono considerate solo le operazioni di ricerca nell'indice per accedere alla tabella o alla vista nell'indice specificato.

    Con parametri mediante la specifica di un indice e colonne di indice

    FROM dbo.MyTable WITH (FORCESEEK (MyIndex (col1, col2, col3)))

    In Query Optimizer vengono considerate solo le operazioni di ricerca nell'indice per accedere alla tabella o alla vista nell'indice specificato, utilizzando almeno le colonne dell'indice specificate.

    Quando si utilizza l'hint FORCESEEK (con o senza parametri di indice), è opportuno considerare le indicazioni generali riportate di seguito.

    • L'hint può essere specificato come hint di tabella o hint per la query. Per ulteriori informazioni sugli hint per la query, vedere Hint per la query (Transact-SQL).

    • Per applicare FORCESEEK a una vista indicizzata, è necessario specificare anche l'hint NOEXPAND.

    • L'hint può essere applicato al massimo una volta per ogni tabella o vista.

    • Non è possibile specificare l'hint per un'origine dei dati remota. Se FORCESEEK viene specificato con un hint per l'indice, viene restituito l'errore 7377. L'errore 8180 viene invece restituito se FORCESEEK viene utilizzato senza un hint per l'indice.

    • Se con FORCESEEK non viene trovato alcun piano, viene restituito l'errore 8622.

    Quando si specifica FORCESEEK con parametri di indice, è opportuno considerare le indicazioni generali e le restrizioni riportate di seguito.

    • Non è possibile specificare questo hint in combinazione con un hint INDEX o un altro hint FORCESEEK.

    • È necessario specificare almeno una colonna, la quale deve corrispondere alla colonna chiave iniziale.

    • Sebbene sia possibile specificare ulteriori colonne di indice, non è possibile ignorare le colonne chiave. Ad esempio, se l'indice specificato contiene le colonne chiave a, b e c, la sintassi valida include FORCESEEK (MyIndex (a)) e FORCESEEK (MyIndex (a, b), mentre la sintassi non valida include FORCESEEK (MyIndex (c)) e FORCESEEK (MyIndex (a, c).

    • L'ordine dei nomi di colonna specificato nell'hint deve corrispondere a quello delle colonne nell'indice a cui viene fatto riferimento.

    • Non è possibile specificare le colonne non incluse nella definizione della chiave dell'indice. In un indice non cluster è ad esempio possibile specificare solo le colonne chiave dell'indice definite. Le colonne chiave cluster incluse automaticamente nell'indice non possono essere specificate, sebbene possano essere utilizzate da Query Optimizer.

    • La modifica della definizione dell'indice, ad esempio l'aggiunta o la rimozione di colonne, può richiedere la modifica delle query che fanno riferimento a tale indice.

    • L'hint impedisce a Query Optimizer di prendere in considerazione gli eventuali indici spaziali o XML nella tabella.

    • Non è possibile specificare l'hint in combinazione con l'hint FORCESCAN.

    • Per gli indici partizionati, la colonna di partizionamento aggiunta in modo implicito da SQL Server non può essere specificata nell'hint FORCESEEK. Per ulteriori informazioni, vedere Linee guida specifiche per gli indici partizionati.

    Nota di attenzioneAttenzione

    Se si specifica FORCESEEK con parametri di indice, 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. Per ulteriori informazioni, vedere Utilizzo dell'hint di tabella FORCESEEK.

  • FORCESCAN
    Introdotto in SQL Server 2008 R2 SP1, questo hint indica che in Query Optimizer deve essere utilizzata solo un'operazione di analisi dell'indice come percorso di accesso alla tabella o alla vista a cui viene fatto riferimento. L'hint FORCESCAN può essere utile per le query in cui, a causa della valutazione errata (in difetto) del numero di righe interessate da parte di Query Optimizer, viene eseguita un'operazione di ricerca anziché di analisi. In questo caso, la quantità di memoria concessa per l'operazione è troppo ridotta, con conseguente calo delle prestazioni di query.

    È possibile specificare FORCESCAN con o senza un hint INDEX. Quando viene specificato in combinazione con un hint per l'indice (INDEX = index_name, FORCESCAN), in Query Optimizer vengono presi in considerazione solo i percorsi di accesso all'analisi nell'indice specificato per accedere alla tabella a cui viene fatto riferimento. FORCESCAN può essere specificato con l'hint per l'indice INDEX(0) per imporre un'operazione di analisi delle tabelle nella tabella di base.

    Per le tabelle e gli indici partizionati, FORCESCAN viene applicato dopo l'eliminazione delle partizioni tramite la valutazione del predicato della query. L'analisi viene pertanto applicata solo alle partizioni rimanenti, anziché all'intera tabella.

    Per l'hint FORCESCAN sono applicate le restrizioni indicate di seguito.

    • Non è possibile specificare l'hint per una tabella che rappresenta la destinazione di un'istruzione INSERT, UPDATE o DELETE.

    • Non è possibile utilizzare l'hint con più hint per l'indice.

    • L'hint impedisce a Query Optimizer di prendere in considerazione gli eventuali indici spaziali o XML nella tabella.

    • Non è possibile specificare l'hint per un'origine dei dati remota.

    • Non è possibile specificare l'hint in combinazione con l'hint FORCESEEK.

  • HOLDLOCK
    Equivale a SERIALIZABLE. Per ulteriori informazioni, vedere la sezione SERIALIZABLE di seguito in questo argomento. HOLDLOCK si applica solo alla tabella o alla vista per la quale è stato specificato e solo per la durata della transazione definita dall'istruzione in cui è utilizzato. Non è possibile utilizzare l'argomento HOLDLOCK in un'istruzione SELECT che include l'opzione FOR BROWSE.

  • IGNORE_CONSTRAINTS
    Applicabile solo in un'istruzione INSERT se viene utilizzata l'opzione BULK con OPENROWSET.

    Specifica che qualsiasi vincolo sulla tabella verrà ignorato dall'operazione di importazione bulk. Per impostazione predefinita, l'istruzione INSERT controlla i vincoli CHECK e FOREIGN KEY. Se si specifica IGNORE_CONSTRAINTS per un'operazione di importazione bulk, l'istruzione INSERT deve ignorare tali vincoli in una tabella di destinazione. Si noti che non è possibile disabilitare i vincoli UNIQUE, PRIMARY KEY o NOT NULL.

    Se i dati di input contengono righe che violano i vincoli, potrebbe essere necessario disabilitare i vincoli CHECK e FOREIGN KEY. Disabilitando i vincoli CHECK e FOREIGN KEY, è possibile importare i dati e quindi utilizzare istruzioni Transact-SQL per pulire i dati.

    Quando i vincoli CHECK e FOREIGN KEY vengono ignorati, ogni vincolo ignorato nella tabella viene tuttavia contrassegnato come is_not_trusted nella vista del catalogo sys.check_constraints o sys.foreign_keys dopo l'operazione. A un certo punto sarà necessario controllare i vincoli nell'intera tabella. Se la tabella non era vuota prima dell'operazione di importazione bulk, l'impegno per la riconvalida dei vincoli può essere superiore all'impegno per l'applicazione dei vincoli CHECK e FOREIGN KEY ai dati incrementali.

  • IGNORE_TRIGGERS
    Applicabile solo in un'istruzione INSERT se viene utilizzata l'opzione BULK con OPENROWSET.

    Specifica che qualsiasi trigger definito sulla tabella verrà ignorato dall'operazione di importazione bulk. Per impostazione predefinita, l'istruzione INSERT applica i trigger.

    Utilizzare l'argomento IGNORE_TRIGGERS solo se l'applicazione non dipende dai trigger e l'ottimizzazione delle prestazioni è un fattore importante.

  • NOLOCK
    Equivale a READUNCOMMITTED. Per ulteriori informazioni, vedere la sezione READUNCOMMITTED di seguito in questo argomento.

    Nota

    Per le istruzioni UPDATE e DELETE: Questa caratteristica verrà rimossa a partire da una delle prossime versioni di Microsoft SQL Server. Evitare di utilizzare questa caratteristica in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata.

  • NOWAIT
    Imposta Motore di database in modo che venga restituito un messaggio non appena viene rilevato un blocco nella tabella. NOWAIT equivale a specificare SET LOCK_TIMEOUT 0 per una tabella specifica.

  • PAGLOCK
    Acquisisce i blocchi di pagina dove in genere vengono acquisiti i singoli blocchi su righe o chiavi oppure dove in genere viene acquisito un singolo blocco a livello di tabella. Per impostazione predefinita, viene utilizzata la modalità di blocco appropriata per l'operazione specifica. Se viene specificato nelle transazioni operative al livello di isolamento SNAPSHOT, i blocchi di pagina vengono acquisiti solo se PAGLOCK è combinato con altri hint di tabella che richiedono i blocchi, ad esempio UPDLOCK e HOLDLOCK.

  • READCOMMITTED
    Specifica la conformità delle operazioni di lettura con le regole relative al livello di isolamento READ COMMITTED mediante l'utilizzo dei blocchi o del controllo delle versioni delle righe. Se l'opzione di database READ_COMMITTED_SNAPSHOT è impostata su OFF, Motore di database acquisisce blocchi condivisi durante la lettura dei dati e rilascia tali blocchi al completamento dell'operazione di lettura. Se l'opzione di database READ_COMMITTED_SNAPSHOT è impostata su ON, Motore di database non acquisisce i blocchi e utilizza il controllo delle versioni delle righe. Per ulteriori informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

    Nota

    Per le istruzioni UPDATE e DELETE: Questa caratteristica verrà rimossa a partire da una delle prossime versioni di Microsoft SQL Server. Evitare di utilizzare questa caratteristica in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata.

  • READCOMMITTEDLOCK
    Specifica la conformità delle operazioni di lettura con le regole relative al livello di isolamento READ COMMITTED mediante l'utilizzo dei blocchi. Il Motore di database acquisisce i blocchi condivisi durante la lettura dei dati e li rilascia al completamento dell'operazione di lettura, indipendentemente dall'impostazione dell'opzione di database READ_COMMITTED_SNAPSHOT. Per ulteriori informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL (Transact-SQL). Non è possibile specificare questo hint in una tabella di destinazione di un'istruzione INSERT. Viene restituito l'errore 4140.

  • READPAST
    Specifica che le righe bloccate da altre transazioni non devono essere lette dal Motore di database. Se si specifica READPAST, i blocchi a livello di riga vengono ignorati. Il Motore di database ignora pertanto le righe anziché bloccare la transazione corrente finché i blocchi non vengono rilasciati. Si supponga, ad esempio, che la tabella T1 contenga una sola colonna integer con i valori 1, 2, 3, 4, 5. Se la transazione A modifica il valore da 3 a 8 senza eseguire il commit, l'istruzione SELECT * FROM T1 (READPAST) restituisce i valori 1, 2, 4, 5. READPAST è utilizzato principalmente per ridurre la contesa dei blocchi durante l'implementazione di una coda di elaborazione che utilizza una tabella SQL Server. Un agente di lettura coda che utilizza l'argomento READPAST ignora le voci della coda bloccate da altre transazioni e passa alla successiva voce disponibile senza attendere il rilascio dei blocchi da parte delle altre transazioni.

    È possibile specificare l'argomento READPAST per qualsiasi tabella a cui viene fatto riferimento in un'istruzione UPDATE o DELETE e per qualsiasi tabella a cui viene fatto riferimento in una clausola FROM. Se specificato in un'istruzione UPDATE, l'argomento READPAST viene applicato solo durante la lettura dei dati per l'identificazione dei record da aggiornare, indipendentemente dalla posizione in cui è stato specificato all'interno dell'istruzione. Non è possibile specificare l'argomento READPAST per le tabelle nella clausola INTO di un'istruzione INSERT. Le operazioni di lettura che utilizzano l'argomento READPAST non applicano blocchi. È possibile che le operazioni di aggiornamento o eliminazione che utilizzano l'argomento READPAST applichino blocchi durante la lettura delle chiavi esterne o delle viste indicizzate oppure durante la modifica degli indici secondari.

    L'argomento READPAST può essere specificato solo nelle transazioni operative ai livelli di isolamento READ COMMITTED o REPEATABLE READ. Se viene specificato nelle transazioni operative al livello di isolamento SNAPSHOT, è necessario combinare READPAST con altri hint di tabella che richiedono i blocchi, ad esempio UPDLOCK e HOLDLOCK.

    L'hint di tabella READPAST non può essere specificato quando l'opzione di database READ_COMMITTED_SNAPSHOT è impostata su ON e una delle condizioni seguenti è vera.

    • Il livello di isolamento delle transazioni della sessione è READ COMMITTED.

    • L'hint di tabella READCOMMITTED viene specificato anche nella query.

    Per specificare l'hint READPAST in questi casi, rimuovere l'hint di tabella READCOMMITTED, se presente, e includere l'hint di tabella READCOMMITTEDLOCK nella query.

  • READUNCOMMITTED
    Indica che le letture dirty sono consentite. Non viene acquisito alcun blocco condiviso per impedire alle altre transazioni di modificare i dati letti dalla transazione corrente. I blocchi esclusivi impostati dalle altre transazioni non impediscono alla transazione corrente di leggere i dati bloccati. Le letture dirty possono provocare un livello più alto di concorrenza a discapito della lettura delle modifiche dei dati per le quali le altre transazioni eseguiranno il rollback. Di conseguenza, è possibile che vengano generati errori per la transazione, che vengano forniti agli utenti dati di cui non è mai stato eseguito il commit oppure che gli utenti visualizzino i record due volte o che non li visualizzino affatto. Per ulteriori informazioni su letture dirty, letture non ripetibili e letture fantasma, vedere Effetti della concorrenza.

    Gli hint READUNCOMMITTED e NOLOCK sono applicabili soltanto a blocchi a livello di dati. Tutte le query, incluse quelle con hint READUNCOMMITTED e NOLOCK, acquisiscono blocchi di stabilità dello schema (Sch-S) durante la compilazione e l'esecuzione. Per questo motivo, le query vengono bloccate quando una transazione simultanea mantiene attivo un blocco di modifica dello schema sulla tabella. Un'operazione DDL (Data Definition Language), ad esempio, acquisisce un blocco Sch-M prima di modificare le informazioni sullo schema della tabella. Tutte le query simultanee che tentano di acquisire un blocco Sch-S, incluse quelle in esecuzione con hint READUNCOMMITTED o NOLOCK, vengono bloccate. Una query con blocco Sch-S blocca invece le transazioni simultanee che tentano di acquisire un blocco Sch-M. Per ulteriori informazioni sul comportamento di blocco, vedere Compatibilità tra blocchi (Motore di database).

    Non è possibile specificare READUNCOMMITTED e NOLOCK per le tabelle modificate da operazioni di inserimento, aggiornamento o eliminazione. Query Optimizer di SQL Server ignora gli hint READUNCOMMITTED e NOLOCK della clausola FROM applicata alla tabella di destinazione di un'istruzione UPDATE o DELETE.

    Nota

    In una versione futura di SQL Server verrà rimosso il supporto per l'utilizzo degli hint READUNCOMMITTED e NOLOCK nella clausola FROM per la tabella di destinazione di un'istruzione UPDATE o DELETE. Evitare quindi di utilizzare questi hint in questo contesto nei nuovi progetti di sviluppo e pianificare la modifica delle applicazioni in cui sono attualmente utilizzati.

    È possibile ridurre al minimo la contesa tra blocchi proteggendo nello stesso tempo le transazioni da letture dirty di modifiche dei dati di cui non è stato eseguito il commit utilizzando una delle impostazioni seguenti:

    • Livello di isolamento READ COMMITTED con l'opzione di database READ_COMMITTED_SNAPSHOT impostata su ON.

    • Livello di isolamento SNAPSHOT.

    Per ulteriori informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

    Nota

    Se si verificano errori 601 quando è specificata l'opzione READUNCOMMITTED, risolverli come errori di deadlock (1205), quindi provare a rieseguire l'istruzione.

  • REPEATABLEREAD
    Specifica che viene eseguita un'analisi con la stessa semantica di blocco di una transazione eseguita con un livello di isolamento REPEATABLE READ. Per ulteriori informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

  • ROWLOCK
    Specifica l'acquisizione dei blocchi di riga quando in genere vengono acquisiti i blocchi di pagina o i blocchi a livello di tabella. Se viene specificato nelle transazioni operative al livello di isolamento SNAPSHOT, i blocchi di riga vengono acquisiti solo se ROWLOCK è combinato con altri hint di tabella che richiedono i blocchi, ad esempio UPDLOCK e HOLDLOCK.

  • SERIALIZABLE
    Equivale a HOLDLOCK. Rende i blocchi condivisi più restrittivi mantenendoli attivi fino al completamento di una transazione anziché rilasciarli non appena la tabella o la pagina dei dati richiesta non è più necessaria, indipendentemente dal completamento della transazione. L'analisi viene eseguita con la stessa semantica di una transazione eseguita con il livello di isolamento SERIALIZABLE. Per ulteriori informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

  • TABLOCK
    Specifica che il blocco acquisito deve essere applicato a livello di tabella. Il tipo di blocco acquisito varia in base all'istruzione eseguita. Un'istruzione SELECT può ad esempio acquisire un blocco condiviso. Se si specifica TABLOCK, il blocco condiviso viene applicato all'intera tabella anziché a livello di riga o di pagina. Se si specifica anche HOLDLOCK, il blocco di tabella viene mantenuto attivo fino al termine della transazione.

    Quando si importano dati in un heap tramite l'istruzione INSERT INTO <target_table> SELECT <columns> FROM <source_table>, è possibile abilitare la registrazione ottimizzata e i blocchi per l'istruzione specificando l'hint TABLOCK per la tabella di destinazione. Il modello di recupero del database deve inoltre essere impostato sul modello con registrazione minima o con registrazione minima delle operazioni bulk. Per ulteriori informazioni, vedere INSERT (Transact-SQL).

    Se utilizzato in combinazione con il provider di set di righe con lettura bulk OPENROWSET per importare dati in una tabella, TABLOCK consente a più client di caricare simultaneamente i dati nella tabella di destinazione ottimizzandone la registrazione e i blocchi. Per ulteriori informazioni, vedere Prerequisiti per la registrazione minima nell'importazione bulk.

  • TABLOCKX
    Specifica l'acquisizione di un blocco esclusivo sulla tabella.

  • UPDLOCK
    Specifica che devono essere acquisiti blocchi di aggiornamento, i quali dovranno essere mantenuti attivi fino al completamento della transazione. UPDLOCK acquisisce i blocchi di aggiornamento per le operazioni di lettura solo a livello di riga o di pagina. Se UPDLOCK viene utilizzato insieme a TABLOCK oppure se viene acquisito un blocco a livello di tabella per altri motivi, viene acquisito un blocco esclusivo (X).

    Quando è specificato UPDLOCK, gli hint del livello di isolamento READCOMMITTED e READCOMMITTEDLOCK vengono ignorati. Se ad esempio il livello di isolamento della sessione è impostato su SERIALIZABLE e una query specifica (UPDLOCK, READCOMMITTED), l'hint READCOMMITTED viene ignorato e la transazione viene eseguita utilizzando il livello di isolamento SERIALIZABLE.

  • XLOCK
    Specifica che devono essere acquisiti blocchi esclusivi, i quali dovranno essere mantenuti attivi fino al completamento della transazione. Se specificato in combinazione con ROWLOCK, PAGLOCK o TABLOCK, i blocchi esclusivi vengono applicati al livello di granularità appropriato.

Osservazioni

Gli hint di tabella vengono ignorati se il piano di query non accede alla tabella. Ciò si verifica se Query Optimizer non accede esplicitamente alla tabella oppure perché viene invece eseguito l'accesso a una vista indicizzata. In questo secondo caso è possibile impedire l'accesso a una vista indicizzata utilizzando l'hint per la query OPTION (EXPAND VIEWS).

Tutti gli hint di blocco vengono propagati a tutte le tabelle e viste a cui accede il piano di query, incluse tabelle e viste di riferimento in una vista. SQL Server esegue inoltre le relative verifiche di consistenza dei blocchi.

È possibile che gli hint di blocco ROWLOCK, UPDLOCK e AND XLOCK che acquisiscono blocchi a livello di riga applichino blocchi alle chiavi di indice anziché alle righe di dati effettive. Se, ad esempio, una tabella include un indice non cluster e un'istruzione SELECT che utilizza un hint di blocco viene gestita da un indice di copertura, viene acquisito un blocco sulla chiave dell'indice di copertura anziché sulla riga di dati nella tabella di base.

Se una tabella include colonne calcolate e le colonne calcolate vengono calcolate in base a espressioni o funzioni che accedono a colonne in altre tabelle, su tali tabelle non verranno utilizzati gli hint di tabella. Ciò significa che gli hint di tabella non vengono propagati. Ad esempio, un hint di tabella NOLOCK è specificato in una tabella della query che include colonne calcolate tramite una combinazione di espressioni e funzioni che accedono alle colonne di un'altra tabella. Le tabelle a cui le espressioni e le funzioni fanno riferimento non utilizzano l'hint di tabella NOLOCK durante l'accesso.

Per ogni tabella nella clausola FROM in SQL Server non è consentito impostare più di un hint di tabella appartenente a ognuno dei gruppi riportati di seguito.

  • Hint di granularità: PAGLOCK, NOLOCK, READCOMMITTEDLOCK, ROWLOCK, TABLOCK o TABLOCKX.

  • Hint del livello di isolamento: HOLDLOCK, NOLOCK, READCOMMITTED, REPEATABLEREAD, SERIALIZABLE.

Hint per l'indice filtrato

È possibile utilizzare un hint per l'indice filtrato come hint di tabella; se tuttavia tale indice non include tutte le righe selezionate dalla query, in Query Optimizer viene generato l'errore 8622. Di seguito viene fornito un esempio di hint per l'indice filtrato non valido. Nell'esempio viene creato l'indice filtrato FIBillOfMaterialsWithComponentID, che viene quindi utilizzato come hint per l'indice per un'istruzione SELECT. Il predicato dell'indice filtrato include righe di dati per gli elementi ComponentID 533, 324 e 753. Anche il predicato della query include righe di dati per gli elementi ComponentID 533, 324 e 753, ma estende il set di risultati in modo da includere gli elementi ComponentID 855 e 924, non inclusi nell'indice filtrato. In Query Optimizer, l'hint per l'indice filtrato non può pertanto essere utilizzato e viene generato l'errore 8622. Per ulteriori informazioni, vedere Linee guida per la progettazione di indici filtrati.

USE AdventureWorks2008R2;
GO
IF EXISTS (SELECT name FROM sys.indexes
    WHERE name = N'FIBillOfMaterialsWithComponentID' 
    AND object_id = OBJECT_ID(N'Production.BillOfMaterials'))
DROP INDEX FIBillOfMaterialsWithComponentID
    ON Production.BillOfMaterials;
GO
CREATE NONCLUSTERED INDEX "FIBillOfMaterialsWithComponentID"
    ON Production.BillOfMaterials (ComponentID, StartDate, EndDate)
    WHERE ComponentID IN (533, 324, 753);
GO
SELECT StartDate, ComponentID FROM Production.BillOfMaterials
    WITH( INDEX (FIBillOfMaterialsWithComponentID) )
    WHERE ComponentID in (533, 324, 753, 855, 924);
GO

In Query Optimizer, un hint per l'indice non viene considerato se le opzioni SET non includono i valori necessari per gli indici filtrati. Per ulteriori informazioni, vedere CREATE INDEX (Transact-SQL).

Utilizzo di NOEXPAND

L'hint NOEXPAND è applicabile solo alle viste indicizzate, ovvero alle viste in cui è stato creato un indice cluster univoco. Query Optimizer utilizza l'indice nella vista se una query include riferimenti a colonne disponibili sia in una vista indicizzata, sia nelle tabelle di base e viene determinato che l'utilizzo della vista indicizzata rappresenta il metodo migliore per l'esecuzione della query. Questa funzione viene definita corrispondenza delle viste indicizzate ed è supportata solo in SQL Server Enterprise Edition e Developer Edition.

Tuttavia, affinché Query Optimizer utilizzi le viste indicizzate oppure una vista indicizzata a cui viene fatto riferimento tramite l'hint NOEXPAND per l'esecuzione della corrispondenza, le opzioni SET seguenti devono essere impostate su ON:

ANSI_NULLS

ANSI_WARNINGS

CONCAT_NULL_YIELDS_NULL

ANSI_PADDING

ARITHABORT1

QUOTED_IDENTIFIERS

1 ARITHABORT viene impostata in modo implicito su ON se ANSI_WARNINGS è impostata su ON. Non sarà pertanto necessario modificare manualmente questa impostazione.

L'opzione NUMERIC_ROUNDABORT deve invece essere impostata su OFF.

Per forzare l'utilizzo di un indice per una vista indicizzata in Query Optimizer, è necessario specificare l'opzione NOEXPAND. È possibile utilizzare questo hint solo se la vista è specificata anche nella query. In SQL Server non è disponibile un hint per forzare l'utilizzo di una vista indicizzata specifica in una query in cui tale vista non viene specificata direttamente nella clausola FROM. In Query Optimizer, viene tuttavia valutata la possibilità di utilizzare le viste indicizzate, anche se non sono presenti riferimenti diretti a tali viste all'interno della query.

Per ulteriori informazioni, vedere Risoluzione di indici nelle viste.

Utilizzo di un hint di tabella come hint per la query

Gli hint di tabella possono anche essere specificati come hint per la query utilizzando la clausola OPTION (TABLE HINT). È consigliabile utilizzare un hint di tabella come hint per la query solo nel contesto di una guida di piano. Per le query ad hoc, specificare questi hint solo come hint di tabella. Per ulteriori informazioni, vedere Hint per la query (Transact-SQL).

Autorizzazioni

Gli hint KEEPIDENTITY, IGNORE_CONSTRAINTS e IGNORE_TRIGGERS richiedono l'autorizzazione ALTER sulla tabella.

Esempi

A. Utilizzo dell'hint TABLOCK per specificare un metodo di blocco

Nell'esempio seguente viene impostata l'acquisizione di un blocco condiviso sulla tabella Production.Product. Tale blocco viene mantenuto attivo fino al termine dell'istruzione UPDATE.

USE AdventureWorks2008R2;
GO
UPDATE Production.Product
WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%';
GO

B. Utilizzo dell'hint FORCESEEK per specificare un'operazione di ricerca nell'indice

Nell'esempio seguente l'hint FORCESEEK viene utilizzato senza un indice specificato affinché in Query Optimizer venga eseguita un'operazione di ricerca nell'indice nella tabella Sales.SalesOrderDetail.

USE AdventureWorks2008R2;
GO
SELECT *
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d WITH (FORCESEEK)
    ON h.SalesOrderID = d.SalesOrderID 
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);
GO

Nell'esempio seguente l'hint FORCESEEK viene utilizzato con un indice affinché in Query Optimizer venga eseguita un'operazione di ricerca nell'indice e nella colonna di indice specificati.

USE AdventureWorks2008R2; 
GO
SELECT h.SalesOrderID, h.TotalDue, d.OrderQty
FROM Sales.SalesOrderHeader AS h
    INNER JOIN Sales.SalesOrderDetail AS d 
    WITH (FORCESEEK (PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID (SalesOrderID))) 
    ON h.SalesOrderID = d.SalesOrderID 
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00); 
GO

C. Utilizzo dell'hint FORCESCAN per specificare un'operazione di analisi dell'indice

Nell'esempio seguente viene utilizzato l'hint FORCESCAN affinché in Query Optimizer venga eseguita un'operazione di analisi dell'indice nella tabella Sales.SalesOrderDetail.

USE AdventureWorks2008R2; 
GO
SELECT h.SalesOrderID, h.TotalDue, d.OrderQty
FROM Sales.SalesOrderHeader AS h
    INNER JOIN Sales.SalesOrderDetail AS d 
    WITH (FORCESCAN) 
    ON h.SalesOrderID = d.SalesOrderID 
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);