Hint di tabella (Transact-SQL)
Si applica a: SQL Server Database SQL di Azure Istanza gestita di SQL di Azure
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 sono specificati nella clausola FROM dell'istruzione DML e influiscono solo sulla tabella o sulla vista a cui viene fatto riferimento nella 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 se 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)
Se l'hint viene specificato con un'altra opzione, è necessario usare 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 Utilizzo di 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. Non è inoltre consentito il collegamento degli indici tramite OR per una tabella per la quale è stato specificato un hint per l'indice.
Un hint di tabella può includere al massimo 250 indici non cluster.
KEEPIDENTITY
Applicabile solo in un'istruzione INSERT quando l'opzione BULK viene usata 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, tale colonna deve essere ignorata, a meno che non sia l'ultima colonna della tabella. Per altre informazioni, vedere Usare un file di formato per escludere un campo di 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 di questo hint in un'istruzione INSERT ... SELECT * FROM OPENROWSET(BULK...)
, vedere Mantenere i valori Identity durante l'importazione bulk dei dati (SQL Server).
Per altre informazioni sul controllo del valore Identity per una tabella, vedere DBCC CHECKIDENT (Transact-SQL).
KEEPDEFAULTS
Applicabile solo in un'istruzione INSERT quando l'opzione BULK viene usata 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 d'uso di questo hint in un'istruzione INSERT... SELECT * FROM OPENROWSET(BULK...), vedere Mantenere i valori Null o usare i valori predefiniti durante un'importazione bulk (SQL Server).
FORCESEEK [ ( <index_value> (< 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. Se necessario, possono essere considerate ulteriori colonne. A esempio, se si specifica un indice non cluster, è possibile che in Query Optimizer vengano usate 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 per la 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 o DELETE.
- 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 possono essere usate dall'utilità di ottimizzazione.
- 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 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.
- 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 Plan cannot be generated
in più casi. In una versione futura le modifiche interne a Query Optimizer potrebbero consentire di prendere in considerazione più piani.
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 per l'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 o DELETE.
- 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 utilizzata. HOLDLOCK
non può essere usato in un'istruzione SELECT che include l'opzione FOR BROWSE
.
IGNORE_CONSTRAINTS
Applicabile solo in un'istruzione INSERT quando l'opzione BULK viene usata con OPENROWSET.
Specifica che qualsiasi vincolo sulla tabella verrà ignorato dall'operazione di importazione bulk. Per impostazione predefinita, INSERT controlla i vincoli UNIQUE e CHECK e i vincoli di chiavi primarie ed esterne. Se si specifica IGNORE_CONSTRAINTS per un'operazione di importazione bulk, l'istruzione INSERT deve ignorare tali vincoli in una tabella di destinazione. Non è possibile disabilitare 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 usare istruzioni Transact-SQL per pulire i dati.
Quando, tuttavia, 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 può superare il costo di applicazione dei vincoli CHECK e FOREIGN KEY ai dati incrementali.
IGNORE_TRIGGERS
Applicabile solo in un'istruzione INSERT quando l'opzione BULK viene usata 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.
Usare IGNORE_TRIGGERS solo se l'applicazione non dipende da alcun trigger e la ottimizzazione delle prestazioni è importante.
NOLOCK
È equivalente a READUNCOMMITTED
. Per altre informazioni, vedere READUNCOMMITTED
più avanti in questo articolo.
Nota
Per le istruzioni UPDATE o 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 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 READ_COMMITTED_SNAPSHOT
di database è impostata su OFF, il motore di database acquisisce blocchi condivisi man mano che i dati vengono letti e rilascia tali blocchi al termine dell'operazione di lettura. Se l'opzione READ_COMMITTED_SNAPSHOT
di database è impostata su 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 (Transact-SQL).
Nota
Per le istruzioni UPDATE o 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 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 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 (Transact-SQL). 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 può essere specificato per le tabelle nella clausola INTO di un'istruzione INSERT. Le operazioni di aggiornamento o eliminazione che usano READPAST
possono bloccare la lettura di chiavi esterne o viste indicizzate o quando si modificano indici secondari.
READPAST
può essere specificato solo nelle transazioni che operano a livello 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
.
Non è possibile specificare l'hint READPAST
di tabella quando l'opzione READ_COMMITTED_SNAPSHOT
di database è 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. 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.
READUNCOMMITTED
e NOLOCK
i suggerimenti si applicano solo ai blocchi dati. Tutte le query, incluse quelle con READUNCOMMITTED
e NOLOCK
hint, acquisiscono blocchi 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 quelle in esecuzione con READUNCOMMITTED
o NOLOCK
hint, 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 READUNCOMMITTED
hint e NOLOCK
nella clausola FROM che si applicano alla tabella di destinazione di un'istruzione UPDATE o DELETE.
Nota
Il supporto per l'uso READUNCOMMITTED
degli hint e NOLOCK
nella clausola FROM che si applicano alla tabella di destinazione di un'istruzione UPDATE o DELETE verrà rimosso 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 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
READ_COMMITTED_SNAPSHOT
database impostata su ON. - Livello
SNAPSHOT
di isolamento.
Per altre informazioni sui livelli di isolamento, vedere SET TRANSACTION ISOLATION LEVEL (Transact-SQL).
Nota
Se viene visualizzato il messaggio di errore 601 quando READUNCOMMITTED
viene specificato, risolverlo come si sarebbe verificato 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 eseguita con un livello di isolamento REPEATABLE READ. Per altre 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 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 (Transact-SQL).
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 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. Un'istruzione SELECT può ad esempio 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 (Transact-SQL).
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ò 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 corrispondenti verifiche di coerenza dei blocchi.
Gli hint ROWLOCK
di blocco , UPDLOCK
, AND XLOCK
che acquisiscono blocchi a livello di riga possono inserire blocchi sulle chiavi di indice anziché sulle 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 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 causerà la generazione dell'errore 8622 da parte di Query Optimizer se non copre tutte le righe selezionate dalla query. 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 usato 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. 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 Create Filtered Indexes.
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 considererà un hint di indice se le opzioni SET non hanno i valori necessari per gli indici filtrati. Per altre informazioni, vedere CREATE INDEX (Transact-SQL).
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) Service Pack 1, l'uso automatico di una vista indicizzata in Query Optimizer era supportato solo in edizioni specifiche di SQL Server. Da allora, 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 SET seguenti su ON.
- ANSI_NULLS
- ANSI_PADDING
- ANSI_WARNINGS
- ARITHABORT 1
- CONCAT_NULL_YIELDS_NULL
- QUOTED_IDENTIFIER
1 ARITHABORT viene impostata in modo implicito su ON se ANSI_WARNINGS è impostata su ON. Pertanto, non è necessario modificare manualmente questa impostazione.
L'opzione NUMERIC_ROUNDABORT deve invece 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 creerà automaticamente statistiche solo in una vista indicizzata quando viene usato un hint per la NOEXPAND
tabella. 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 anche essere specificati come hint per la query tramite 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 per la query (Transact-SQL).
Autorizzazioni
Gli hint KEEPIDENTITY, IGNORE_CONSTRAINTS e IGNORE_TRIGGERS richiedono l'autorizzazione ALTER
sulla 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 Production.Product
tabella nel 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);