Hint di tabella (Transact-SQL)
Si applica a:SQL Server database SQL di Azure Istanza gestita di SQL di Azuredatabase SQL in Microsoft Fabric
Gli hint di tabella vengono usati per eseguire l'override del comportamento predefinito di Query Optimizer durante l'istruzione DML (Data Manipulation Language). È possibile specificare un metodo di blocco, uno o più indici, un'operazione di elaborazione query, ad esempio un'analisi di tabella o una ricerca di indice o altre opzioni. Gli hint di tabella vengono specificati nella clausola FROM
dell'istruzione DML e influiscono solo sulla tabella o vista a cui si fa riferimento in tale clausola.
Attenzione
Poiché Query Optimizer di SQL Server seleziona in genere il piano di esecuzione migliore per una query, gli hint devono essere usati solo se strettamente necessari ed esclusivamente da sviluppatori e amministratori di database esperti.
Si applica a:
Convenzioni relative alla sintassi Transact-SQL
Sintassi
WITH ( <table_hint> [ [ , ] ...n ] )
<table_hint> ::=
{ NOEXPAND
| INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> )
| FORCESEEK [ ( <index_value> ( <index_column_name> [ , ... ] ) ) ]
| FORCESCAN
| HOLDLOCK
| NOLOCK
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| READUNCOMMITTED
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| SNAPSHOT
| SPATIAL_WINDOW_MAX_CELLS = <integer_value>
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
<table_hint_limited> ::=
{
KEEPIDENTITY
| KEEPDEFAULTS
| HOLDLOCK
| IGNORE_CONSTRAINTS
| IGNORE_TRIGGERS
| NOLOCK
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| SNAPSHOT
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
Argomenti
WITH ( <table_hint> ) [ [ , ] ...n ]
Con alcune eccezioni, gli hint di tabella sono supportati nella clausola FROM
solo quando gli hint vengono specificati con la parola chiave WITH
. Tali hint devono inoltre essere racchiusi tra parentesi.
Importante
L'omissione della parola chiave WITH
è una funzionalità deprecata: questa funzionalità verrà rimossa in una versione futura di SQL Server. Evitare di usare questa funzionalità in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata.
Gli hint di tabella seguenti sono consentiti con e senza la parola chiave WITH
: NOLOCK
, READUNCOMMITTED
, UPDLOCK
, REPEATABLEREAD
, SERIALIZABLE
, READCOMMITTED
, TABLOCK
, TABLOCKX
, PAGLOCK
, ROWLOCK
, NOWAIT
, READPAST
, XLOCK
, SNAPSHOT
e NOEXPAND
. Quando questi hint di tabella vengono specificati senza la WITH
parola chiave , gli hint devono essere specificati da soli. Ad esempio:
FROM t (TABLOCK)
Quando l'hint viene specificato con un'altra opzione, l'hint deve essere specificato con la parola chiave WITH
:
FROM t WITH (TABLOCK, INDEX(myindex))
Si consiglia di separare gli hint di tabella tramite virgole.
Importante
La separazione degli hint in base agli spazi anziché alle virgole è una funzionalità deprecata: questa funzionalità verrà rimossa in una versione futura di SQL Server. Evitare di usare questa funzionalità in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata.
NOEXPAND
Specifica che le viste indicizzate non vengono espanse per accedere alle tabelle sottostanti quando Query Optimizer elabora la query. In Query Optimizer la vista viene gestita come una tabella con indici cluster.
NOEXPAND
si applica solo alle viste indicizzate. Per altre informazioni, vedere Usare NOEXPAND.
INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> )
La INDEX()
sintassi specifica i nomi o gli ID di uno o più indici da usare da Query Optimizer quando elabora l'istruzione. La sintassi alternativa INDEX =
specifica un singolo valore di indice. È possibile specificare solo un hint per l'indice per ogni tabella.
Se esiste un indice cluster, INDEX(0)
forza un'analisi dell'indice cluster e INDEX(1)
forza un'analisi o una ricerca di indici cluster. Se non esiste alcun indice cluster, INDEX(0)
forza un'analisi di tabella e INDEX(1)
viene interpretata come un errore.
Se in un singolo elenco di hint vengono utilizzati più indici, i duplicati vengono ignorati e il resto degli indici elencati viene usato per recuperare le righe della tabella. L'ordine degli indici nell'hint è significativo. Un hint con 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 fa riferimento la query, viene eseguito un recupero per recuperare le colonne rimanenti dopo che sql Server motore di database recupera tutte le colonne indicizzate.
Nota
Se in una tabella dei fatti in un join a stella viene usato 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. Inoltre, index ORing non è consentito per una tabella con un hint di indice specificato.
Un hint di tabella può includere al massimo 250 indici non cluster.
KEEPIDENTITY
Applicabile solo in un'istruzione INSERT
quando viene usata l'opzione BULK
con OPENROWSET.
Specifica che il valore o i valori Identity presenti nel file di dati importato devono essere usati per la colonna Identity. Se KEEPIDENTITY
non viene specificato, 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 incremento specificati durante la creazione della tabella.
Importante
Se il file di dati non contiene valori per la colonna Identity nella tabella o nella vista e la colonna Identity non è l'ultima colonna della tabella, è necessario ignorare la colonna Identity. Per altre informazioni, vedere Usare un file di formato per ignorare un campo dati (SQL Server). 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 che usa questo hint in un'istruzione INSERT ... SELECT * FROM OPENROWSET(BULK...)
, vedere Mantenere i valori Identity durante l'importazione bulk dei dati (SQL Server).
Per informazioni sul controllo del valore Identity per una tabella, vedere DBCC CHECKIDENT.
KEEPDEFAULTS
Applicabile solo in un'istruzione INSERT
quando viene usata l'opzione BULK
con OPENROWSET.
Specifica l'inserimento del valore predefinito di una colonna di tabella, se presente, anziché NULL
quando il record di dati non dispone di un valore per la colonna.
Per un esempio che usa questo hint in un'istruzione INSERT ... SELECT * FROM OPENROWSET(BULK...)
, vedere Mantenere valori Null o valori predefiniti durante l'importazione bulk (SQL Server).
FORCESEEK [ ( > (< index_column_name> [ , ...n ] ) ) ]
Specifica che Query Optimizer usa solo un'operazione di ricerca dell'indice come percorso di accesso ai dati nella tabella o nella vista.
Nota
A partire da SQL Server 2008 R2 (10.50.x) Service Pack 1, è anche possibile specificare parametri di indice. In questo caso, in Query Optimizer vengono considerate solo le operazioni di ricerca nell'indice specificato, utilizzando almeno le colonne dell'indice specificate.
index_value
Nome dell'indice o valore ID di indice. Non è possibile specificare l'ID di indice 0 (heap). Per restituire il nome o l'ID dell'indice, eseguire una query sulla vista del
sys.indexes
catalogo.index_column_name
Nome della colonna di indice da includere nell'operazione di ricerca. L'impostazione
FORCESEEK
con i parametri di indice è simile all'usoFORCESEEK
con unINDEX
hint. È tuttavia possibile ottenere un maggior controllo sul percorso di accesso usato 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. L'utilità di ottimizzazione potrebbe prendere in considerazione più colonne, se necessario. Ad esempio, se viene specificato un indice non cluster, l'utilità di ottimizzazione potrebbe scegliere di usare le colonne chiave dell'indice cluster oltre alle colonne specificate.
L'hint FORCESEEK
può essere specificato nei modi seguenti.
Sintassi | Esempio | Descrizione |
---|---|---|
Senza un indice o INDEX un hint |
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. |
Combinazione con un INDEX suggerimento |
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 usa l'hint FORCESEEK
(con o senza parametri di indice), prendere in considerazione le linee guida seguenti:
- L'hint può essere specificato come hint di tabella o hint per la query. Per altre informazioni sugli hint per la query, vedere hint di query (Transact-SQL).
- Per applicare
FORCESEEK
a una vista indicizzata, è necessario specificare anche l'hintNOEXPAND
. - L'hint può essere applicato al massimo una volta per ogni tabella o vista.
- Non è possibile specificare l'hint per un'origine dati remota. L'errore 7377 viene restituito quando
FORCESEEK
viene specificato con un hint di indice e viene restituito l'errore 8180 quandoFORCESEEK
viene usato senza un hint di indice. - Se
FORCESEEK
non viene trovato alcun piano, viene restituito l'errore 8622.
Quando FORCESEEK
viene specificato con i parametri di indice, si applicano le linee guida e le restrizioni seguenti:
- Non è possibile specificare l'hint per una tabella che rappresenta la destinazione di un'istruzione
INSERT
,UPDATE
oDELETE
. - L'hint non può essere specificato in combinazione con un
INDEX
hint o un altroFORCESEEK
hint. - È necessario specificare almeno una colonna, la quale deve corrispondere alla colonna chiave iniziale.
- È possibile specificare colonne di indice aggiuntive, ma non è possibile ignorare le colonne chiave. Ad esempio, se l'indice specificato contiene le colonne chiave
a
,b
ec
, la sintassi valida includeFORCESEEK (MyIndex (a))
eFORCESEEK (MyIndex (a, b)
, mentre la sintassi non valida includeFORCESEEK (MyIndex (c))
eFORCESEEK (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 colonne che non sono nella definizione della chiave di 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, ma potrebbero essere usate da Optimizer.
- Non è possibile specificare un indice columnstore ottimizzato per la memoria xVelocity come parametro di indice. Viene restituito l'errore 366.
- La modifica della definizione dell'indice, ad esempio aggiungendo o rimuovendo colonne, potrebbe richiedere modifiche alle 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.
- L'hint non può essere specificato 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
.
Attenzione
Se FORCESEEK
si specifica con parametri, il numero di piani che possono essere considerati dall'ottimizzatore più di quando si specifica FORCESEEK
senza parametri. Ciò potrebbe causare un errore di Plan cannot be generated
in più casi.
FORCESCAN
Si applica a: SQL Server 2008 R2 (10.50.x) Service Pack 1 e versioni successive
Specifica che Query Optimizer usa solo un'operazione di analisi dell'indice come percorso di accesso alla tabella o alla vista a cui si fa riferimento. L'hint FORCESCAN
può essere utile per le query in cui Optimizer sottovaluta il numero di righe interessate e sceglie un'operazione di ricerca anziché un'operazione di analisi. In questo caso, la quantità di memoria concessa per l'operazione è troppo piccola e le prestazioni delle query sono influenzate.
FORCESCAN
può essere specificato con o senza hint INDEX
. Se combinato con un hint di indice (INDEX = index_name, FORCESCAN
), Query Optimizer considera solo i percorsi di accesso tramite l'indice specificato, quando si accede alla tabella a cui si fa riferimento.
FORCESCAN
può essere specificato con l'hint INDEX(0)
di indice per forzare un'operazione di analisi di tabella nella tabella di base.
Per le tabelle e gli indici partizionati, FORCESCAN
viene applicato dopo l'eliminazione delle partizioni tramite la valutazione del predicato di query. L'analisi viene pertanto applicata solo alle partizioni rimanenti, anziché all'intera tabella.
L'hint FORCESCAN
presenta le restrizioni seguenti:
- Non è possibile specificare l'hint per una tabella che rappresenta la destinazione di un'istruzione
INSERT
,UPDATE
oDELETE
. - L'hint non può essere usato con più hint di indice.
- L'hint impedisce a Query Optimizer di prendere in considerazione gli indici spaziali o XML nella tabella.
- Non è possibile specificare l'hint per un'origine dati remota.
- L'hint non può essere specificato in combinazione con l'hint
FORCESEEK
.
HOLDLOCK
È equivalente a SERIALIZABLE
. Per altre informazioni, vedere SERIALIZABLE più avanti in questo articolo.
HOLDLOCK
si applica solo alla tabella o alla vista in cui è specificata e solo per la durata della transazione definita dall'istruzione in cui viene usata.
HOLDLOCK
non può essere usato in un'istruzione SELECT che include l'opzione FOR BROWSE
.
IGNORE_CONSTRAINTS
Applicabile solo in un'istruzione INSERT
quando viene usata l'opzione BULK
con OPENROWSET.
Specifica che l'operazione di importazione bulk ignora tutti i vincoli nella tabella. Per impostazione predefinita, INSERT
controlla vincoli Unique e check e vincoli di chiave primaria ed esterna. Quando si specifica IGNORE_CONSTRAINTS
per un'operazione di importazione bulk, INSERT
deve ignorare questi vincoli in una tabella di destinazione. Non è possibile disabilitare i vincoli UNIQUE
, PRIMARY KEY
o NOT NULL
.
È possibile disabilitare CHECK
e FOREIGN KEY
vincoli se i dati di input contengono righe che violano i vincoli. Disabilitando i vincoli CHECK
e FOREIGN KEY
, è possibile importare i dati e quindi usare istruzioni Transact-SQL per pulire i dati.
Tuttavia, quando i vincoli CHECK
e FOREIGN KEY
vengono ignorati, ogni vincolo ignorato nella tabella viene 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, il costo della riconvalida del vincolo potrebbe superare il costo dell'applicazione di vincoli CHECK
e FOREIGN KEY
ai dati incrementali.
IGNORE_TRIGGERS
Applicabile solo in un'istruzione INSERT
quando viene usata l'opzione BULK
con OPENROWSET.
Specifica che qualsiasi trigger definito sulla tabella verrà ignorato dall'operazione di importazione bulk. Per impostazione predefinita, INSERT
applica i trigger.
Usare IGNORE_TRIGGERS
solo se l'applicazione non dipende da trigger e la ottimizzazione delle prestazioni è importante.
NOLOCK
È equivalente a READUNCOMMITTED
. Per altre informazioni, vedere READUNCOMMITTED più avanti in questo articolo.
Nota
Per UPDATE
o istruzioni DELETE
: questa funzionalità verrà rimossa in una versione futura di SQL Server. Evitare di usare questa funzionalità in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata.
NOWAIT
Indica al motore di database di restituire un messaggio non appena viene rilevato un blocco nella tabella.
NOWAIT
equivale a specificare SET LOCK_TIMEOUT 0
per una tabella specifica. L'hint NOWAIT
non funziona quando viene incluso anche l'hint TABLOCK
. Per terminare una query senza attendere quando si usa l'hint TABLOCK
, anteporre invece la query a SET LOCK_TIMEOUT 0;
.
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 di tabella. Per impostazione predefinita, viene usata la modalità di blocco appropriata per l'operazione specifica. Se specificato nelle transazioni che operano a SNAPSHOT
livello di isolamento, i blocchi di pagina non vengono acquisiti a meno che PAGLOCK
non vengano combinati con altri hint di tabella che richiedono blocchi, ad esempio UPDLOCK
e HOLDLOCK
.
READCOMMITTED
Specifica che le operazioni di lettura sono conformi alle regole per il livello di isolamento READ COMMITTED
tramite il blocco o il controllo delle versioni delle righe. Se l'opzione di database READ_COMMITTED_SNAPSHOT
è OFF
, il motore di database acquisisce blocchi condivisi mentre i dati vengono letti e rilascia tali blocchi al termine dell'operazione di lettura. Se l'opzione di database READ_COMMITTED_SNAPSHOT
è ON
, il motore di database non acquisisce blocchi e usa il controllo delle versioni delle righe. Per altre informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL.
Nota
Per UPDATE
o istruzioni DELETE
: questa funzionalità verrà rimossa in una versione futura di SQL Server. Evitare di usare questa funzionalità in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata.
READCOMMITTEDLOCK
Specifica che le operazioni di lettura sono conformi alle regole per il livello di isolamento READ COMMITTED
tramite il blocco. Il motore di database acquisisce blocchi condivisi durante la lettura dei dati e rilascia tali blocchi al termine dell'operazione di lettura, indipendentemente dall'impostazione dell'opzione READ_COMMITTED_SNAPSHOT
di database. Per altre informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL. Questo hint non può essere specificato nella 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. Quando READPAST
viene specificato, i blocchi a livello di riga vengono ignorati, ma i blocchi a livello di pagina non 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 ma non è ancora stato eseguito il commit, SELECT * FROM T1 (READPAST)
restituisce i valori 1, 2, 4, 5.
READPAST
viene usato principalmente per ridurre la contesa di blocco quando si implementa una coda di lavoro che usa una tabella di SQL Server. Un lettore di coda che usa READPAST
ignora le voci della coda passate bloccate da altre transazioni alla voce successiva della coda disponibile, senza dover attendere fino a quando le altre transazioni rilasciano i blocchi.
READPAST
può essere specificato 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
, READPAST
viene applicato solo durante la lettura dei dati per identificare i record da aggiornare, indipendentemente dalla posizione nell'istruzione specificata.
READPAST
non è possibile specificare per le tabelle nella clausola INTO
di un'istruzione INSERT
. Le operazioni di aggiornamento o eliminazione che usano READPAST
potrebbero bloccarsi durante la lettura di chiavi esterne o viste indicizzate o durante la modifica di indici secondari.
READPAST
può essere specificato solo nelle transazioni che operano ai livelli di isolamento READ COMMITTED
o REPEATABLE READ
. Se specificato nelle transazioni che operano a SNAPSHOT
livello di isolamento, READPAST
deve essere combinato con altri hint di tabella che richiedono 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
READCOMMITTED
di tabella viene specificato anche nella query.
Per specificare l'hint READPAST
in questi casi, rimuovere l'hint READCOMMITTED
di tabella, se presente, e includere l'hint READCOMMITTEDLOCK
di tabella nella query.
READUNCOMMITTED
Indica che le letture dirty sono consentite. Nessun blocco condiviso viene emesso per impedire ad altre transazioni di modificare i dati letti dalla transazione corrente e i blocchi esclusivi impostati da 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. Ciò potrebbe generare errori per la transazione, presentare agli utenti dati che non sono mai stati sottoposti a commit o fare in modo che gli utenti visualizzino i record due volte (o non affatto).
READUNCOMMITTED
e NOLOCK
i suggerimenti si applicano solo ai blocchi dati. Tutte le query, incluse le query con hint READUNCOMMITTED
e NOLOCK
, acquisiscono blocchi di Sch-S (stabilità dello schema) 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. Ad esempio, un'operazione DDL (Data Definition Language) acquisisce un blocco Sch-M prima di modificare le informazioni dello schema della tabella. Tutte le query simultanee, incluse le query in esecuzione con hint READUNCOMMITTED
o NOLOCK
, vengono bloccate quando si tenta di acquisire un blocco Sch-S. Una query con blocco Sch-S blocca invece le transazioni simultanee che tentano di acquisire un blocco Sch-M.
READUNCOMMITTED
e NOLOCK
non possono essere specificati per le tabelle modificate da operazioni di inserimento, aggiornamento o eliminazione. Query Optimizer di SQL Server ignora gli hint READUNCOMMITTED
e NOLOCK
nella clausola FROM
che si applicano alla tabella di destinazione di un'istruzione UPDATE
o DELETE
.
Nota
Il supporto per l'uso degli hint READUNCOMMITTED
e NOLOCK
nella clausola FROM
che si applica alla tabella di destinazione di un'istruzione UPDATE
o DELETE
verrà rimossa in una versione futura di SQL Server. Evitare di usare questi hint in questo contesto nei nuovi progetti di sviluppo e pianificare la modifica delle applicazioni in cui sono attualmente usati.
È possibile ridurre al minimo la contesa di blocco proteggendo le transazioni da letture dirty di modifiche ai dati di cui non è stato eseguito il commit usando una delle opzioni seguenti:
- Livello di isolamento
READ COMMITTED
con l'opzione di databaseREAD_COMMITTED_SNAPSHOT
impostataON
. - Livello
SNAPSHOT
di isolamento.
Per altre informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL.
Nota
Se viene visualizzato messaggio di errore 601 quando si specifica READUNCOMMITTED
, risolverlo come si farebbe con un errore di deadlock (messaggio di errore 1205) e ripetere l'istruzione.
REPEATABLEREAD
Specifica che viene eseguita un'analisi con la stessa semantica di blocco di una transazione in esecuzione a REPEATABLE READ
livello di isolamento. Per altre informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL.
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 specificato nelle transazioni che operano a SNAPSHOT
livello di isolamento, i blocchi di riga non vengono eseguiti a meno che ROWLOCK
non vengano combinati con altri hint di tabella che richiedono blocchi, ad esempio UPDLOCK
e HOLDLOCK
.
ROWLOCK
non può essere usato con una tabella con un indice columnstore cluster. L'esempio seguente restituisce l'errore 651 all'applicazione.
UPDATE [dbo].[FactResellerSalesXL_CCI] WITH (ROWLOCK)
SET UnitPrice = 50
WHERE ProductKey = 150;
SERIALIZABLE
È equivalente 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 in esecuzione a livello di SERIALIZABLE
isolamento. Per altre informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL.
SNAPSHOT
Si applica a: SQL Server 2014 (12.x) e versioni successive
L'accesso alla tabella ottimizzata per la memoria è in SNAPSHOT
isolamento.
SNAPSHOT
può essere usato solo con tabelle ottimizzate per la memoria (non con tabelle basate su disco), come illustrato nell'esempio seguente. Per altre informazioni, vedere Introduzione alle tabelle con ottimizzazione per la memoria.
SELECT *
FROM dbo.Customers AS c WITH (SNAPSHOT)
LEFT OUTER JOIN dbo.[Order History] AS oh
ON c.customer_id = oh.customer_id;
SPATIAL_WINDOW_MAX_CELLS = <integer_value>
Si applica a: SQL Server 2012 (11.x) e versioni successive
Specifica il numero massimo di celle da usare per la suddivisione a mosaico di un oggetto geografico o di geometria. <integer_value> è un valore compreso tra 1 e 8192.
Questa opzione consente l'ottimizzazione dei tempi di esecuzione delle query raggiungendo un compromesso tra il tempo di esecuzione del filtro primario e secondario. Un numero maggiore riduce il tempo di esecuzione del filtro secondario, ma aumenta il tempo di esecuzione del filtro primario e un numero minore diminuisce tempo di esecuzione del filtro primario, ma aumenta l'esecuzione del filtro secondario. Per i dati spaziali più densi, un numero superiore dovrebbe dar luogo a un tempo di esecuzione più rapido fornendo un'approssimazione migliore del filtro primario e riducendo il tempo di esecuzione del filtro secondario. Per altri dati di tipo sparse, un numero inferiore riduce il tempo di esecuzione del filtro primario.
Questa opzione funziona per sia per le suddivisioni a mosaico della griglia automatiche che per quelle manuali.
TABLOCK
Specifica che il blocco acquisito deve essere applicato a livello di tabella. Il tipo di blocco acquisito varia in base all'istruzione eseguita. Ad esempio, un'istruzione SELECT
potrebbe acquisire un blocco condiviso. Specificando TABLOCK
, il blocco condiviso viene applicato all'intera tabella anziché a livello di riga o di pagina. Se HOLDLOCK
viene specificato anche , il blocco di tabella viene mantenuto fino alla fine della transazione.
Quando si importano dati in un heap usando l'istruzione INSERT INTO <target_table> SELECT <columns> FROM <source_table>
, è possibile abilitare la registrazione minima e il blocco ottimale 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. L'hint TABLOCK
consente anche inserimenti paralleli agli heap o agli indici columnstore cluster. Per altre informazioni, vedere INSERT.
Se usato con il provider di set di righe bulk OPENROWSET per importare dati in una tabella, TABLOCK
consente a più client di caricare simultaneamente i dati nella tabella di destinazione con registrazione e blocco ottimizzati. Per altre 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
accetta blocchi di aggiornamento per le operazioni di lettura solo a livello di riga o di pagina. Se UPDLOCK
viene combinato con TABLOCK
o viene eseguito un blocco a livello di tabella per un altro motivo, viene invece eseguito un blocco esclusivo (X).
Quando UPDLOCK
viene specificato, gli hint del READCOMMITTED
livello di isolamento e READCOMMITTEDLOCK
vengono ignorati. Ad esempio, se 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 usando il SERIALIZABLE
livello di isolamento.
XLOCK
Specifica che devono essere acquisiti blocchi esclusivi, i quali dovranno essere mantenuti attivi fino al completamento della transazione. Se specificato con ROWLOCK
, PAGLOCK
o TABLOCK
, i blocchi esclusivi si applicano al livello di granularità appropriato.
Osservazioni:
Gli hint di tabella vengono ignorati se la tabella non è accessibile dal piano di query. Ciò potrebbe essere causato dalla scelta dell'utilità di ottimizzazione di non accedere alla tabella o perché si accede a una vista indicizzata. In quest'ultimo caso, l'accesso a una vista indicizzata può essere impedito usando 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 corrispondenti verifiche di coerenza dei blocchi.
Gli hint di blocco ROWLOCK
, UPDLOCK
e XLOCK
che acquisiscono blocchi a livello di riga potrebbero inserire blocchi sulle chiavi di indice anziché sulle righe di dati effettive. Ad esempio, se una tabella ha un indice non cluster e un'istruzione SELECT
che usa un hint di blocco viene gestita da un indice di copertura, viene acquisito un blocco sulla chiave di indice nell'indice di copertura anziché sulla riga di dati nella tabella di base.
Se una tabella contiene colonne calcolate calcolate calcolate da espressioni o funzioni che accedono alle colonne in altre tabelle, gli hint di tabella non vengono usati in tali tabelle e non vengono propagati. Ad esempio, un NOLOCK
hint di tabella viene specificato in una tabella nella query. che include colonne calcolate tramite una combinazione di espressioni e funzioni che accedono alle colonne di un'altra tabella. Le tabelle a cui fanno riferimento le espressioni e le funzioni non usano l'hint di NOLOCK
tabella quando si accede.
SQL Server non consente più di un hint di tabella da ognuno dei gruppi seguenti per ogni tabella nella clausola FROM
:
- Hint di granularità:
PAGLOCK
,NOLOCK
,READCOMMITTEDLOCK
ROWLOCK
, ,TABLOCK
oTABLOCKX
. - Hint del livello di isolamento:
HOLDLOCK
,NOLOCK
,READCOMMITTED
,REPEATABLEREAD
,SERIALIZABLE
.
Hint per l'indice filtrato
Un indice filtrato può essere usato come hint di tabella, ma fa sì che Query Optimizer generi l'errore 8622 se non copre tutte le righe selezionate dalla query. Di seguito viene fornito un esempio di hint per l'indice filtrato non valido. L'esempio crea l'indice filtrato FIBillOfMaterialsWithComponentID
e quindi lo usa come hint di indice per un'istruzione SELECT
. Il predicato dell'indice filtrato include righe di dati per gli elementi ComponentID 533, 324 e 753. Il predicato di query include anche righe di dati per ComponentID 533, 324 e 753, ma estende il set di risultati per includere ComponentIDs 855 e 924, che non sono nell'indice filtrato. Pertanto, Query Optimizer non può usare l'hint per l'indice filtrato e genera l'errore 8622. Per altre informazioni, vedere Creare indici filtrati.
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
Query Optimizer non considera un hint per l'indice se le opzioni di SET
non hanno i valori necessari per gli indici filtrati. Per altre informazioni, vedere CREATE INDEX.
Usare NOEXPAND
NOEXPAND
si applica solo alle viste indicizzate. ovvero alle viste in cui è stato creato un indice cluster univoco. In Query Optimizer viene usato l'indice nella vista se in una query sono inclusi 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 funzionalità viene chiamata corrispondenza della vista indicizzata. Prima di SQL Server 2016 (13.x) con Service Pack 1, l'uso automatico di una vista indicizzata da Query Optimizer è supportato solo in edizioni specifiche di SQL Server. In SQL Server 2016 (13.x) con Service Pack 1 e versioni successive, tutte le edizioni supportano l'uso automatico di una vista indicizzata. Database SQL di Azure e Istanza gestita di SQL di Azure supportano l'uso automatico di viste indicizzate senza specificare l'hint NOEXPAND
.
Per altre informazioni, vedere Guida all'architettura di elaborazione delle query.
Per un elenco delle caratteristiche supportate dalle edizioni di SQL Server su Windows, vedi:
- Edizioni e funzionalità supportate di SQL Server 2022
- Edizioni e funzionalità supportate di SQL Server 2019
- Edizioni e funzionalità supportate di SQL Server 2017
- Edizioni e le funzionalità supportate di SQL Server 2016
Tuttavia, affinché Query Optimizer consideri le viste indicizzate per la corrispondenza o usa una vista indicizzata a cui viene fatto riferimento con l'hint NOEXPAND
, è necessario impostare le opzioni di SET
seguenti su ON
.
- ANSI_NULLS
- ANSI_PADDING
- ANSI_WARNINGS
- ARITHABORT 1
- CONCAT_NULL_YIELDS_NULL
- QUOTED_IDENTIFIER
1ARITHABORT
viene impostato in modo implicito su ON
quando ANSI_WARNINGS
è impostato su ON
. Pertanto, non è necessario modificare manualmente questa impostazione.
Inoltre, l'opzione NUMERIC_ROUNDABORT
deve essere impostata su OFF
.
Per forzare Query Optimizer a usare un indice per una vista indicizzata, specificare l'opzione NOEXPAND
. Questo hint può essere usato solo se la vista è specificata anche nella query. SQL Server non fornisce un hint per forzare l'uso di una particolare vista indicizzata in una query che non denomina la vista direttamente nella clausola FROM
. Tuttavia, Query Optimizer considera l'uso di viste indicizzate, anche se non viene fatto riferimento direttamente nella query. Il motore di database di SQL Server crea automaticamente statistiche solo in una vista indicizzata quando viene usato un hint di tabella NOEXPAND
. L'omissione di questo hint può causare avvisi del piano di esecuzione relativi alle statistiche mancanti che non possono essere risolte creando manualmente le statistiche.
Durante l'ottimizzazione delle query, il motore di database usa le statistiche di visualizzazione create automaticamente o manualmente quando la query fa riferimento direttamente alla vista e viene usato l'hintNOEXPAND
.
Usare un hint di tabella come hint per la query
gli hint di tabella possono essere specificati anche come hint per la query usando la clausola OPTION (TABLE HINT)
. È consigliabile usare 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 altre informazioni, vedere hint di query .
Autorizzazioni
Gli hint KEEPIDENTITY
, IGNORE_CONSTRAINTS
e IGNORE_TRIGGERS
richiedono autorizzazioni di ALTER
per la tabella.
Esempi
R. Usare l'hint TABLOCK per specificare un metodo di blocco
Nell'esempio seguente viene specificato che viene eseguito un blocco condiviso nella tabella Production.Product
del database AdventureWorks2022 e viene mantenuto fino alla fine dell'istruzione UPDATE
.
UPDATE Production.Product WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%';
GO
B. Usare l'hint FORCESEEK per specificare un'operazione index seek
Nell'esempio seguente viene usato l'hint FORCESEEK
senza specificare un indice per forzare query optimizer a eseguire un'operazione di ricerca dell'indice nella Sales.SalesOrderDetail
tabella nel database AdventureWorks2022.
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 viene usato l'hint FORCESEEK
con un indice per forzare query Optimizer a eseguire un'operazione di ricerca dell'indice sull'indice e sulla colonna di indice specificata.
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. Usare l'hint FORCESCAN per specificare un'operazione di analisi dell'indice
Nell'esempio seguente viene usato l'hint FORCESCAN
per forzare query optimizer a eseguire un'operazione di analisi nella Sales.SalesOrderDetail
tabella nel database AdventureWorks2022.
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);
Contenuto correlato
- OPENROWSET (Transact-SQL)
- Hint (Transact-SQL)
- hint di query (Transact-SQL)