it-swarm.it

Quando devo utilizzare un vincolo univoco anziché un indice univoco?

Quando voglio che una colonna abbia valori distinti, posso usare un vincolo

create table t1(
id int primary key,
code varchar(10) unique NULL
);
go

oppure posso usare un indice univoco

create table t2(
id int primary key,
code varchar(10) NULL
);
go

create unique index I_t2 on t2(code);

Le colonne con vincoli univoci sembrano essere buoni candidati per indici univoci.

Esistono motivi noti per utilizzare vincoli univoci e non utilizzare indici univoci?

210
bernd_k

Sotto il cofano un vincolo unico è implementato allo stesso modo di un indice univoco: è necessario un indice per soddisfare in modo efficiente il requisito di imporre il vincolo. Anche se l'indice viene creato come risultato di un vincolo UNIQUE, il pianificatore di query può utilizzarlo come qualsiasi altro indice se lo vede come il modo migliore per avvicinarsi a una determinata query.

Quindi, per un database che supporta entrambe le funzionalità, la scelta di quale utilizzare spesso dipenderà dallo stile e dalla coerenza preferiti.

Se hai intenzione di utilizzare l'indice come indice (ad esempio, il tuo codice potrebbe fare affidamento sulla ricerca/ordinamento/filtro su quel campo per essere veloce) Vorrei usare esplicitamente un indice univoco (e commentare la fonte) piuttosto che un vincolo per renderlo chiaro: in questo modo se il requisito di unicità viene modificato in una revisione successiva dell'applicazione che l'utente (o qualche altro programmatore) saprà per assicurarsi che un indice non univoco venga inserito al posto di quello univoco (rimuovendo semplicemente un vincolo univoco rimuoveresti l'indice completamente). Inoltre, un indice specifico può essere nominato in un suggerimento sull'indice (ovvero WITH (INDEX (ix_index_name)), che non credo sia il caso dell'indice creato dietro le quinte per la gestione dell'unicità poiché è improbabile che tu ne conosca il nome.

Allo stesso modo se hai solo bisogno di imporre l'unicità come regola aziendale piuttosto che il campo che deve essere cercato o utilizzato per l'ordinamento, allora userei il vincolo, ancora una volta per rendere l'uso previsto più ovvio quando qualcun altro guarda la definizione della tabella.

Si noti che se si utilizzano sia un vincolo univoco che un indice univoco sullo stesso campo, il database non sarà abbastanza luminoso da vedere la duplicazione, quindi si otterranno due indici che consumeranno spazio extra e rallenteranno gli inserimenti/gli aggiornamenti delle righe.

165
David Spillett

Oltre ai punti in altre risposte, ecco alcune differenze chiave tra i due.

Nota: i messaggi di errore provengono da SQL Server 2012.

Errori

La violazione di un vincolo univoco restituisce l'errore 2627.

Msg 2627, Level 14, State 1, Line 1
Violation of UNIQUE KEY constraint 'P1U_pk'. Cannot insert duplicate key in object 'dbo.P1U'. The duplicate key value is (1).
The statement has been terminated.

La violazione di un indice univoco restituisce l'errore 2601.

Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.P1' with unique index 'P1_u'. The duplicate key value is (1).
The statement has been terminated.

Disattivazione

Un vincolo univoco non può essere disabilitato.

Msg 11415, Level 16, State 1, Line 1
Object 'P1U_pk' cannot be disabled or enabled. This action applies only to foreign key and check constraints.
Msg 4916, Level 16, State 0, Line 1
Could not enable or disable the constraint. See previous errors.

Ma l'indice univoco dietro un vincolo di chiave primaria o un vincolo univoco può essere disabilitato, così come qualsiasi indice univoco. Hat-tip Brain2000.

ALTER INDEX P1_u ON dbo.P1 DISABLE ;

Si noti il ​​solito avviso che la disabilitazione di un indice cluster rende i dati inaccessibili.

Opzioni

Vincoli univoci supportano opzioni di indicizzazione come FILLFACTOR e IGNORE_DUP_KEY, sebbene ciò non sia avvenuto per tutte le versioni di SQL Server.

Colonne incluse

Gli indici non cluster possono includere colonne non indicizzate (definito indice di copertura, questo è un importante miglioramento delle prestazioni). Gli indici dietro i vincoli PRIMARY KEY e UNIQUE non possono includere colonne. Hat-tip @ypercube.

Filtraggio

Un vincolo univoco non può essere filtrato.

È possibile filtrare un indice univoco.

CREATE UNIQUE NONCLUSTERED INDEX Students6_DrivesLicence_u 
ON dbo.Students6( DriversLicenceNo ) WHERE DriversLicenceNo is not null ;

Vincoli di chiave esterna

Un vincolo di chiave esterna non può fare riferimento a un indice univoco filtrato, sebbene possa fare riferimento a un indice univoco non filtrato (penso che questo sia stato aggiunto in SQL Server 2005).

Naming

Quando si crea un vincolo, specificare un nome di vincolo è facoltativo (per tutti e cinque i tipi di vincoli). Se non specifichi un nome, MSSQL ne genererà uno per te.

CREATE TABLE dbo.T1 (
    TID int not null PRIMARY KEY
) ;
GO
CREATE TABLE dbo.T2 (
    TID int not null CONSTRAINT T2_pk PRIMARY KEY
) ;

Durante la creazione di indici, è necessario specificare un nome.

Hat-tip @ i-one.

Link

http://technet.Microsoft.com/en-us/library/aa224827 (v = SQL.80) .aspx

http://technet.Microsoft.com/en-us/library/ms177456.aspx

107

Per citare MSDN come fonte autorevole:

Non ci sono differenze significative tra la creazione di un vincolo UNIQUE e la creazione di un indice univoco indipendente da un vincolo . La convalida dei dati avviene allo stesso modo e Query Optimizer non distingue tra un indice univoco creato da un vincolo o creato manualmente. Tuttavia, la creazione di un vincolo UNICO sulla colonna chiarisce l'obiettivo dell'indice ... maggiori informazioni qui

E ...

Il Motore di database crea automaticamente un indice UNIQUE per applicare il requisito di unicità del vincolo UNIQUE. Pertanto, se viene effettuato un tentativo di inserire una riga duplicata, il Motore di database restituisce un messaggio di errore che indica che il vincolo UNIQUE è stato violato e non aggiunge la riga alla tabella. A meno che un indice cluster non sia esplicitamente specificato, un indice univoco e non cluster viene creato per impostazione predefinita per applicare il vincolo UNIQUE ... maggiori informazioni qui

Altro in: https://technet.Microsoft.com/en-us/library/aa224827%28v=sql.80%29.aspx

10
user919426

Una delle principali differenze tra un vincolo univoco e un indice univoco è che un vincolo di chiave esterna su un'altra tabella può fare riferimento a colonne che costituiscono un vincolo univoco. Questo non è vero per gli indici univoci. Inoltre, i vincoli univoci sono definiti come parte dello standard ANSI, mentre gli indici no. Infine, si ritiene che un vincolo unico risieda nel regno della progettazione logica del database (che può essere implementato in modo diverso da motori DB diversi) mentre l'indice è un aspetto fisico. Pertanto, il vincolo univoco è più dichiarativo. Preferirei un vincolo unico in quasi tutti i casi.

7
Dmitry Frenkel

In Oracle una grande differenza è che puoi creare un indice univoco di funzione, che non è fattibile con vincoli univoci:

Per esempio

create unique index ux_test on my_table (case when amount != 0 then fk_xyz end);

Così fk_xyz è univoco solo per i record che hanno amount != 0.

1
Amir Pashazadeh