Kiedy powinienem zastosować unikalne ograniczenie zamiast unikalnego indeksu?

194

Gdy chcę, aby kolumna miała odrębne wartości, mogę użyć ograniczenia

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

lub mogę użyć unikalnego indeksu

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

create unique index I_t2 on t2(code);

Kolumny z unikalnymi ograniczeniami wydają się być dobrymi kandydatami na unikalne indeksy.

Czy istnieją znane powody, aby używać unikalnych ograniczeń i zamiast tego używać unikalnych indeksów?

bernd_k
źródło
9
czy oni faktycznie są różni? Myślę, że w niektórych bazach danych, np. Postgresql, unikalne ograniczenie po prostu tworzy unikalny indeks. Nie odpowiadam, ponieważ nic nie wiem o serwerze SQL.
Xenoterracide
6
w postgresql możesz użyć wyrażenia w unikalnym indeksie, ale nie w unikalnym ograniczeniu.
Neil McGuigan,
1
W MS SQL są one zaimplementowane tak samo. Spróbuj utworzyć dwie tabele z tymi samymi danymi, jedną z unikalnym ograniczeniem, drugą z unikalnym indeksem. Będą korzystać z tej samej ilości miejsca na indeksy i oba będą w stanie wyszukać unikalny indeks, który (w praktyce) jest tworzony w obu kierunkach.
Jon of All Trades

Odpowiedzi:

153

Pod maską stosowane jest unikalne ograniczenie w taki sam sposób, jak unikalny indeks - indeks jest potrzebny, aby skutecznie spełnić wymóg wymuszenia ograniczenia. Nawet jeśli indeks został utworzony w wyniku ograniczenia UNIKALNEGO, planista zapytań może go używać tak jak każdego innego indeksu, jeśli uzna to za najlepszy sposób podejścia do danego zapytania.

Tak więc w przypadku bazy danych obsługującej obie funkcje wybór opcji często sprowadza się do preferowanego stylu i spójności.

Jeśli planujesz używać indeksu jako indeksu (tzn. Twój kod może polegać na szybkim wyszukiwaniu / sortowaniu / filtrowaniu tego pola), wolałbym wyraźnie użyć unikalnego indeksu (i skomentować źródło), a nie ograniczenia, aby to zrobić jasne - w ten sposób, jeśli wymóg unikatowości zostanie zmieniony w późniejszej wersji aplikacji, którą Ty (lub inny koder) będziesz wiedział, aby upewnić się, że indeks unikalny zostanie wstawiony w miejsce unikatowego indeksu (usunięcie pojedynczego ograniczenia spowoduje usunięcie indeks całkowicie). Określony indeks można również nazwać wskazówką dotyczącą indeksu (tj. Z (INDEX (ix_index_name)), co nie wydaje mi się, że ma to miejsce w przypadku indeksu utworzonego za kulisami do zarządzania wyjątkowością, ponieważ prawdopodobnie nie znasz jego nazwy.

Podobnie, jeśli musisz wymusić unikalność jako regułę biznesową, a nie pole, które trzeba przeszukać lub użyć do sortowania, użyłbym ograniczenia, ponownie, aby zamienić użycie bardziej oczywistym, gdy ktoś inny patrzy na twoją definicję tabeli.

Zauważ, że jeśli użyjesz zarówno unikalnego ograniczenia, jak i unikalnego indeksu w tym samym polu, baza danych nie będzie wystarczająco jasna, aby zobaczyć duplikację, więc otrzymasz dwa indeksy, które zajmą dodatkowe miejsce i spowolnią wstawianie / aktualizację wierszy.

David Spillett
źródło
1
Zastanawiam się, czy „baza danych nie będzie wystarczająco jasna”? Czy to prawda dla wszystkich RDBMS? Czy jest to wymagane przez standard SQL? A nawet jeśli tak (zastanawiam się, dlaczego tak powinno być), czy wszystkie implementacje implementują to w ten sposób? Lub: dlaczego DB nie może być wystarczająco „jasny”?
Jürgen A. Erhard
4
@jae: DBMS z pewnością może być wystarczająco jasny, ale musisz sprawdzić z każdym DBMS, aby sprawdzić, czy tak jest. Jeśli poprosisz MSSQL o utworzenie dwóch identycznych indeksów, utworzy dwa zamiast jednego, do którego odnoszą się dwie nazwy (przynajmniej tak było w ostatnim przypadku, gdy zauważyłem taką sytuację (z powodu błędu kopiowania + wklejenia z mojej strony)), więc zakładam, że to samo dotyczy przypadku, gdy jeden z indeksów jest obecny z powodu ograniczenia.
David Spillett,
3
+1 @David Spillett Myślę, że w zasadzie DBMS zakłada, że ​​wiesz, co robisz; Jeśli masz ochotę dwa razy utworzyć ten sam indeks, nie ma co do tego pytania.
Andrew Barber,
2
bardzo wnikliwy. Czy zdarza ci się wiedzieć, czy to zachowanie występuje również w MySQL i Apache Derby?
corsiKa
5
Ty można wymienić ograniczenie i używać go w podpowiedź indeksu. CREATE TABLE #T(X INT CONSTRAINT PK PRIMARY KEY NONCLUSTERED);SELECT * FROM #T WITH(INDEX(PK)) WHERE X = 1. Indeksy mogą być bardziej elastyczne, ponieważ ograniczenia nie obsługują wszystkich opcji indeksów, takich jak INCLUDEkolumny d lub indeksy filtrowane.
Martin Smith
101

Oprócz punktów w innych odpowiedziach, oto kilka kluczowych różnic między nimi.

Uwaga: komunikaty o błędach pochodzą z SQL Server 2012.

Błędy

Naruszenie ograniczenia unikalnego zwraca błąd 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.

Naruszenie unikalnego indeksu zwraca błąd 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.

Wyłączanie

Unikalne ograniczenie nie może zostać wyłączone.

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.

Ale unikalny indeks stojący za ograniczeniem klucza podstawowego lub unikatowy może zostać wyłączony, podobnie jak każdy unikalny indeks. Kapelusz Brain2000.

ALTER INDEX P1_u ON dbo.P1 DISABLE ;

Zwróć uwagę na zwykłe ostrzeżenie, że wyłączenie indeksu klastrowego powoduje, że dane są niedostępne.

Opcje

Unikalne ograniczenia obsługują opcje indeksowania takie jak FILLFACTORi IGNORE_DUP_KEY, chociaż nie było tak w przypadku wszystkich wersji SQL Server.

Zawarte kolumny

Indeksy nieklastrowane mogą zawierać nieindeksowane kolumny (nazywane indeksem kryjącym, jest to znaczące zwiększenie wydajności). Indeksy za ograniczeniami PRIMARY KEY i UNIQUE nie mogą zawierać kolumn. Hat-tip @ypercube.

Filtracja

Ograniczenia unikatowego nie można filtrować.

Unikalny indeks można filtrować.

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

Ograniczenia klucza obcego

Ograniczenie klucza obcego nie może odwoływać się do przefiltrowanego indeksu unikalnego, chociaż może odwoływać się do niefiltrowanego indeksu unikalnego (myślę, że został on dodany w SQL Server 2005).

Nazewnictwo

Podczas tworzenia wiązania określenie nazwy wiązania jest opcjonalne (dla wszystkich pięciu typów wiązań). Jeśli nie podasz nazwy, MSSQL wygeneruje ją dla Ciebie.

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

Podczas tworzenia indeksów musisz podać nazwę.

Hat-tip @ i-one.

Spinki do mankietów

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

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

Greenstone Walker
źródło
Unikalne ograniczenie można wyłączyć i włączyć za pomocą tej samej metody, co indeks: ALTER INDEX tbl ON uconstraint DISABLE, ALTER INDEX tbl ON uconstraint ODBUDOWA
Brain2000
Dzięki @ Brain2000. Przypadkowo nauczyłem się dziś rano sekcji o wyłączaniu indeksów tuż przed przeczytaniem tego komentarza.
Greenstone Walker,
10

Aby zacytować MSDN jako wiarygodne źródło:

Nie ma znaczących różnic między tworzeniem ograniczenia UNIQUE a tworzeniem unikalnego indeksu, który jest niezależny od ograniczenia . Sprawdzanie poprawności danych odbywa się w ten sam sposób, a optymalizator zapytań nie rozróżnia unikalnego indeksu utworzonego przez ograniczenie lub utworzonego ręcznie. Jednak utworzenie ograniczenia UNIQUE w kolumnie sprawia, że ​​cel indeksu jest jasny ... więcej informacji tutaj

I...

Aparat baz danych automatycznie tworzy indeks UNIQUE, aby wymusić wymóg unikatowości ograniczenia UNIQUE. Dlatego jeśli podjęta zostanie próba wstawienia zduplikowanego wiersza, aparat bazy danych zwraca komunikat o błędzie informujący o naruszeniu ograniczenia UNIQUE i nie dodaje wiersza do tabeli. O ile indeks klastrowany nie zostanie wyraźnie określony, domyślnie tworzony jest unikalny indeks nieklastrowany, aby wymusić ograniczenie UNIKALNE ... więcej informacji tutaj

Inne do: https://technet.microsoft.com/en-us/library/aa224827%28v=sql.80%29.aspx

użytkownik919426
źródło
6

Jedną z głównych różnic między ograniczeniem unikalnym a indeksem jest to, że ograniczenie klucza obcego w innej tabeli może odwoływać się do kolumn tworzących ograniczenie unikalne. Nie dotyczy to unikalnych indeksów. Ponadto unikalne ograniczenia są zdefiniowane jako część standardu ANSI, podczas gdy indeksy nie. Wreszcie, uważa się, że istnieje unikalne ograniczenie w dziedzinie logicznego projektowania baz danych (które mogą być wdrażane inaczej przez różne silniki DB), podczas gdy indeks jest aspektem fizycznym. Dlatego unikalne ograniczenie jest bardziej deklaratywne. Wolę unikalne ograniczenie w prawie wszystkich przypadkach.

Dmitrij Frenkel
źródło
8
-1 W SQL Server następujące błędy są niepoprawne: „ograniczenie klucza obcego w innej tabeli może odwoływać się do kolumn, które tworzą unikalne ograniczenie. Nie dotyczy to unikatowych indeksów”. W SQL Server możemy odwoływać ograniczenia FK do unikalnych indeksów.
AK
4
Zdolność ograniczenia klucza obcego do odniesienia do unikalnego indeksu została, jak sądzę, dodana w SQL Server 2005. Wiele źródeł, w tym niektóre strony w BOL, nie zostało zaktualizowanych w celu odzwierciedlenia zmian, więc nie sądzę, aby odpowiedź Dmitry'ego zasługuje na opinie negatywne. Reszta jego odpowiedzi jest natychmiastowa - Ograniczenia są standardem ANSI, a indeksy nie.
Greenstone Walker
pomimo tych negatywnych opinii moja ulubiona odpowiedź.
miracle173
Standardy są ważne. Jeśli standardy Ansi mają używać Unikalnego Ograniczenia, powinniśmy zastosować Unikalne Ograniczenie.
Rhyous,
1

W Oracle główna różnica polega na tym, że można utworzyć indeks unikalny dla funkcji, którego nie da się zrobić przy unikalnych ograniczeniach:

Na przykład

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

fk_xyzJest więc wyjątkowy tylko dla rekordów, które mają amount != 0.

Amir Pashazadeh
źródło
7
W SQL Server (tag pytania) indeksy można filtrować za pomocą WHEREklauzuli. CREATE UNIQUE NONCLUSTERED INDEX P4_U ON DBO.P4 ( PID ) WHERE TXT = 'qwert' ;
Greenstone Walker
-3

Ograniczenie UNIQUE jest preferowane w stosunku do indeksu UNIQUE. Jeśli ograniczenie nie jest unikalne, musisz użyć zwykłego lub nie unikalnego indeksu. Ograniczenie to także inny rodzaj indeksu. Indeks służy do szybszego dostępu.

Unikalne indeksy mogą zawierać klauzule where. Na przykład możesz tworzyć indeksy dla każdego roku na podstawie kolumny daty

WHERE Sale_Date BETWEEN '2012-01-01' AND '2012-12-31'
Ravi Ramaswamy
źródło
Dobrze jest zobaczyć wspomnianą korzyść z klauzuli where.
crokusek
3
„Ograniczenie to także inny rodzaj indeksu”. Nie, nie jest. Niektóre ograniczenia (PK, UQ, FK) mogą być i są często egzekwowane przy użyciu indeksów. Niekoniecznie jednak i nie domyślnie we wszystkich DBMS.
ypercubeᵀᴹ