Benzersiz bir dizin yerine benzersiz bir kısıtlamayı ne zaman kullanmalıyım?


194

Bir sütunun farklı değerlere sahip olmasını istediğimde bir kısıtlama kullanabilirim

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

veya benzersiz bir dizin kullanabilirim

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

create unique index I_t2 on t2(code);

Eşsiz kısıtlamaları olan sütunlar, benzersiz dizinler için iyi adaylar gibi görünmektedir.

Benzersiz kısıtlamalar kullanmanın ve bunun yerine benzersiz dizinleri kullanmamanızın bilinen bir nedeni var mı?


9
aslında farklı mılar? Bazı veritabanlarında örneğin postgresql, bence benzersiz bir kısıtlama sadece benzersiz bir indeks yaratıyor. Cevap vermiyorum çünkü sql sunucusu hakkında hiçbir şey bilmiyorum.
xenoterracide

6
postgresql'de, bir ifadeyi benzersiz bir dizinde ancak benzersiz bir kısıtlamada kullanabilirsiniz.
Neil McGuigan

1
MS SQL'de de aynı şekilde uygulanırlar. Aynı verilerle, biri benzersiz bir kısıtlamaya, diğeri benzersiz bir dizine sahip iki tablo oluşturmayı deneyin. Aynı miktarda indeks alanı kullanacaklar ve her ikisi de (pratikte) her iki şekilde de yaratılan benzersiz endekse karşı arama yapabilecekler.
Tüm İşlemlerden Jon,

Yanıtlar:


153

Kaputun altında, benzersiz bir kısıtlama, benzersiz bir indeksle aynı şekilde uygulanır - kısıtlamayı uygulama gereksinimini etkin bir şekilde yerine getirmek için bir endekse ihtiyaç vardır. Dizin bir UNIQUE kısıtlaması sonucu oluşturulmuş olsa bile, sorgu planlayıcısı, verilen bir sorguyu ele almanın en iyi yolu olarak görürse, diğer dizinler gibi kullanabilir.

Bu yüzden, her iki özelliği de destekleyen bir veritabanı için hangisinin kullanılacağının seçimi genellikle tercih edilen stil ve tutarlılığa bağlı olacaktır.

Dizini bir indeks olarak kullanmayı planlıyorsanız (yani kodunuz hızlı olması için bu alanda arama / sıralama / filtrelemeye güvenebilir) açıkça yapmak için bir kısıtlama yerine açıkça benzersiz bir endeks kullanırım (ve kaynağı yorumlarım). temizle - bu şekilde benzersizlik gereksinimi uygulamanızın (veya bazı diğer kodlayıcıların) daha sonraki sürümlerinde değiştirilirse, benzersiz olmayan bir dizinin benzersiz olanın yerine koyulduğundan emin olmasını bileceksiniz (yalnızca benzersiz bir kısıtlamayı kaldırmak tamamen endeks). Ayrıca, bir dizin ipucunda (yani WITH (INDEX (ix_index_name))) isimlendirilebilir, ki bence onun adını bilmediğiniz için benzersizliği yönetmek için perde arkasında yaratılan dizin için durum böyle değildir.

Aynı şekilde, sadece aranması gereken veya sıralama için kullanılan alanlardan ziyade, sadece bir iş kuralı olarak benzersizliği zorlamanız gerekiyorsa, o zaman bir başkası tablo tanımınıza bakıldığında amaçlanan kullanımı daha açık hale getirmek için kısıtlamayı kullanırdım.

Aynı alanda hem benzersiz bir kısıtlama hem de benzersiz bir dizin kullanırsanız, veritabanının kopyalamayı görecek kadar parlak olmayacağını, bu nedenle fazladan alan tüketecek ve satır eklerini / güncellemelerini yavaşlatan iki dizinle sonuçlanacağını unutmayın.


1
Merak ediyorum "veritabanı yeterince parlak olmayacak"? Bu tüm RDBMS'ler için geçerli mi? SQL-Standard tarafından zorunlu mu? Öyle olsa bile (ve neden olması gerektiğini merak ediyorum), tüm uygulamalar bu şekilde mi uygulanıyor? Veya: neden bir DB yeterince "parlak" olamaz?
Jürgen A. Erhard

4
@jae: Bir DBMS kesinlikle yeterince parlak olabilir , ancak olup olmadığını görmek için her DBMS ile kontrol etmeniz gerekir. MSSQL'den iki aynı endeks oluşturmasını rica ediyorsanız, iki isim tarafından adlandırılan iki taneden ziyade iki tane yaratacaktır (en azından böyle bir durum tespit ettiğimde bu oldu (benim bölümümdeki bir kopya + yapıştırma hatası nedeniyle)), öyleyse, aynısının bir kısıtlama nedeniyle endekslerden birinin mevcut olması durumunda olduğunu varsayalım.
David Spillett

3
+1 @David Spillett Temelde DBMS'nin ne yaptığınızı bildiğinizi varsaydığını düşünüyorum; Aynı endeksi iki kez oluşturmak istiyorsanız, bu konuda sizi sorgulamaz.
Andrew Barber

2
Çok anlayışlı. Bu davranışın MySQL ve Apache Derby'de olup olmadığını biliyor musunuz?
corsiKa

5
Sen edebilir bir sınırlama isim ve bir dizin ipucu kullanmak. CREATE TABLE #T(X INT CONSTRAINT PK PRIMARY KEY NONCLUSTERED);SELECT * FROM #T WITH(INDEX(PK)) WHERE X = 1. Dizinler daha esnek olabilir, ancak kısıtlamalar, INCLUDEd sütunlar veya filtrelenmiş dizinler gibi tüm dizin seçeneklerini desteklememektedir .
Martin Smith,

101

Diğer cevaplardaki noktalara ek olarak, işte ikisi arasında bazı temel farklar.

Not: Hata mesajları SQL Server 2012'dendir.

Hatalar

Benzersiz bir kısıtlamanın ihlali 2627 numaralı hatayı döndürür.

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.

Benzersiz bir dizinin ihlali 2601 hatası veriyor.

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.

Devre Dışı Bırakma

Benzersiz bir kısıtlama devre dışı bırakılamaz.

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.

Ancak, bir birincil anahtar kısıtının veya benzersiz bir kısıtlamanın arkasındaki benzersiz dizin, herhangi bir benzersiz dizinin olduğu gibi devre dışı bırakılabilir. Şapkalı Brain2000.

ALTER INDEX P1_u ON dbo.P1 DISABLE ;

Kümelenmiş bir dizini devre dışı bırakmanın verilere erişilemez hale getirdiğine dikkat edin.

Seçenekler

Benzersiz kısıtlamalar , FILLFACTORve benzeri IGNORE_DUP_KEYSQL Server sürümleri için geçerli olmamasına rağmen dizin oluşturma seçeneklerini destekler .

Dahil Edilen Sütunlar

Kümelenmemiş dizinler, dizine eklenmemiş sütunlar içerebilir (örtü endeksi olarak adlandırılır, bu büyük bir performans artışıdır). PRIMARY KEY ve UNIQUE kısıtlamalarının arkasındaki dizinler sütun içeremez. Hat-tip @ypercube.

süzme

Benzersiz bir kısıtlama filtrelenemez.

Benzersiz bir dizin filtrelenebilir.

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

Yabancı Anahtar Kısıtlamaları

Bir Yabancı Anahtar kısıtı, filtrelenmemiş benzersiz bir dizine referans veremez, ancak filtrelenmemiş benzersiz bir dizine başvurabilir (bunun SQL Server 2005'te eklendiğini düşünüyorum).

Adlandırma

Kısıtlama oluştururken, bir kısıtlama adı belirlemek isteğe bağlıdır (beş sınırlamanın tümü için). Bir ad belirtmezseniz, MSSQL sizin için bir tane oluşturur.

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

Dizin oluştururken bir ad belirtmeniz gerekir.

Hat-ucu @ i-bir.

Bağlantılar

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

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


Benzersiz bir kısıt endeks olarak aynı yöntemle devre dışı ve etkinleştirilebilir: uconstraint DISABLE AÇIK ENDEKSİ tbl ALTER ALTER INDEX tbl AÇIK REBUILD uconstraint
Brain2000

Brain2000 @ teşekkürler. Tesadüfen, bu sabah okumadan hemen önce bu sabah endeksleri devre dışı bırakma üzerine bir bölüm öğrettim.
Greenstone Walker,

10

MSDN'yi yetkili bir kaynak olarak sunmak için:

UNIQUE kısıtlaması oluşturma ile bir kısıtlamadan bağımsız benzersiz bir dizin oluşturma arasında önemli bir fark yoktur . Veri doğrulama aynı şekilde gerçekleşir ve sorgu iyileştirici, bir kısıtlama tarafından oluşturulan veya manuel olarak oluşturulan benzersiz bir dizin arasında ayrım yapmaz. Ancak, sütunda UNIQUE kısıtlaması oluşturmak, endeksin hedefini açıkça ortaya koyuyor ... daha fazla bilgi

Ve...

Veritabanı Altyapısı, UNIQUE sınırının benzersizliğini zorunlu kılmak için otomatik olarak bir UNIQUE dizini oluşturur. Bu nedenle, yinelenen bir satır ekleme denemesi yapılırsa, Veritabanı Altyapısı, UNIQUE kısıtlamasının ihlal edildiğini ve satırı tabloya eklemediğini belirten bir hata mesajı döndürür. Kümelenmiş bir dizin açıkça belirtilmediği sürece, UNIQUE kısıtlamasını uygulamak için varsayılan olarak benzersiz, kümelenmemiş bir dizin oluşturulur ... daha fazla bilgi

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


6

Benzersiz bir kısıtlama ile benzersiz bir dizin arasındaki en büyük farklardan biri, başka bir tablodaki yabancı anahtar kısıtlamasının, benzersiz bir kısıtlama oluşturan sütunlara başvuru yapabilmesidir. Bu benzersiz dizinler için doğru değildir. Ayrıca, benzersiz kısıtlamalar, ANSI standardının bir parçası olarak tanımlanırken, dizinler değildir. Son olarak, endeks fiziksel yönü iken mantıksal veritabanı tasarımı (farklı DB motorları tarafından farklı şekilde uygulanabilir) alanında yaşadığı düşünülen benzersiz kısıtlama. Bu nedenle, benzersiz kısıtlama daha açıklayıcıdır. Neredeyse tüm durumlarda benzersiz kısıtlama tercih ederim.


8
-1 SQL Server'da aşağıdakiler yanlıştır: "başka bir tablodaki yabancı anahtar kısıtı, benzersiz bir kısıtlama oluşturan sütunlara başvurabilir. Bu, benzersiz dizinler için doğru değildir". SQL Server'da FK kısıtlarını benzersiz dizinlere yönlendirebiliriz.
AK,

4
Yabancı bir anahtar kısıtlamasının benzersiz bir dizine referans verme yeteneği, sanırım, SQL Server 2005'te eklenmiştir. BOL'deki bazı sayfalar da dahil olmak üzere birçok kaynak, değişiklikleri yansıtacak şekilde güncellenmemiştir, bu nedenle Dmitry'ın cevabını sanmıyorum Düşüşleri hak ediyor. Cevabının geri kalan kısmı açıktır - Kısıtlamalar ANSI standardıdır, indeksler değildir.
Greenstone Walker

Bu düşüşe rağmen en sevdiğim cevap.
miracle173

Standartlar önemlidir. Eğer Ansi standartları Eşsiz Bir Kısıt kullanmaksa, Eşsiz Bir Kısıt kullanmalıyız.
Rhyous

1

Oracle'da önemli bir fark, benzersiz kısıtlamalarla gerçekleştirilemeyen, fonksiyona özgü bir dizin oluşturabilirsiniz:

Örneğin

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

Yani fk_xyzsadece sahip olduğu kayıtlar için benzersizdir amount != 0.


7
SQL Server'da (soru etiketi), dizinler bir WHEREcümle ile filtrelenebilir . CREATE UNIQUE NONCLUSTERED INDEX P4_U ON DBO.P4 ( PID ) WHERE TXT = 'qwert' ;
Greenstone Walker

-3

UNIQUE Kısıtlaması, UNIQUE Endeksine göre tercih edilir. Kısıtlama benzersiz değilse, normal veya benzersiz olmayan bir dizin kullanmanız gerekir. Kısıt da başka bir indeks türüdür. Dizin daha hızlı erişim için kullanılır.

Benzersiz Dizinler nerede cümlecikleri olabilir. Örneğin, tarih sütununa göre her yıl için dizinler oluşturabilirsiniz.

WHERE Sale_Date BETWEEN '2012-01-01' AND '2012-12-31'

Yan tümce fayda bahsini görmek güzel.
crokusek

3
"Sınırlama aynı zamanda başka bir indeks türüdür." Hayır değil. Bazı kısıtlamalar (PK, UQ, FK) endekslerin kullanımı ile zorlanabilir ve zorlanır. Tüm DBMS’lerde varsayılan olarak olmasa da, mutlaka değil.
ypercubeᵀᴹ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.