Eventi
31 mar, 23 - 2 apr, 23
Il più grande evento di apprendimento di SQL, Infrastruttura e Power BI. 31 marzo - 2 aprile. Usare il codice FABINSIDER per salvare $400.
Iscriviti oggi stessoQuesto browser non è più supportato.
Esegui l'aggiornamento a Microsoft Edge per sfruttare i vantaggi di funzionalità più recenti, aggiornamenti della sicurezza e supporto tecnico.
Si applica a: SQL Server
Database SQL di Azure
Istanza gestita di SQL di Azure
Azure Synapse Analytics
Piattaforma di strumenti analitici (PDW)
Crea un indice relazionale per una tabella o una vista. Viene detto anche indice rowstore, perché è un indice ad albero b-tree sia cluster che non cluster. È possibile creare un indice rowstore prima che siano presenti dati nella tabella. Usare un indice rowstore per migliorare le prestazioni delle query, in particolare quando le query effettuano le selezioni da colonne specifiche o richiedono valori da organizzare in base a un ordine particolare.
Nota
Nella documentazione viene usato in modo generico il termine albero B in riferimento agli indici. Negli indici rowstore, il motore di database implementa un albero B+. Ciò non si applica a indici columnstore o a indici in tabelle ottimizzate per la memoria. Per altre informazioni, vedere Architettura e guida per la progettazione degli indici SQL Server e Azure SQL.
Azure Synapse Analytics e la piattaforma di strumenti analitici attualmente non supportano vincoli univoci. Eventuali esempi che fanno riferimento ai vincoli univoci sono applicabili solo a SQL Server e database SQL.
Per informazioni sulle linee guida di progettazione degli indici, vedere Guida per la progettazione di indici di SQL Server.
Esempi:
Creare un indice non cluster in una tabella o una vista
CREATE INDEX index1 ON schema1.table1 (column1);
Creare un indice cluster in una tabella e usare un nome in 3 parti per la tabella
CREATE CLUSTERED INDEX index1 ON database1.schema1.table1 (column1);
Creare un indice non cluster con un vincolo univoco e specificare l'ordinamento
CREATE UNIQUE INDEX index1 ON schema1.table1 (column1 DESC, column2 ASC, column3 DESC);
Scenario chiave:
A partire da SQL Server 2016 (13.x) e database SQL, è possibile usare un indice non cluster in un indice columnstore per migliorare le prestazioni delle query di data warehousing. Per altre informazioni, vedere Indici columnstore - Data warehouse.
Per altri tipi di indici, vedere:
Convenzioni relative alla sintassi Transact-SQL
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
ON <object> ( column [ ASC | DESC ] [ ,...n ] )
[ INCLUDE ( column_name [ ,...n ] ) ]
[ WHERE <filter_predicate> ]
[ WITH ( <relational_index_option> [ ,...n ] ) ]
[ ON { partition_scheme_name ( column_name )
| filegroup_name
| default
}
]
[ FILESTREAM_ON { filestream_filegroup_name | partition_scheme_name | "NULL" } ]
[ ; ]
<object> ::=
{ database_name.schema_name.table_or_view_name | schema_name.table_or_view_name | table_or_view_name }
<relational_index_option> ::=
{
PAD_INDEX = { ON | OFF }
| FILLFACTOR = fillfactor
| SORT_IN_TEMPDB = { ON | OFF }
| IGNORE_DUP_KEY = { ON | OFF }
| STATISTICS_NORECOMPUTE = { ON | OFF }
| STATISTICS_INCREMENTAL = { ON | OFF }
| DROP_EXISTING = { ON | OFF }
| ONLINE = { ON [ ( <low_priority_lock_wait> ) ] | OFF }
| RESUMABLE = { ON | OFF }
| MAX_DURATION = <time> [MINUTES]
| ALLOW_ROW_LOCKS = { ON | OFF }
| ALLOW_PAGE_LOCKS = { ON | OFF }
| OPTIMIZE_FOR_SEQUENTIAL_KEY = { ON | OFF }
| MAXDOP = max_degree_of_parallelism
| DATA_COMPRESSION = { NONE | ROW | PAGE }
[ ON PARTITIONS ( { <partition_number_expression> | <range> }
[ , ...n ] ) ]
| XML_COMPRESSION = { ON | OFF }
[ ON PARTITIONS ( { <partition_number_expression> | <range> }
[ , ...n ] ) ]
}
<filter_predicate> ::=
<conjunct> [ AND ] [ ...n ]
<conjunct> ::=
<disjunct> | <comparison>
<disjunct> ::=
column_name IN (constant ,...n)
<comparison> ::=
column_name <comparison_op> constant
<comparison_op> ::=
{ IS | IS NOT | = | <> | != | > | >= | !> | < | <= | !< }
<low_priority_lock_wait>::=
{
WAIT_AT_LOW_PRIORITY ( MAX_DURATION = <time> [ MINUTES ] ,
ABORT_AFTER_WAIT = { NONE | SELF | BLOCKERS } )
}
<range> ::=
<partition_number_expression> TO <partition_number_expression>
Importante
La struttura della sintassi dell'indice relazionale compatibile con le versioni precedenti verrà rimossa in una versione futura di SQL Server. Evitare di utilizzare questa struttura della sintassi e pianificare la modifica delle applicazioni che ne fanno uso. Usare invece la struttura della sintassi specificata in <relational_index_option>.
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
ON <object> ( column_name [ ASC | DESC ] [ ,...n ] )
[ WITH <backward_compatible_index_option> [ ,...n ] ]
[ ON { filegroup_name | "default" } ]
<object> ::=
{
[ database_name. [ owner_name ] . | owner_name. ]
table_or_view_name
}
<backward_compatible_index_option> ::=
{
PAD_INDEX
| FILLFACTOR = fillfactor
| SORT_IN_TEMPDB
| IGNORE_DUP_KEY
| STATISTICS_NORECOMPUTE
| DROP_EXISTING
}
CREATE CLUSTERED COLUMNSTORE INDEX index_name
ON [ database_name . [ schema ] . | schema . ] table_name
[ORDER (column[,...n])]
[WITH ( DROP_EXISTING = { ON | OFF } )]
[;]
CREATE [ CLUSTERED | NONCLUSTERED ] INDEX index_name
ON [ database_name . [ schema ] . | schema . ] table_name
( { column [ ASC | DESC ] } [ ,...n ] )
WITH ( DROP_EXISTING = { ON | OFF } )
[;]
Crea un indice univoco per una tabella o una vista. Un indice univoco non consente l'utilizzo di uno stesso valore di chiave di indice per più righe. L'indice cluster di una vista deve essere univoco.
Nel motore di database non è possibile creare un indice univoco su colonne che includono già valori duplicati, indipendentemente dal fatto che l'opzione IGNORE_DUP_KEY
sia impostata o meno su ON. Se si tenta di eseguire questa operazione, il motore di database visualizza un messaggio di errore. Prima di poter creare un indice univoco su una o più colonne di questo tipo, è necessario rimuovere i valori duplicati. Le colonne utilizzate in un indice univoco devono essere impostate su NOT NULL, perché più valori Null vengono considerati duplicati in fase di creazione dell'indice.
Crea un indice in cui l'ordine logico dei valori di chiave determina l'ordine fisico delle righe corrispondenti di una tabella. Nel livello inferiore, o foglia, dell'indice cluster sono contenute le righe di dati effettive della tabella. È possibile creare un solo indice cluster alla volta per una tabella o una vista.
Una vista con un indice cluster univoco viene definita vista indicizzata. La creazione di un indice cluster univoco per una vista materializza fisicamente la vista. È necessario creare un indice cluster univoco per una vista prima di poter definire altri indici per la stessa vista. Per altre informazioni, vedere Creare viste indicizzate.
Creare l'indice cluster prima di qualsiasi indice non cluster. Quando si crea un indice cluster, gli indici non cluster esistenti delle tabelle vengono ricompilati.
Se CLUSTERED
viene omesso, viene creato un indice non cluster.
Nota
Poiché per definizione il livello foglia di un indice cluster corrisponde alle pagine di dati, la creazione di un indice cluster con la clausola ON partition_scheme_name
oppure ON filegroup_name
comporta lo spostamento di una tabella dal filegroup in cui è stata creata al nuovo schema di partizione o filegroup. Prima di creare tabelle o indici in filegroup specifici, verificare i filegroup disponibili e controllare che dispongano di spazio sufficiente per l'indice.
In alcuni casi la creazione di un indice cluster può abilitare gli indici precedentemente disabilitati. Per altre informazioni, vedere Abilitare indici e vincoli e Disabilitare indici e vincoli.
Crea un indice che specifica l'ordinamento logico di una tabella. Quando si utilizza un indice non cluster, l'ordine fisico delle righe di dati è indipendente dall'ordine delle righe indicizzato.
Per ogni tabella è possibile definire al massimo 999 indici non cluster, indipendentemente dal fatto che vengano creati in modo implicito tramite vincoli PRIMARY KEY e UNIQUE oppure in modo esplicito tramite CREATE INDEX
.
Per le viste indicizzate, gli indici non cluster possono essere creati solo se sulla vista è già stato definito un indice cluster univoco.
Se non è specificato diversamente, il tipo di indice predefinito è non cluster.
Nome dell'indice. I nomi di indice devono essere univoci all'interno di una tabella o di una vista, ma non all'interno di un database. Devono essere anche conformi alle regole degli identificatori.
Una o più colonne su cui è basato l'indice. Specificare due o più nomi di colonna per creare un indice composto sui valori combinati delle colonne specificate. Elencare le colonne da includere nell'indice composto, in base alla priorità di ordinamento, tra parentesi dopo table_or_view_name.
In una singola chiave di indice composto è possibile combinare al massimo 32 colonne. Tutte le colonne di una chiave di indice composto devono appartenere alla stessa tabella o vista. La dimensione massima consentita dei valori combinati dell'indice è 900 byte per un indice cluster o 1700 per un indice non cluster. I limiti sono 16 colonne e 900 byte per le versioni precedenti a database SQL e SQL Server 2016 (13.x).
Le colonne con tipo di dati LOB (Large Object) ntext, text, varchar(max), nvarchar(max), varbinary(max), xml o image non possono essere specificate come colonne chiave di un indice. Inoltre, una definizione di vista non può includere colonne di tipo ntext, text o image anche se non vi viene fatto riferimento nell'istruzione CREATE INDEX
.
È possibile creare indici su colonne di tipo CLR definito dall'utente se il tipo supporta l'ordinamento binario. È inoltre possibile creare indici su colonne calcolate definite come chiamate di metodo da una colonna con tipo definito dall'utente, a condizione che i metodi siano contrassegnati come deterministici e non eseguano operazioni di accesso ai dati. Per altre informazioni sull'indicizzazione di colonne di tipo CLR definito dall'utente, vedere Tipi CLR definiti dall'utente.
Determina se il tipo di ordinamento della colonna di indice specificata è crescente o decrescente. Il valore predefinito è ASC.
Specifica le colonne non chiave da aggiungere al livello foglia dell'indice non cluster. L'indice non cluster può essere univoco o non univoco.
I nomi di colonna non possono essere ripetuti nell'elenco INCLUDE e non possono essere usati contemporaneamente per colonne chiave e non chiave. Gli indici non cluster contengono sempre le colonne dell'indice cluster se nella tabella è definito un indice cluster. Per altre informazioni, vedere Creare indici con colonne incluse.
È possibile usare qualsiasi tipo di dati, ad eccezione di text, ntexte image. A partire da SQL Server 2012 (11.x) e database SQL di Azure, se una delle colonne non chiave specificate è di tipo di dati varchar(max), nvarchar(max) o varbinary(max), l'indice può essere compilato o ricompilato usando l'opzione ONLINE.
Come colonne incluse è possibile utilizzare colonne calcolate che sono deterministiche, sia precise che imprecise. Le colonne calcolate derivate dai tipi di dati image, ntext, text, varchar(max), nvarchar(max), varbinary(max) e xml possono essere incluse in colonne non chiave purché il tipo di dati della colonna calcolata sia consentito come colonna inclusa. Per altre informazioni, vedere Indici per le colonne calcolate.
Per informazioni sulla creazione di un indice XML, vedere CREATE XML INDEX.
Crea un indice filtrato specificando le righe da includere nell'indice. L'indice filtrato deve essere un indice non cluster in una tabella. Crea statistiche filtrate per le righe di dati dell'indice filtrato.
Il predicato del filtro usa una logica di confronto semplice e non può fare riferimento a una colonna calcolata, a una colonna con tipo definito dall'utente (UDT), a una colonna con tipo di dati spaziali o a una colonna con tipo di dati hierarchyID. I confronti in cui vengono usati valori letterali NULL
non sono consentiti con gli operatori di confronto. Usare invece gli operatori IS NULL
e IS NOT NULL
.
Di seguito sono riportati alcuni esempi di predicati di filtro per la tabella Production.BillOfMaterials
:
WHERE StartDate > '20000101' AND EndDate <= '20000630'
WHERE ComponentID IN (533, 324, 753)
WHERE StartDate IN ('20000404', '20000905') AND EndDate IS NOT NULL
Gli indici filtrati non si applicano agli indici XML e full-text. Per gli indici UNIQUE, solo le righe selezionate devono avere valori di indice univoci. Gli indici filtrati non consentono l'opzione IGNORE_DUP_KEY
.
Specifica lo schema di partizione che definisce i filegroup a cui verrà eseguito il mapping delle partizioni di un indice partizionato. È necessario che lo schema di partizione sia presente nel database e sia stato creato eseguendo CREATE PARTITION SCHEME o ALTER PARTITION SCHEME. column_name specifica la colonna in base alla quale verrà eseguita la partizione di un indice partizionato. La colonna deve corrispondere all'argomento della funzione di partizione usata da partition_scheme_name per tipo di dati, lunghezza e precisione. column_name non è limitato alle colonne nella definizione dell'indice. È possibile specificare qualsiasi colonna della tabella di base tranne quando si esegue la partizione di un indice UNIQUE. In questo caso il valore column_name deve essere scelto tra quelli usati come chiave univoca. Questa restrizione consente al motore di database di verificare l'univocità dei valori di chiave solo all'interno di una singola partizione.
Nota
Quando si partiziona un indice cluster non univoco, per impostazione predefinita il motore di database aggiunge la colonna di partizionamento all'elenco delle chiavi di indice cluster, se non è già presente. Quando si partiziona un indice non cluster non univoco, il motore di database aggiunge la colonna di partizionamento come colonna non chiave (inclusa) dell'indice, se non è già presente.
Se non si specifica partition_scheme_name o filegroup e la tabella è partizionata, l'indice viene posizionato nello stesso schema di partizione, usando la stessa colonna di partizionamento della tabella sottostante.
Nota
Non è possibile specificare uno schema di partizione per un indice XML. Se la tabella di base è partizionata, l'indice XML utilizzerà lo stesso schema di partizione della tabella.
Per altre informazioni sul partizionamento degli indici, vedere Tabelle e indici partizionati.
Crea l'indice specificato nel filegroup specificato. Se non viene specificata una posizione e la tabella o la vista non è partizionata, l'indice userà lo stesso filegroup della tabella o della vista sottostante. Il filegroup deve essere già esistente.
Crea l'indice specificato nello stesso filegroup o schema di partizione della tabella o della vista.
In questo contesto "default" non rappresenta una parola chiave. Si tratta di un identificatore del filegroup predefinito e deve essere delimitato, ad esempio ON "default"
o ON [default]
. Se si specifica "default", l'opzione QUOTED_IDENTIFIER deve essere impostata su ON per la sessione corrente. Si tratta dell'impostazione predefinita. Per altre informazioni, vedere SET QUOTED_IDENTIFIER.
Nota
"default" non indica il filegroup predefinito del database nel contesto di CREATE INDEX
, a differenza di CREATE TABLE
dove "default" individua la tabella nel filegroup predefinito del database.
Specifica la posizione dei dati FILESTREAM per la tabella quando viene creato un indice cluster. La clausola FILESTREAM_ON
consente di spostare i dati FILESTREAM in uno schema di partizione o in un filegroup FILESTREAM diverso.
filestream_filegroup_name è il nome di un filegroup FILESTREAM. Nel filegroup deve essere disponibile un file definito usando un'istruzione CREATE DATABASE o ALTER DATABASE. In caso contrario, viene generato un errore.
Se la tabella è partizionata, la clausola FILESTREAM_ON
deve essere inclusa e deve specificare uno schema di partizione dei filegroup FILESTREAM che usi la stessa funzione di partizione e le stesse colonne di partizione dello schema di partizione per la tabella. In caso contrario, viene generato un errore.
Se la tabella non è partizionata, la colonna FILESTREAM non può essere partizionata. I dati FILESTREAM per la tabella devono essere archiviati in un singolo filegroup specificato nella clausola FILESTREAM_ON
.
È possibile specificare FILESTREAM_ON NULL
in un'istruzione CREATE INDEX
se si sta creando un indice cluster e se nella tabella non è contenuta alcuna colonna FILESTREAM.
Per altre informazioni, vedere FILESTREAM (SQL Server).
Oggetto con nome completo o non completo da indicizzare.
Nome del database.
Nome dello schema a cui appartiene la tabella o la vista.
Nome della tabella o della vista che si desidera indicizzare.
Per poter creare un indice per una vista, è necessario che la vista sia definita con l'opzione SCHEMABINDING. Prima di creare qualsiasi indice non cluster per una vista, è necessario creare un indice cluster univoco. Per ulteriori informazioni sulle viste indicizzate, vedere la sezione Osservazioni.
A partire da SQL Server 2016 (13.x), l'oggetto può essere una tabella archiviata con un indice columnstore cluster.
Il database SQL di Azure supporta il formato del nome in tre parti nome_database.[nome_schema].nome_oggetto quando nome_database è il database corrente oppure nome_database è tempdb
e nome_oggetto inizia con #.
Specifica le opzioni da usare quando si crea l'indice.
Specifica il riempimento dell'indice. Il valore predefinito è OFF.
In...
La percentuale di spazio disponibile specificata da fillfactor viene applicata alle pagine di livello intermedio dell'indice.
OFF o fillfactor non è specificato
Le pagine di livello intermedio vengono riempite poco al di sotto della capacità massima, in modo che lo spazio residuo sia sufficiente per almeno una riga della dimensione massima supportata dall'indice, in base al set di chiavi nelle pagine intermedie.
L'opzione PAD_INDEX
risulta utile solo quando si specifica FILLFACTOR, perché PAD_INDEX
usa la percentuale specificata in FILLFACTOR. Se la percentuale specificata in FILLFACTOR non consente l'inserimento di una riga, il motore di database sostituisce internamente tale percentuale in modo da rendere disponibile lo spazio minimo necessario. Il numero di righe di una pagina intermedia dell'indice non è mai minore di due, indipendentemente dal valore di fillfactor.
Nella sintassi compatibile con le versioni precedenti WITH PAD_INDEX
equivale a WITH PAD_INDEX = ON
.
Specifica una percentuale che indica il livello di riempimento del livello foglia di ogni pagina di indice da parte del motore di database durante la creazione o la ricompilazione dell'indice. fillfactor deve essere un valore intero compreso tra 1 e 100. I valori 0 e 100 relativi al fattore di riempimento sono equivalenti. Se fillfactor è 100, il motore di database crea indici con pagine foglia riempite fino alla capacità massima.
L'impostazione FILLFACTOR
viene applicata solo in fase di creazione o ricompilazione dell'indice. La percentuale specificata di spazio vuoto delle pagine non viene mantenuta in modo dinamico dal motore di database.
Per visualizzare l'impostazione del fattore di riempimento. usare fill_factor
in sys.indexes
.
Importante
La creazione di un indice cluster con un valore FILLFACTOR
inferiore a 100 influisce sulla quantità di spazio di archiviazione occupata dai dati perché i dati vengono ridistribuiti dal motore di database durante la creazione dell'indice cluster.
Per altre informazioni, vedere Specificare un fattore di riempimento per un indice.
Specifica se i risultati temporanei dell'ordinamento devono essere archiviati in tempdb. Il valore predefinito è OFF, tranne per Hyperscale del database SQL di Azure. Per tutte le operazioni di compilazione dell'indice in Hyperscale, SORT_IN_TEMPDB
è sempre ON, indipendentemente dall'opzione specificata, a meno che non venga usata la ricompilazione dell'indice ripristinabile.
In...
I risultati intermedi dell'ordinamento usati per la compilazione dell'indice vengono archiviati in tempdb. In questo modo si può ridurre il tempo necessario per creare un indice se tempdb si trova in un set di dischi diverso rispetto al database utente. La quantità di spazio su disco utilizzata durante la compilazione dell'indice sarà tuttavia maggiore.
OFF
I risultati intermedi dell'ordinamento vengono archiviati nello stesso database dell'indice.
Oltre allo spazio necessario nel database utente per la creazione dell'indice, in tempdb deve essere disponibile una quantità di spazio aggiuntivo pressoché equivalente per l'archiviazione dei risultati intermedi dell'ordinamento. Per altre informazioni, vedere Opzione SORT_IN_TEMPDB per gli indici.
Nella sintassi compatibile con le versioni precedenti WITH SORT_IN_TEMPDB
equivale a WITH SORT_IN_TEMPDB = ON
.
Specifica l'errore restituito quando un'operazione di inserimento tenta di inserire valori di chiave duplicati in un indice univoco. L'opzione IGNORE_DUP_KEY
viene applicata solo alle operazioni di inserimento eseguite dopo la creazione o la ricompilazione dell'indice. L'opzione non ha alcun effetto se si esegue CREATE INDEX, ALTER INDEX o UPDATE. Il valore predefinito è OFF.
In...
Viene visualizzato un messaggio di avviso quando i valori di chiave duplicati vengono inseriti in un indice univoco. Avranno esito negativo solo le righe che violano il vincolo di unicità.
OFF
Viene visualizzato un messaggio di errore quando i valori di chiave duplicati vengono inseriti in un indice univoco. Viene eseguito il rollback dell'intera operazione INSERT.
L'opzione IGNORE_DUP_KEY
non può essere impostata su ON per indici creati in una vista, indici non univoci, indici XML, indici spaziali e indici filtrati.
Per visualizzare IGNORE_DUP_KEY
, usare sys.indexes.
Nella sintassi compatibile con le versioni precedenti WITH IGNORE_DUP_KEY
equivale a WITH IGNORE_DUP_KEY = ON
.
Specifica se le statistiche di distribuzione vengono ricalcolate. Il valore predefinito è OFF.
In...
Le statistiche non aggiornate non vengono ricalcolate automaticamente.
OFF
Abilita l'aggiornamento automatico delle statistiche.
Per ripristinare l'aggiornamento automatico delle statistiche, impostare STATISTICS_NORECOMPUTE
su OFF oppure eseguire UPDATE STATISTICS
senza la clausola NORECOMPUTE
.
Importante
La disabilitazione del ricalcolo automatico delle statistiche di distribuzione può compromettere la selezione di piani di esecuzione ottimali per le query riguardanti la tabella in Query Optimizer.
Nella sintassi compatibile con le versioni precedenti WITH STATISTICS_NORECOMPUTE
equivale a WITH STATISTICS_NORECOMPUTE = ON
.
Si applica a: SQL Server, a partire da SQL Server 2014 (12.x), e database SQL di Azure
Se è specificato ON, le statistiche create sono statistiche per partizione. Quando è impostata su OFF, l'albero delle statistiche viene eliminato e SQL Server ricalcola le statistiche. Il valore predefinito è OFF.
Se le statistiche per partizione non sono supportate, l'opzione viene ignorata e viene generato un avviso. Le statistiche incrementali non sono supportate per i seguenti tipi di statistiche:
Consente di eliminare e ricompilare l'indice cluster o non cluster esistente con le specifiche colonne modificate e di mantenere lo stesso nome per l'indice. Il valore predefinito è OFF.
In...
Specifica che l'indice esistente deve essere eliminato e ricompilato e che deve avere lo stesso nome del parametro index_name.
OFF
Specifica che l'indice esistente non deve essere eliminato e ricompilato. Se il nome di indice specificato esiste già, SQL Server visualizza un messaggio di errore.
Con DROP_EXISTING
è possibile modificare:
Con DROP_EXISTING
non è possibile modificare:
Nella sintassi compatibile con le versioni precedenti WITH DROP_EXISTING
equivale a WITH DROP_EXISTING = ON
.
Specifica se le tabelle sottostanti e gli indici associati sono disponibili per le query e la modifica dei dati durante l'operazione sugli indici. Il valore predefinito è OFF.
Importante
Le operazioni online sugli indici non sono disponibili in tutte le edizioni di SQL Server. Per un elenco delle funzionalità supportate dalle varie edizioni di SQL Server, vedere Edizioni e funzionalità supportate di SQL Server 2017.
In...
I blocchi di tabella a lungo termine non vengono mantenuti per la durata dell'operazione sugli indici. Durante la fase principale dell'operazione viene mantenuto solo un blocco preventivo condiviso (IS, Intent Shared) sulla tabella di origine. in modo da consentire l'esecuzione di query o l'aggiornamento della tabella sottostante e degli indici. All'inizio dell'operazione viene mantenuto un blocco condiviso (S) sull'oggetto di origine per un periodo molto breve. Al termine dell'operazione, per un breve periodo di tempo viene acquisito un blocco condiviso (S) sull'origine, se viene creato un indice non cluster. Viene acquisito un blocco di modifica dello schema (Sch-M) quando un indice cluster viene creato o eliminato online e quando un indice cluster o non cluster viene ricompilato. L'opzione ONLINE non può essere impostata su ON quando viene creato un indice per una tabella temporanea locale.
Nota
La creazione di indici online può impostare le opzioni low_priority_lock_wait
; vedere WAIT_AT_LOW_PRIORITY con operazioni sugli indici online.
OFF
I blocchi di tabella vengono applicati per la durata dell'operazione sugli indici. Un'operazione sugli indici offline che crea, ricompila o elimina un indice cluster oppure ricompila o elimina un indice non cluster acquisisce un blocco di modifica dello schema (SCH-M) sulla tabella. Il blocco impedisce agli utenti di accedere alla tabella sottostante per la durata dell'operazione. Un'operazione sugli indici offline che crea un indice non cluster acquisisce un blocco condiviso (S) sulla tabella. Tale blocco impedisce l'aggiornamento della tabella sottostante ma consente operazioni di lettura, ad esempio l'esecuzione di istruzioni SELECT.
Per altre informazioni, vedere Perform Index Operations Online.
È possibile creare online tutti gli indici, inclusi quelli di tabelle temporanee globali, ad eccezione dei casi seguenti:
ONLINE
.Per altre informazioni, vedere Funzionamento delle operazioni sugli indici online.
Si applica a: SQL Server, a partire da SQL Server 2019 (15.x) e database SQL di Azure
Specifica se un'operazione sull'indice online è ripristinabile.
In...
L'operazione sull'indice è ripristinabile.
OFF
L'operazione sull'indice non è ripristinabile.
Si applica a: SQL Server, a partire da SQL Server 2019 (15.x) e database SQL di Azure
Indica il tempo (un valore intero specificato in minuti) di esecuzione di un'operazione sull'indice online ripristinabile prima di essere sospesa.
Importante
Per informazioni più dettagliate sulle operazioni di indice eseguibili online, vedere Linee guida per operazioni di indice online.
Nota
Le ricompilazione degli indici online ripristinabili non sono supportate per gli indici columnstore o gli indici disabilitati.
Specifica se sono consentiti blocchi di riga. Il valore predefinito è ON.
In...
I blocchi di riga sono consentiti durante l'accesso all'indice. Il motore di database determina quando usare i blocchi di riga.
OFF
I blocchi di riga non vengono utilizzati.
Specifica se sono consentiti blocchi a livello di pagina. Il valore predefinito è ON.
In...
I blocchi a livello di pagina sono consentiti durante l'accesso all'indice. Il motore di database determina quando usare i blocchi di pagina.
OFF
I blocchi a livello di pagina non vengono utilizzati.
Si applica a: SQL Server, a partire da SQL Server 2019 (15.x) e database SQL di Azure
Specifica se eseguire o meno l'ottimizzazione per la contesa di inserimento dell'ultima pagina. Il valore predefinito è OFF. Per altre informazioni, vedere le sezione Chiavi sequenziali.
Sostituisce l'opzione di configurazione max degree of parallelism per la durata dell'operazione sull'indice. Per altre informazioni, vedere Configurare l'opzione di configurazione del server max degree of parallelism. Utilizzare MAXDOP per limitare il numero di processori utilizzati durante l'esecuzione di un piano parallelo. Il valore massimo è 64 processori.
max_degree_of_parallelism può essere:
1
Disattiva la generazione di piani paralleli.
>1
Consente di limitare al valore specificato, o a un valore più basso in base al carico di lavoro corrente del sistema, il numero massimo di processori utilizzati in un'operazione parallela sugli indici.
0 (predefinito)
Utilizza il numero effettivo di processori o un numero inferiore in base al carico di lavoro corrente del sistema.
Per altre informazioni, vedere Configurazione di operazioni parallele sugli indici.
Nota
Le operazioni parallele sugli indici non sono disponibili in tutte le edizioni di SQL Server. Per un elenco delle funzionalità supportate dalle varie edizioni di SQL Server, vedere Edizioni e funzionalità supportate di SQL Server 2017.
Specifica l'opzione di compressione dei dati per l'indice, il numero di partizione o l'intervallo di partizioni specificato. Le opzioni sono le seguenti:
NONE
L'indice o le partizioni specificate non vengono compressi.
ROW
L'indice o le partizioni specificate vengono compressi utilizzando la compressione di riga.
PAGE
L'indice o le partizioni specificate vengono compressi utilizzando la compressione di pagina.
Per altre informazioni sulla compressione, vedere Compressione dei dati.
Si applica a: SQL Server 2022 (16.x) e versioni successive Database SQL di Azure e Istanza gestita di SQL di Azure
Specifica l'opzione di compressione XML per l'indice specificato che contiene una o più colonne del tipo di dati xml. Le opzioni sono le seguenti:
In...
L'indice o le partizioni specificate vengono compressi usando la compressione XML.
OFF
L'indice o le partizioni specificate non vengono compressi.
Specifica le partizioni a cui si applicano le impostazioni DATA_COMPRESSION
o XML_COMPRESSION
. Se l'indice non è partizionato, l'argomento ON PARTITIONS
genererà un errore. Se la clausola ON PARTITIONS
non viene specificata, l'opzione DATA_COMPRESSION
o XML_COMPRESSION
verrà applicata a tutte le partizioni di un indice partizionato.
<partition_number_expression>
può essere specificato nei modi seguenti:
ON PARTITIONS (2)
.ON PARTITIONS (1, 5)
.ON PARTITIONS (2, 4, 6 TO 8)
.È possibile specificare <range>
sotto forma di numeri di partizione separati dalla parola TO, ad esempio: ON PARTITIONS (6 TO 8)
.
Per impostare tipi diversi di compressione dei dati per partizioni diverse, specificare più volte l'opzione DATA_COMPRESSION
, ad esempio:
REBUILD WITH
(
DATA_COMPRESSION = NONE ON PARTITIONS (1),
DATA_COMPRESSION = ROW ON PARTITIONS (2, 4, 6 TO 8),
DATA_COMPRESSION = PAGE ON PARTITIONS (3, 5)
);
È anche possibile specificare più volte l'opzione XML_COMPRESSION
, ad esempio:
REBUILD WITH
(
XML_COMPRESSION = OFF ON PARTITIONS (1),
XML_COMPRESSION = ON ON PARTITIONS (2, 4, 6 TO 8),
XML_COMPRESSION = OFF ON PARTITIONS (3, 5)
);
L'istruzione CREATE INDEX
viene ottimizzata come qualsiasi altra query. Al fine di limitare le operazioni di I/O, è possibile che Query Processor scelga di sottoporre ad analisi un altro indice anziché eseguire un'analisi di tabella. In alcune situazioni è possibile che l'operazione di ordinamento venga eliminata. Nei computer multiprocessore l'istruzione CREATE INDEX
può usare più processori per eseguire le operazioni di analisi e ordinamento associate alla creazione dell'indice, in modo identico alle altre query. Per altre informazioni, vedere Configurazione di operazioni parallele sugli indici.
L'operazione CREATE INDEX
può essere sottoposta a registrazione minima se viene usato il modello di recupero del database con registrazione minima o con registrazione minima delle operazioni bulk.
È possibile creare indici per una tabella temporanea. Quando si elimina la tabella o termina la sessione, vengono eliminati anche gli indici associati.
Un indice cluster può essere compilato in base a una variabile di tabella quando viene creata una chiave primaria. Quando la query viene completata o la sessione termina, l'indice viene eliminato.
Gli indici supportano proprietà estese.
CREATE INDEX
non è supportato in Microsoft Fabric.
La creazione di un indice cluster per una tabella (heap) e l'eliminazione e la ricreazione di un indice cluster esistente richiedono la disponibilità di un'area di lavoro aggiuntiva nel database per contenere l'ordinamento dei dati e una copia temporanea della tabella originale o dei dati dell'indice cluster esistenti. Per altre informazioni sugli indici cluster, vedere Creare indici cluster e Architettura e guida per la progettazione degli indici di SQL Server.
A partire da SQL Server 2016 (13.x) e database SQL di Azure è possibile creare un indice non cluster per una tabella archiviata come indice columnstore cluster. Se si crea prima un indice non cluster per una tabella archiviata come heap o indice cluster, l'indice verrà conservato se in un secondo tempo la tabella viene convertita in un indice columnstore cluster. Non è inoltre necessario eliminare l'indice non cluster quando si ricompila l'indice columnstore cluster.
Limitazioni e restrizioni:
FILESTREAM_ON
non è valida quando si crea un indice non cluster per una tabella archiviata come indice columnstore cluster.Quando esiste un indice univoco, ogni volta che vengono aggiunti nuovi dati tramite un'operazione di inserimento, il motore di database verifica l'eventuale presenza di valori duplicati. Le operazioni di inserimento che generano valori di chiave duplicati vengono sottoposte a rollback e nel motore di database viene visualizzato un messaggio di errore, anche nel caso in cui l'operazione di inserimento interessi più righe e crei un solo valore duplicato. Se si tenta di immettere dati per i quali è disponibile un indice univoco e la clausola IGNORE_DUP_KEY
è impostata su ON, l'operazione ha esito negativo solo per le righe che violano l'indice UNIQUE.
Gli indici partizionati vengono creati e gestiti in modo analogo alle tabelle partizionate, ma, come gli indici normali, vengono trattati come oggetti di database separati. È possibile creare un indice partizionato per una tabella non partizionata, nonché creare un indice non partizionato per una tabella partizionata.
Se si crea un indice per una tabella partizionata senza specificare un filegroup in cui inserirlo, l'indice verrà partizionato in modo identico alla tabella sottostante, in quanto per impostazione predefinita gli indici vengono inseriti negli stessi filegroup delle tabelle sottostanti e, nel caso di una tabella partizionata, nello stesso schema di partizione con colonne di partizionamento identiche. Se usa lo stesso schema di partizione e la stessa colonna di partizionamento della tabella, l'indice viene allineato alla tabella.
Avviso
La creazione e la ricompilazione di indici non allineati per una tabella con oltre 1.000 partizioni sono possibili, ma non supportate. Questo tipo di operazioni può causare riduzioni delle prestazioni e un eccessivo consumo della memoria. Quando il numero di partizioni supera 1.000, si consiglia di utilizzare solo indici allineati.
Quando si partiziona un indice cluster non univoco, per impostazione predefinita nel motore di database vengono aggiunte tutte le colonne di partizionamento all'elenco di chiavi di indice cluster, se non sono già presenti.
È possibile creare viste indicizzate per tabelle partizionate in modo analogo agli indici delle tabelle. Per altre informazioni sugli indici partizionati, vedere Tabelle e indici partizionati e Architettura e guida per la progettazione degli indici di SQL Server.
In SQL Server le statistiche non vengono create analizzando tutte le righe nella tabella se viene creato o ricompilato un indice partizionato. Query Optimizer utilizza invece l'algoritmo di campionamento predefinito per generare statistiche. Per ottenere statistiche sugli indici partizionati analizzando tutte le righe nella tabella, usare CREATE STATISTICS
o UPDATE STATISTICS
con la clausola FULLSCAN
.
Un indice filtrato è un indice non cluster ottimizzato, adatto per le query tramite cui viene selezionata una piccola percentuale di righe da una tabella. Utilizza un predicato del filtro per indicizzare una parte dei dati di una tabella. Un indice filtrato progettato correttamente consente di migliorare le prestazioni di esecuzione delle query e di ridurre i costi di archiviazione e di manutenzione.
Le opzioni SET nella colonna Valore obbligatorio sono richieste ogni volta che si verifica una qualsiasi delle condizioni seguenti:
Viene creato un indice filtrato.
I dati di un indice filtrato vengono modificati tramite un'operazione INSERT, UPDATE, DELETE o MERGE.
L'indice filtrato viene usato da Query Optimizer per generare il piano di query.
Opzioni SET | Valore obbligatorio | Valore server predefinito | Predefiniti OLE DB e ODBC predefinito |
Predefiniti DB-Library predefinito |
---|---|---|---|---|
ANSI_NULLS | In... | In... | In... | OFF |
ANSI_PADDING | In... | In... | In... | OFF |
ANSI_WARNINGS* | In... | In... | In... | OFF |
ARITHABORT | In... | In... | OFF | OFF |
CONCAT_NULL_YIELDS_NULL | In... | In... | In... | OFF |
NUMERIC_ROUNDABORT | OFF | OFF | OFF | OFF |
QUOTED_IDENTIFIER | In... | In... | In... | OFF |
Se le opzioni SET non sono corrette, possono verificarsi le condizioni seguenti:
Per altre informazioni sugli indici filtrati, vedere Creare indici filtrati e Architettura e guida per la progettazione degli indici di SQL Server.
Per informazioni sugli indici spaziali, vedere CREATE SPATIAL INDEX e Panoramica degli indici spaziali.
Per informazioni sugli indici XML, vedere CREATE XML INDEX e Indici XML (SQL Server).
La dimensione massima per una chiave di indice è 900 byte per un indice cluster e 1700 byte per un indice non cluster. Prima di database SQL e SQL Server 2016 (13.x) il limite era sempre 900 byte. È possibile creare indici su colonne varchar che superano il limite di byte se i dati esistenti nelle colonne non superano tale limite quando l'indice viene creato. Le successive operazioni di inserimento o aggiornamento nelle colonne che determinano l'aumento della dimensione totale oltre il limite avranno tuttavia esito negativo. La chiave di indice di un indice cluster non può contenere colonne di tipo varchar con dati esistenti nell'unità di allocazione ROW_OVERFLOW_DATA. Se viene creato un indice cluster in una colonna varchar e i dati esistenti si trovano nell'unità di allocazione IN_ROW_DATA, le azioni di inserimento o aggiornamento successive eseguite nella colonna che comporterebbero lo spostamento dei dati all'esterno delle righe avranno esito negativo.
Negli indici non cluster possono essere incluse colonne non chiave nel relativo livello foglia. Queste colonne non vengono considerate dal motore di database durante il calcolo della dimensione della chiave di indice. Per altre informazioni, vedere Creare indici con colonne incluse e Architettura e guida per la progettazione degli indici di SQL Server.
Nota
Quando le tabelle vengono partizionate, le colonne della chiave di partizionamento vengono aggiunte all'indice dal motore di database, se non sono già presenti in un indice cluster non univoco. Le dimensioni combinate delle colonne indicizzate, senza le colonne incluse, più tutte le colonne di partizionamento aggiunte non possono superare 1800 byte in un indice cluster non univoco.
Gli indici possono essere creati su colonne calcolate. Per le colonne calcolate è inoltre possibile impostare la proprietà PERSISTED. Questo significa che il motore di database archivia i valori calcolati nella tabella e li aggiorna quando vengono aggiornate altre colonne da cui dipende la colonna calcolata. Il motore di database usa questi valori persistenti quando crea un indice sulla colonna e quando viene fatto riferimento all'indice all'interno di una query.
Per indicizzare una colonna calcolata, è necessario che tale colonna sia deterministica e precisa. La proprietà PERSISTED consente tuttavia di espandere i tipi di colonne calcolate indicizzabili, includendo i tipi seguenti:
Le colonne calcolate persistenti richiedono l'impostazione delle seguenti opzioni SET come mostrato nella sezione precedente Opzioni SET necessarie per gli indici filtrati.
Il vincolo UNIQUE o PRIMARY KEY può includere una colonna calcolata a condizione che vengano soddisfatte tutte le condizioni per l'indicizzazione. In particolare, la colonna calcolata deve essere deterministica e precisa oppure deterministica e persistente. Per altre informazioni sul determinismo, vedere Funzioni deterministiche e non deterministiche.
Le colonne calcolate derivate dai tipi di dati image, ntext, text, varchar(max), nvarchar(max), varbinary(max) e xml possono essere indicizzate come colonne chiave o colonne non chiave incluse purché il tipo di dati della colonna calcolata sia consentito come colonna chiave o colonna non chiave dell'indice. Ad esempio, non è possibile creare un indice XML primario per una colonna xml calcolata. Se la dimensione della chiave di indice supera i 900 byte, viene visualizzato un messaggio di avviso.
La creazione di un indice su una colonna calcolata può impedire l'esecuzione di un'operazione di inserimento o di aggiornamento che in precedenza veniva eseguita correttamente. Questo problema si può verificare quando la colonna calcolata genera un errore aritmetico. Nella tabella seguente, ad esempio, nonostante la colonna calcolata c
generi un errore aritmetico, l'istruzione INSERT viene eseguita correttamente.
CREATE TABLE t1 (a INT, b INT, c AS a/b);
INSERT INTO t1 VALUES (1, 0);
Se invece, dopo la creazione della tabella, viene creato un indice sulla colonna calcolata c
, la stessa istruzione INSERT
avrà esito negativo.
CREATE TABLE t1 (a INT, b INT, c AS a/b);
CREATE UNIQUE CLUSTERED INDEX Idx1 ON t1(c);
INSERT INTO t1 VALUES (1, 0);
Per altre informazioni, vedere Indici per le colonne calcolate.
È possibile aggiungere colonne non chiave, o incluse, al livello foglia di un indice non cluster per migliorare le prestazioni di esecuzione delle query tramite la copertura della query. Questo significa che tutte le colonne a cui la query fa riferimento sono incluse nell'indice come colonne chiave o non chiave. In questo modo, per individuare tutte le informazioni necessarie, in Query Optimizer verrà eseguita un'analisi dell'indice, senza necessità di accedere ai dati della tabella o dell'indice cluster. Per altre informazioni, vedere Creare indici con colonne incluse e Architettura e guida per la progettazione degli indici di SQL Server.
In SQL Server 2005 (9.x) sono state introdotte nuove opzioni per gli indici ed è stata modificata la modalità di impostazione di tali opzioni. Nella sintassi compatibile con le versioni precedenti WITH option_name
equivale a WITH (option_name = ON)
. Quando si impostano opzioni per gli indici, è necessario rispettare le regole seguenti:
WITH (<option_name> = <ON | OFF>)
.WITH (DROP_EXISTING, ONLINE = ON)
, l'istruzione avrà esito negativo.WITH (<option_name> = <ON | OFF>)
.È possibile usare la clausola DROP_EXISTING
per ricompilare l'indice, aggiungere o eliminare colonne, modificare opzioni, modificare il tipo di ordinamento delle colonne oppure cambiare lo schema di partizione o il filegroup.
Se l'indice applica un vincolo PRIMARY KEY o UNIQUE e la definizione dell'indice non viene modificata in alcun modo, l'indice verrà eliminato e ricreato mantenendo il vincolo esistente. Se invece la definizione dell'indice viene modificata, l'istruzione avrà esito negativo. Per modificare la definizione di un vincolo PRIMARY KEY o UNIQUE, eliminare il vincolo e aggiungere un vincolo con la nuova definizione.
DROP_EXISTING
consente un miglioramento delle prestazioni quando viene creato un indice cluster, con un set di chiavi identico oppure diverso, per una tabella che include anche indici non cluster.
DROP_EXISTING
sostituisce l'esecuzione di un'istruzione DROP INDEX
sull'indice cluster precedente e quindi di un'istruzione CREATE INDEX
per il nuovo indice cluster. Gli indici non cluster vengono ricompilati una sola volta e poi solo in caso di modifica della relativa definizione. La clausola DROP_EXISTING
non ricompila gli indici non cluster quando la definizione dell'indice contiene gli stessi valori dell'indice originale relativi al nome di indice, alle colonne chiave e di partizione, all'attributo di univocità e al tipo di ordinamento.
Indipendentemente dal fatto che gli indici non cluster vengano ricompilati o meno, rimangono sempre nei filegroup o negli schemi di partizione originali e utilizzano le funzioni di partizione originali. Se un indice cluster viene ricompilato in un filegroup o in uno schema di partizione diverso, gli indici non cluster non vengono spostati in funzione della nuova posizione dell'indice cluster. Pertanto, anche gli indici non cluster in precedenza allineati con l'indice cluster potrebbero non essere più allineati. Per altre informazioni sull'allineamento degli indici partizionati, vedere Tabelle e indici partizionati.
La clausola DROP_EXISTING
non ripete l'ordinamento dei dati se vengono usate le stesse colonne chiave indice nello stesso ordine e con lo stesso tipo di ordinamento crescente o decrescente, a meno che nell'istruzione dell'indice non venga specificato un indice non cluster e l'opzione ONLINE sia impostata su OFF. Se l'indice cluster è disabilitato, l'operazione CREATE INDEX WITH DROP_EXISTING
deve essere eseguita con l'opzione ONLINE impostata su OFF. Se un indice non cluster è disabilitato e non è associato a un indice cluster disabilitato, l'operazione CREATE INDEX WITH DROP_EXISTING
può essere eseguita con l'opzione ONLINE impostata su OFF o ON.
Nota
Quando vengono eliminati o ricompilati indici con un numero di extent pari o superiore a 128, tramite il motore di database vengono posticipate le effettive deallocazioni delle pagine e i blocchi associati fino al termine del commit della transazione.
Per l'esecuzione di operazioni sugli indici online, è necessario attenersi alle indicazioni seguenti:
low_priority_lock_wait
consente di definire il comportamento dell'operazione sull'indice quando questa è bloccata tramite il blocco SCH-M.Per altre informazioni, vedere Perform Index Operations Online.
Sono necessarie le risorse seguenti per un'operazione di creazione dell'indice online ripristinabile:
Le funzionalità seguenti sono disabilitate per le operazioni di creazione dell'indice ripristinabili:
Quando un'operazione di creazione dell'indice online ripristinabile viene sospesa, il valore iniziale di MAXDOP non può essere modificato
Creare un indice che contenga:
Si applica a: SQL Server, a partire da SQL Server 2019 (15.x) e database SQL di Azure
Per l'esecuzione di operazioni sull'indice ripristinabili, è necessario attenersi alle indicazioni seguenti:
RESUMABLE = ON
.RESUMABLE = ON
sia specificata in modo esplicito.MAX_DURATION
è supportata solo per l'opzione RESUMABLE = ON
.MAX_DURATION
per RESUMABLE specifica l'intervallo di tempo per la compilazione di un indice. Trascorso questo tempo, la compilazione dell'indice viene sospesa oppure viene completata. È l'utente a decidere quando riprendere la compilazione di un indice che è stata sospesa. Il valore espresso in minuti in time per MAX_DURATION
deve essere maggiore di 0 e minore o uguale a una settimana (7 * 24 * 60 = 10.080 minuti). Una sospensione prolungata di un'operazione sull'indice può compromettere le prestazioni DML su una tabella specifica, nonché la capacità del disco del database poiché entrambi gli indici, quello originale e quello appena creato, richiedono spazio su disco e devono essere aggiornati durante le operazioni DML. Se l'opzione MAX_DURATION
viene omessa, l'operazione sull'indice continuerà fino al suo completamento o fino a quando non si verificherà un errore.KILL <session_id>
. Quando il comando viene sospeso, è possibile riprenderlo usando il comando ALTER INDEX.CREATE INDEX
originale per l'indice ripristinabile, un'operazione di creazione indice sospesa riprende automaticamente.SORT_IN_TEMPDB = ON
non è supportata per l'indice ripristinabile.RESUMABLE = ON
non può essere eseguito all'interno di una transazione esplicita (non può far parte del blocco begin TRAN ... COMMIT
).Nota
Il comando DDL viene eseguito fin tanto che è completato, sospeso o non riuscito. Nel caso in cui il comando sia sospeso, verrà generato un errore a indicare che l'operazione è stata sospesa e che la creazione dell'indice non è stata completata. Altre informazioni sullo stato corrente dell'indice sono disponibili in sys.index_resumable_operations. Come in precedenza, in caso di errore verrà generato un errore.
Per indicare che la creazione di un indice viene eseguita come operazione ripristinabile e per verificarne lo stato di esecuzione corrente, vedere index_resumable_operations.
Si applica a: questa sintassi per CREATE INDEX
attualmente si applica solo a SQL Server 2022 (16.x), database SQL di Azure e Istanza gestita di SQL di Azure. Per ALTER INDEX
, questa sintassi si applica a SQL Server, a partire da SQL Server 2014 (12.x) e database SQL di Azure. Per altre informazioni, vedere ALTER INDEX.
La sintassi low_priority_lock_wait
consente di specificare il comportamento WAIT_AT_LOW_PRIORITY
. È possibile usare WAIT_AT_LOW_PRIORITY
solo con ONLINE=ON
.
L'opzione WAIT_AT_LOW_PRIORITY
consente agli amministratori di database di gestire i blocchi Sch-S e Sch-M necessari per la creazione degli indici online, nonché di selezionare una tra tre opzioni. In tutti e tre i casi, se durante il tempo di attesa MAX_DURATION = n [minutes]
non sono presenti attività di blocco, la ricompilazione dell'indice online viene eseguita immediatamente senza attendere il completamento dell'istruzione DDL.
WAIT_AT_LOW_PRIORITY
indica che l'operazione di creazione online rimarrà in attesa di blocchi con priorità bassa, consentendo la continuazione delle altre operazioni mentre quella di compilazione dell'indice online è in attesa. L'omissione dell'opzione WAIT AT LOW PRIORITY
equivale a WAIT_AT_LOW_PRIORITY (MAX_DURATION = 0 minutes, ABORT_AFTER_WAIT = NONE)
.
MAX_DURATION = time [MINUTES]
Il tempo di attesa (valore intero specificato in minuti) con priorità bassa dei blocchi di creazione dell'indice online durante l'esecuzione del comando DDL. Se l'operazione viene bloccata per il tempo MAX_DURATION
, verrà eseguita l'azione ABORT_AFTER_WAIT
specificata.
MAX_DURATION
il tempo è sempre espresso in minuti e la parola MINUTES può essere omessa.
ABORT_AFTER_WAIT = [NONE | SELF | BLOCKERS } ]
NONE: continua ad attendere il blocco con priorità normale (regolare).
L'opzione SELF esce dall'operazione DDL di creazione dell'indice online attualmente in esecuzione senza eseguire alcuna azione. L'opzione SELF non può essere usata con MAX_DURATION
con valore 0.
BLOCKERS termina tutte le transazioni utente che bloccano l'operazione DDL di ricompilazione dell'indice online in modo da poter continuare l'operazione. L'opzione BLOCKERS richiede che l'account di accesso disponga ALTER ANY CONNECTION
dell'autorizzazione.
Se ALLOW_ROW_LOCKS = ON
e ALLOW_PAGE_LOCK = ON
, i blocchi a livello di riga, pagina e tabella sono consentiti quando si accede all'indice. Il motore di database sceglie il blocco appropriato e può eseguire un'escalation del blocco da un blocco di riga o di pagina a un blocco di tabella.
Se ALLOW_ROW_LOCKS = OFF
e ALLOW_PAGE_LOCK = OFF
, è consentito solo un blocco a livello di tabella quando si accede all'indice.
Si applica a: SQL Server, a partire da SQL Server 2019 (15.x) e database SQL di Azure
La contesa di inserimento dell'ultima pagina è un problema di prestazioni comune che si verifica quando un numero elevato di thread simultanei tenta di inserire righe in un indice con una chiave sequenziale. Un indice viene considerato sequenziale quando la colonna chiave iniziale contiene valori che sono sempre crescenti o decrescenti, ad esempio una colonna Identity o una data che per impostazione predefinita è la data/ora corrente. Poiché le chiavi da inserire sono sequenziali, tutte le nuove righe verranno inserite alla fine della struttura dell'indice (in altre parole, nella stessa pagina). Questo comporta una contesa per la pagina in memoria, che si manifesta come diversi thread in attesa di PAGELATCH_EX per la pagina in questione.
Abilitando l'opzione per gli indici OPTIMIZE_FOR_SEQUENTIAL_KEY
viene attivata un'ottimizzazione all'interno del motore di database che contribuisce a migliorare la velocità effettiva per gli inserimenti nell'indice con un elevato grado di concorrenza. Questa opzione è destinata agli indici che dispongono di una chiave sequenziale e che pertanto sono soggetti a contesa di inserimento dell'ultima pagina, ma può essere utile anche per gli indici contenenti aree sensibili in altre aree della struttura dell'indice albero B.
Nota
Nella documentazione viene usato in modo generico il termine albero B in riferimento agli indici. Negli indici rowstore, il motore di database implementa un albero B+. Ciò non si applica a indici columnstore o a indici in tabelle ottimizzate per la memoria. Per altre informazioni, vedere Architettura e guida per la progettazione degli indici SQL Server e Azure SQL.
Per ottenere informazioni sugli indici, è possibile utilizzare viste del catalogo, funzioni di sistema e stored procedure di sistema.
La compressione dei dati è descritta nell'argomento Compressione dei dati. Di seguito sono illustrati i punti principali da considerare:
Agli indici partizionati vengono applicate le restrizioni seguenti:
ALTER INDEX <index> ... REBUILD PARTITION ...
ricompila la partizione specificata dell'indice.ALTER INDEX <index> ... REBUILD WITH ...
ricompila tutte le partizioni dell'indice.Per valutare il modo in cui la modifica dello stato di compressione influirà su una tabella, un indice o una partizione, usare la stored procedure sp_estimate_data_compression_savings .
Si applica a: SQL Server 2022 (16.x) e versioni successive Database SQL di Azure e Istanza gestita di SQL di Azure
Molte delle stesse considerazioni relative alla compressione dei dati si applicano anche alla compressione XML. È consigliabile tenere presenti le considerazioni seguenti:
xml_compression
della vista del catalogo sys.partitions
.Richiede l'autorizzazione ALTER
sulla vista o sulla tabella o l'appartenenza ai ruoli predefiniti del database db_ddladmin
.
In Azure Synapse Analytics e nella piattaforma di strumenti analitici non è possibile creare:
Per visualizzare informazioni sugli indici esistenti, è possibile eseguire una query sulla vista del catalogo sys.indexes.
Il database SQL non supporta le opzioni per filegroup e filestream.
Negli esempi che seguono viene creato un indice non cluster per la colonna VendorID
della tabella Purchasing.ProductVendor
.
CREATE INDEX IX_VendorID ON ProductVendor (VendorID);
CREATE INDEX IX_VendorID ON dbo.ProductVendor (VendorID DESC, Name ASC, Address DESC);
CREATE INDEX IX_VendorID ON Purchasing..ProductVendor (VendorID);
Nell'esempio seguente viene creato un indice composto non cluster per le colonne SalesQuota
e SalesYTD
della tabella Sales.SalesPerson
.
CREATE NONCLUSTERED INDEX IX_SalesPerson_SalesQuota_SalesYTD ON Sales.SalesPerson (SalesQuota, SalesYTD);
Nell'esempio seguente viene creato un indice cluster per la colonna VendorID
della tabella ProductVendor
nel database Purchasing
.
CREATE CLUSTERED INDEX IX_ProductVendor_VendorID ON Purchasing..ProductVendor (VendorID);
Nell'esempio seguente viene creato l'indice IX_FF con due colonne della tabella dbo.FactFinance. L'istruzione successiva ricompila l'indice con un'ulteriore colonna e mantiene il nome esistente.
CREATE INDEX IX_FF ON dbo.FactFinance (FinanceKey ASC, DateKey ASC);
-- Rebuild and add the OrganizationKey
CREATE INDEX IX_FF ON dbo.FactFinance (FinanceKey, DateKey, OrganizationKey DESC)
WITH (DROP_EXISTING = ON);
Nell'esempio seguente viene creato un indice non cluster univoco sulla colonna Name
della tabella Production.UnitMeasure
nel database AdventureWorks2022
. Questo indice impone l'univocità dei dati inseriti nella colonna Name
.
CREATE UNIQUE INDEX AK_UnitMeasure_Name
ON Production.UnitMeasure(Name);
Nella query seguente viene verificato il vincolo di univocità mediante un tentativo di inserimento di una riga con lo stesso valore di una riga esistente.
-- Verify the existing value.
SELECT Name FROM Production.UnitMeasure WHERE Name = N'Ounces';
GO
INSERT INTO Production.UnitMeasure (UnitMeasureCode, Name, ModifiedDate)
VALUES ('OC', 'Ounces', GETDATE());
Il messaggio di errore risultante è:
Server: Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'UnitMeasure' with unique index 'AK_UnitMeasure_Name'. The statement has been terminated.
Nell'esempio seguente viene illustrato l'effetto dell'opzione IGNORE_DUP_KEY
tramite l'inserimento di più righe in una tabella temporanea prima con questa opzione impostata su ON
e quindi con questa opzione impostata su OFF
. Nella tabella #Test
viene inserita una singola riga che genererà intenzionalmente un valore duplicato quando verrà eseguita la seconda istruzione INSERT
su più righe. Il calcolo delle righe della tabella restituisce il numero di righe inserite.
CREATE TABLE #Test (C1 NVARCHAR(10), C2 NVARCHAR(50), C3 DATETIME);
GO
CREATE UNIQUE INDEX AK_Index ON #Test (C2)
WITH (IGNORE_DUP_KEY = ON);
GO
INSERT INTO #Test VALUES (N'OC', N'Ounces', GETDATE());
INSERT INTO #Test SELECT * FROM Production.UnitMeasure;
GO
SELECT COUNT(*) AS [Number of rows] FROM #Test;
GO
DROP TABLE #Test;
GO
Di seguito sono riportati i risultati della seconda istruzione INSERT
.
Server: Msg 3604, Level 16, State 1, Line 5 Duplicate key was ignored.
Number of rows
--------------
38
Si noti che le righe della tabella Production.UnitMeasure
che non violano il vincolo di univocità sono state inserite correttamente. Nonostante sia stato visualizzato un messaggio di avviso e sia stata ignorata la riga duplicata, non è stato eseguito un rollback dell'intera transazione.
A questo punto vengono eseguite nuovamente le stesse istruzioni, ma l'opzione IGNORE_DUP_KEY
è impostata su OFF
.
CREATE TABLE #Test (C1 NVARCHAR(10), C2 NVARCHAR(50), C3 DATETIME);
GO
CREATE UNIQUE INDEX AK_Index ON #Test (C2)
WITH (IGNORE_DUP_KEY = OFF);
GO
INSERT INTO #Test VALUES (N'OC', N'Ounces', GETDATE());
INSERT INTO #Test SELECT * FROM Production.UnitMeasure;
GO
SELECT COUNT(*) AS [Number of rows] FROM #Test;
GO
DROP TABLE #Test;
GO
Di seguito sono riportati i risultati della seconda istruzione INSERT
.
Server: Msg 2601, Level 14, State 1, Line 5
Cannot insert duplicate key row in object '#Test' with unique index
'AK_Index'. The statement has been terminated.
Number of rows
--------------
1
Si noti che nella tabella non è stata inserita alcuna riga della tabella Production.UnitMeasure
, sebbene la violazione del vincolo dell'indice UNIQUE
fosse determinata da una sola riga.
Nell'esempio seguente viene eliminato e ricreato un indice esistente nella colonna ProductID
della tabella Production.WorkOrder
nel database AdventureWorks2022
utilizzando l'opzione DROP_EXISTING
. Vengono inoltre impostate le opzioni FILLFACTOR
e PAD_INDEX
.
CREATE NONCLUSTERED INDEX IX_WorkOrder_ProductID
ON Production.WorkOrder(ProductID)
WITH (FILLFACTOR = 80,
PAD_INDEX = ON,
DROP_EXISTING = ON);
GO
Nell'esempio seguente vengono creati una vista e un indice per tale vista, quindi vengono eseguite due query in cui viene usata la vista indicizzata.
-- Set the options to support indexed views
SET NUMERIC_ROUNDABORT OFF;
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT,
QUOTED_IDENTIFIER, ANSI_NULLS ON;
GO
-- Create view with schemabinding
IF OBJECT_ID ('Sales.vOrders', 'view') IS NOT NULL
DROP VIEW Sales.vOrders;
GO
CREATE VIEW Sales.vOrders
WITH SCHEMABINDING
AS
SELECT SUM(UnitPrice * OrderQty * (1.00 - UnitPriceDiscount)) AS Revenue,
OrderDate, ProductID, COUNT_BIG(*) AS COUNT
FROM Sales.SalesOrderDetail AS od, Sales.SalesOrderHeader AS o
WHERE od.SalesOrderID = o.SalesOrderID
GROUP BY OrderDate, ProductID;
GO
-- Create an index on the view
CREATE UNIQUE CLUSTERED INDEX IDX_V1
ON Sales.vOrders (OrderDate, ProductID);
GO
-- This query can use the indexed view even though the view is
-- not specified in the FROM clause.
SELECT SUM(UnitPrice * OrderQty * (1.00 - UnitPriceDiscount)) AS Rev,
OrderDate, ProductID
FROM Sales.SalesOrderDetail AS od
JOIN Sales.SalesOrderHeader AS o ON od.SalesOrderID = o.SalesOrderID
AND ProductID BETWEEN 700 AND 800
AND OrderDate >= CONVERT(DATETIME, '05/01/2002', 101)
GROUP BY OrderDate, ProductID
ORDER BY Rev DESC;
GO
-- This query can use the above indexed view
SELECT OrderDate, SUM(UnitPrice * OrderQty * (1.00 - UnitPriceDiscount)) AS Rev
FROM Sales.SalesOrderDetail AS od
JOIN Sales.SalesOrderHeader AS o ON od.SalesOrderID = o.SalesOrderID
AND DATEPART(mm, OrderDate) = 3
AND DATEPART(yy, OrderDate) = 2002
GROUP BY OrderDate
ORDER BY OrderDate ASC;
GO
Nell'esempio seguente viene creato un indice non cluster con una colonna chiave (PostalCode
) e quattro colonne non chiave (AddressLine1
, AddressLine2
, City
, StateProvinceID
), quindi viene eseguita una query che utilizza tale indice. Per visualizzare l'indice selezionato da Query Optimizer, nel menu Query di SQL Server Management Studio selezionare Visualizza piano di esecuzione effettivo prima di eseguire la query.
CREATE NONCLUSTERED INDEX IX_Address_PostalCode
ON Person.Address (PostalCode)
INCLUDE (AddressLine1, AddressLine2, City, StateProvinceID);
GO
SELECT AddressLine1, AddressLine2, City, StateProvinceID, PostalCode
FROM Person.Address
WHERE PostalCode BETWEEN N'98000' and N'99999';
GO
Nell'esempio seguente viene creato un indice partizionato non cluster nello schema di partizione esistente TransactionsPS1
nel database AdventureWorks2022
. In questo esempio si presuppone che sia stato installato l'esempio di indice partizionato.
CREATE NONCLUSTERED INDEX IX_TransactionHistory_ReferenceOrderID
ON Production.TransactionHistory (ReferenceOrderID)
ON TransactionsPS1 (TransactionDate);
GO
Nell'esempio seguente viene creato un indice filtrato nella tabella Production.BillOfMaterials nel database AdventureWorks2022
. Il predicato del filtro può includere colonne che non sono colonne chiave nell'indice filtrato. Il predicato in questo esempio consente di selezionare solo le righe in cui EndDate non ha un valore NULL.
CREATE NONCLUSTERED INDEX "FIBillOfMaterialsWithEndDate"
ON Production.BillOfMaterials (ComponentID, StartDate)
WHERE EndDate IS NOT NULL;
Nell'esempio seguente viene creato un indice in una tabella non partizionata utilizzando la compressione di riga.
CREATE NONCLUSTERED INDEX IX_INDEX_1
ON T1 (C2)
WITH (DATA_COMPRESSION = ROW);
GO
Nell'esempio seguente viene creato un indice in una tabella partizionata utilizzando la compressione di riga in tutte le partizioni dell'indice.
CREATE CLUSTERED INDEX IX_PartTab2Col1
ON PartitionTable1 (Col1)
WITH (DATA_COMPRESSION = ROW);
GO
Nell'esempio seguente viene creato un indice in una tabella partizionata utilizzando la compressione di pagina nella partizione 1
dell'indice e la compressione di riga nelle partizioni da 2
a 4
dell'indice.
CREATE CLUSTERED INDEX IX_PartTab2Col1
ON PartitionTable1 (Col1)
WITH (
DATA_COMPRESSION = PAGE ON PARTITIONS(1),
DATA_COMPRESSION = ROW ON PARTITIONS (2 TO 4)
);
GO
Si applica a: SQL Server 2022 (16.x) e versioni successive Database SQL di Azure e Istanza gestita di SQL di Azure
Nell'esempio seguente viene creato un indice in una tabella non partizionata usando la compressione XML. Almeno una colonna nell'indice deve essere il tipo di dati xml.
CREATE NONCLUSTERED INDEX IX_INDEX_1
ON T1 (C2)
WITH (XML_COMPRESSION = ON);
GO
Nell'esempio seguente viene creato un indice in una tabella partizionata usando la compressione XML in tutte le partizioni dell'indice.
CREATE CLUSTERED INDEX IX_PartTab2Col1
ON PartitionTable1 (Col1)
WITH (XML_COMPRESSION = ON);
GO
Si applica a: SQL Server, a partire da SQL Server 2019 (15.x) e database SQL di Azure
-- Execute a resumable online index create statement with MAXDOP=1
CREATE INDEX test_idx1 ON test_table (col1) WITH (ONLINE = ON, MAXDOP = 1, RESUMABLE = ON);
-- Executing the same command again (see above) after an index operation was paused, resumes automatically the index create operation.
-- Execute a resumable online index creates operation with MAX_DURATION set to 240 minutes. After the time expires, the resumable index create operation is paused.
CREATE INDEX test_idx2 ON test_table (col2) WITH (ONLINE = ON, RESUMABLE = ON, MAX_DURATION = 240);
-- Pause a running resumable online index creation
ALTER INDEX test_idx1 ON test_table PAUSE;
ALTER INDEX test_idx2 ON test_table PAUSE;
-- Resume a paused online index creation
ALTER INDEX test_idx1 ON test_table RESUME;
ALTER INDEX test_idx2 ON test_table RESUME;
-- Abort resumable index create operation which is running or paused
ALTER INDEX test_idx1 ON test_table ABORT;
ALTER INDEX test_idx2 ON test_table ABORT;
Gli esempi seguenti usano l'opzione WAIT_AT_LOW_PRIORITY
per specificare diverse strategie per la gestione del blocco.
--Kill this session after waiting 5 minutes
CREATE CLUSTERED INDEX idx_1 ON dbo.T2 (a) WITH (ONLINE = ON (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 5 MINUTES, ABORT_AFTER_WAIT = SELF)));
GO
--Kill blocker sessions
CREATE CLUSTERED INDEX idx_1 ON dbo.T2 (a) WITH (ONLINE = ON (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 5 MINUTES, ABORT_AFTER_WAIT = BLOCKERS)));
GO
L'esempio seguente usa l'opzione RESUMABLE
e specifica due valori MAX_DURATION
, il primo applicabile all'opzione ABORT_AFTER_WAIT
, il secondo all'opzione RESUMABLE
.
--With resumable option; default locking behavior
CREATE CLUSTERED INDEX idx_1 ON dbo.T2 (a) WITH (ONLINE = ON (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 5 MINUTES, ABORT_AFTER_WAIT = NONE)), RESUMABLE = ON, MAX_DURATION = 240 MINUTES);
Creare, riprendere, sospendere e interrompere operazioni sull'indice ripristinabili
Si applica a: SQL Server, a partire da SQL Server 2019 (15.x) e database SQL di Azure
-- Execute a resumable online index create statement with MAXDOP=1
CREATE INDEX test_idx ON test_table WITH (ONLINE = ON, MAXDOP = 1, RESUMABLE = ON);
-- Executing the same command again (see above) after an index operation was paused, resumes automatically the index create operation.
-- Execute a resumable online index creates operation with MAX_DURATION set to 240 minutes. After the time expires, the resumable index create operation is paused.
CREATE INDEX test_idx ON test_table WITH (ONLINE = ON, RESUMABLE = ON, MAX_DURATION = 240);
-- Pause a running resumable online index creation
ALTER INDEX test_idx ON test_table PAUSE;
-- Resume a paused online index creation
ALTER INDEX test_idx ON test_table RESUME;
-- Abort resumable index create operation which is running or paused
ALTER INDEX test_idx ON test_table ABORT;
Nell'esempio seguente viene creato un indice non cluster nella colonna VendorID
della tabella ProductVendor
.
CREATE INDEX IX_ProductVendor_VendorID
ON ProductVendor (VendorID);
Nell'esempio seguente viene creato un indice non cluster nella colonna VendorID
della tabella ProductVendor
nel database Purchasing
.
CREATE CLUSTERED INDEX IX_ProductVendor_VendorID
ON Purchasing..ProductVendor (VendorID);
L'esempio seguente crea un indice cluster ordinato nelle colonne c1
e c2
della tabella T1
nel database MyDB
.
CREATE CLUSTERED COLUMNSTORE INDEX MyOrderedCCI ON MyDB.dbo.T1
ORDER (c1, c2);
L'esempio seguente converte l'indice columnstore cluster esistente in un indice columnstore cluster ordinato denominato MyOrderedCCI
nelle colonne c1
e c2
della tabella T2
del database MyDB
.
CREATE CLUSTERED COLUMNSTORE INDEX MyOrderedCCI ON MyDB.dbo.T2
ORDER (c1, c2)
WITH (DROP_EXISTING = ON);
Eventi
31 mar, 23 - 2 apr, 23
Il più grande evento di apprendimento di SQL, Infrastruttura e Power BI. 31 marzo - 2 aprile. Usare il codice FABINSIDER per salvare $400.
Iscriviti oggi stesso