Khi nào tôi nên sử dụng một ràng buộc duy nhất thay vì một chỉ mục duy nhất?


195

Khi tôi muốn một cột có các giá trị riêng biệt, tôi có thể sử dụng một ràng buộc

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

hoặc tôi có thể sử dụng một chỉ mục duy nhất

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

create unique index I_t2 on t2(code);

Các cột với các ràng buộc duy nhất dường như là ứng cử viên tốt cho các chỉ mục duy nhất.

Có bất kỳ lý do đã biết để sử dụng các ràng buộc duy nhất và không sử dụng các chỉ mục duy nhất thay thế?


9
chúng có thực sự khác nhau không? Tôi nghĩ rằng trong một số cơ sở dữ liệu, ví dụ như postgresql, một ràng buộc duy nhất chỉ đơn giản là tạo ra một chỉ mục duy nhất. Tôi không trả lời vì tôi không biết gì về máy chủ sql.
xenoterracide

6
trong postgresql, bạn có thể sử dụng một biểu thức trong một chỉ mục duy nhất nhưng không phải trong một ràng buộc duy nhất.
Neil McGuigan

1
Trên MS SQL, chúng được thực hiện giống nhau. Hãy thử tạo hai bảng có cùng dữ liệu, một bảng có ràng buộc duy nhất, bảng còn lại có chỉ mục duy nhất. Họ sẽ sử dụng cùng một không gian chỉ mục và cả hai sẽ có thể tìm kiếm dựa vào chỉ mục duy nhất (trong thực tế) được tạo theo bất kỳ cách nào.
Jon của tất cả các giao dịch

Câu trả lời:


153

Dưới vỏ bọc, một ràng buộc duy nhất được triển khai giống như một chỉ mục duy nhất - một chỉ mục là cần thiết để thực hiện hiệu quả yêu cầu thực thi ràng buộc đó. Ngay cả khi chỉ mục được tạo do kết quả của ràng buộc UNIQUE, trình lập kế hoạch truy vấn có thể sử dụng nó giống như bất kỳ chỉ mục nào khác nếu nó thấy đó là cách tốt nhất để tiếp cận một truy vấn nhất định.

Vì vậy, đối với một cơ sở dữ liệu hỗ trợ cả hai tính năng, việc lựa chọn sử dụng thường sẽ đi theo phong cách và tính nhất quán ưa thích.

Nếu bạn dự định sử dụng chỉ mục làm chỉ mục (nghĩa là mã của bạn có thể dựa vào tìm kiếm / sắp xếp / lọc trên trường đó một cách nhanh chóng) tôi sẽ sử dụng một chỉ mục duy nhất (và nhận xét nguồn) thay vì ràng buộc để thực hiện điều đó rõ ràng - theo cách này nếu yêu cầu về tính duy nhất được thay đổi trong lần sửa đổi sau của ứng dụng mà bạn (hoặc một số lập trình viên khác) sẽ biết để đảm bảo một chỉ mục không duy nhất được đặt thay thế cho một chỉ số duy nhất (chỉ cần loại bỏ một ràng buộc duy nhất sẽ loại bỏ chỉ số hoàn toàn). Ngoài ra, một chỉ mục cụ thể có thể được đặt tên trong một gợi ý chỉ mục (ví dụ: VỚI (INDEX (ix_index_name)), mà tôi không nghĩ là trường hợp chỉ mục được tạo ra đằng sau hậu trường để quản lý tính duy nhất vì bạn không thể biết tên của nó.

Tương tự như vậy, nếu bạn chỉ cần thực thi tính duy nhất như một quy tắc kinh doanh thay vì trường cần tìm kiếm hoặc sử dụng để sắp xếp thì tôi sẽ sử dụng ràng buộc, một lần nữa để làm cho mục đích sử dụng rõ ràng hơn khi người khác nhìn vào định nghĩa bảng của bạn.

Lưu ý rằng nếu bạn sử dụng cả ràng buộc duy nhất và chỉ mục duy nhất trên cùng một trường, cơ sở dữ liệu sẽ không đủ sáng để xem bản sao, do đó bạn sẽ kết thúc với hai chỉ mục sẽ tiêu tốn thêm dung lượng và làm chậm việc chèn / cập nhật hàng.


1
Tôi đang tự hỏi về "cơ sở dữ liệu sẽ không đủ sáng"? Điều đó có đúng với tất cả RDBMS không? Được ủy quyền bởi Tiêu chuẩn SQL? Và ngay cả khi nó là (và tôi tự hỏi tại sao nó phải như vậy), liệu tất cả các triển khai thực hiện theo cách đó? Hoặc: tại sao DB không đủ "sáng"?
Jürgen A. Erhard

4
@jae: một DBMS chắc chắn thể đủ sáng, nhưng bạn phải kiểm tra với từng DBMS để xem nó có. Nếu bạn yêu cầu MSSQL tạo hai chỉ mục giống hệt nhau, nó sẽ tạo hai chỉ mục được gọi bằng hai tên (ít nhất đây là trường hợp lần trước tôi phát hiện ra một tình huống như vậy (do lỗi sao chép + dán trên phần của tôi)), vì vậy tôi giả sử như vậy là trường hợp nếu một trong các chỉ mục xuất hiện do một ràng buộc.
David Spillett

3
+1 @David Spillett Tôi nghĩ rằng về cơ bản DBMS chỉ cho rằng bạn biết bạn đang làm gì; Nếu bạn cảm thấy muốn tạo cùng một chỉ mục hai lần, nó không hỏi bạn về điều đó.
Andrew Barber

2
rất sâu sắc. Bạn có tình cờ biết hành vi này có trong MySQL và Apache Derby không?
corsiKa

5
Bạn có thể đặt tên cho một ràng buộc và sử dụng nó trong một gợi ý chỉ mục. CREATE TABLE #T(X INT CONSTRAINT PK PRIMARY KEY NONCLUSTERED);SELECT * FROM #T WITH(INDEX(PK)) WHERE X = 1. Các chỉ mục có thể linh hoạt hơn mặc dù trong các ràng buộc đó không hỗ trợ tất cả các tùy chọn chỉ mục như INCLUDEcột d hoặc chỉ mục được lọc.
Martin Smith

101

Ngoài những điểm trong các câu trả lời khác, đây là một số khác biệt chính giữa hai câu hỏi.

Lưu ý: Các thông báo lỗi là từ SQL Server 2012.

Lỗi

Vi phạm một ràng buộc duy nhất trả về lỗi 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.

Vi phạm một chỉ mục duy nhất trả về lỗi 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.

Vô hiệu hóa

Một ràng buộc duy nhất không thể bị vô hiệu hóa.

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.

Nhưng chỉ mục duy nhất đằng sau một ràng buộc khóa chính hoặc một ràng buộc duy nhất có thể bị vô hiệu hóa, như bất kỳ chỉ mục duy nhất nào. Mũ lưỡi trai Brain2000.

ALTER INDEX P1_u ON dbo.P1 DISABLE ;

Lưu ý cảnh báo thông thường rằng việc vô hiệu hóa một chỉ mục được nhóm làm cho dữ liệu không thể truy cập được.

Tùy chọn

Các ràng buộc duy nhất hỗ trợ các tùy chọn lập chỉ mục như FILLFACTORIGNORE_DUP_KEY, mặc dù điều này không xảy ra đối với mọi phiên bản của SQL Server.

Cột bao gồm

Các chỉ mục không bao gồm có thể bao gồm các cột không được lập chỉ mục (được gọi là chỉ mục bao phủ, đây là một cải tiến hiệu suất chính). Các chỉ mục đằng sau các ràng buộc PRIMARY KEY và UNIITE không thể bao gồm các cột. Mũ lưỡi trai @ypercube.

Lọc

Một ràng buộc duy nhất không thể được lọc.

Một chỉ mục duy nhất có thể được lọc.

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

Ràng buộc khóa ngoại

Ràng buộc khóa ngoài không thể tham chiếu một chỉ mục duy nhất được lọc, mặc dù nó có thể tham chiếu một chỉ mục duy nhất không được lọc (tôi nghĩ rằng điều này đã được thêm vào trong SQL Server 2005).

Đặt tên

Khi tạo ràng buộc, chỉ định tên ràng buộc là tùy chọn (cho tất cả năm loại ràng buộc). Nếu bạn không chỉ định tên thì MSSQL sẽ tạo một tên cho bạn.

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

Khi tạo chỉ mục, bạn phải chỉ định một tên.

Hat-tip @ i-one.

Liên kết

http://technet.microsoft.com/en-us/l Library / aa224827 (v = Vista.80) .aspx

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


Một ràng buộc duy nhất có thể được vô hiệu hóa và kích hoạt thông qua cùng một phương thức như một chỉ mục: ALTER INDEX tbl ON uconstraint DISABLE, ALTER INDEX tbl ON uconstraint REBUILD
Brain2000 19/07/18

Cảm ơn @ Brain2000. Thật trùng hợp, tôi đã dạy một phần về việc vô hiệu hóa các chỉ mục sáng nay ngay trước khi tôi đọc bình luận này.
Greenstone Walker

10

Để trích dẫn MSDN như một nguồn có thẩm quyền:

Không có sự khác biệt đáng kể giữa việc tạo ra một ràng buộc ĐỘC ĐÁO và tạo một chỉ mục duy nhất độc lập với một ràng buộc . Xác thực dữ liệu xảy ra theo cách tương tự và trình tối ưu hóa truy vấn không phân biệt giữa một chỉ mục duy nhất được tạo bởi một ràng buộc hoặc được tạo thủ công. Tuy nhiên, việc tạo một ràng buộc ĐỘC ĐÁO trên cột làm cho mục tiêu của chỉ mục rõ ràng ... thông tin thêm ở đây

Và ...

Công cụ cơ sở dữ liệu tự động tạo ra một chỉ mục UNIQUE để thực thi yêu cầu duy nhất của ràng buộc UNIQUE. Do đó, nếu một nỗ lực chèn một hàng trùng lặp được thực hiện, Cơ sở dữ liệu sẽ trả về một thông báo lỗi cho biết ràng buộc UNIQUE đã bị vi phạm và không thêm hàng vào bảng. Trừ khi một chỉ mục được nhóm được chỉ định rõ ràng, một chỉ mục duy nhất, không bao gồm được tạo theo mặc định để thực thi ràng buộc UNIQUE ... thông tin thêm ở đây

Khác vào: https://technet.microsoft.com/en-us/l Library / aa224827% 28v = sql.80% 29.aspx


6

Một trong những khác biệt chính giữa ràng buộc duy nhất và chỉ mục duy nhất là ràng buộc khóa ngoại trên bảng khác có thể tham chiếu các cột tạo nên ràng buộc duy nhất. Điều này không đúng với các chỉ mục duy nhất. Ngoài ra, các ràng buộc duy nhất được xác định là một phần của tiêu chuẩn ANSI, trong khi các chỉ mục thì không. Cuối cùng, ràng buộc duy nhất được coi là sống trong lĩnh vực thiết kế cơ sở dữ liệu logic (có thể được triển khai khác nhau bởi các công cụ DB khác nhau) trong khi chỉ mục là khía cạnh vật lý. Do đó, ràng buộc duy nhất là khai báo nhiều hơn. Tôi thích ràng buộc duy nhất trong hầu hết các trường hợp.


8
-1 Trong SQL Server, điều sau đây là sai: "một ràng buộc khóa ngoài trên một bảng khác có thể tham chiếu các cột tạo nên một ràng buộc duy nhất. Điều này không đúng với các chỉ mục duy nhất". Trong SQL Server, chúng ta có thể tham chiếu các ràng buộc FK cho các chỉ mục duy nhất.
AK

4
Khả năng cho một ràng buộc khóa ngoại để tham chiếu một chỉ mục duy nhất là, tôi nghĩ, đã được thêm vào trong SQL Server 2005. Nhiều nguồn, bao gồm một số trang trong BOL, chưa được cập nhật để phản ánh các thay đổi, vì vậy tôi không nghĩ câu trả lời của Dmitry xứng đáng với downvote. Phần còn lại của câu trả lời của anh là tại chỗ - Các ràng buộc là tiêu chuẩn ANSI, các chỉ mục thì không.
Greenstone Walker

mặc dù những downvote câu trả lời yêu thích của tôi.
phép lạ173

Tiêu chuẩn rất quan trọng. Nếu các tiêu chuẩn của Ansi là sử dụng một ràng buộc duy nhất, thì chúng ta nên sử dụng một ràng buộc duy nhất.
Rhyous

1

Trong Oracle, một sự khác biệt lớn là bạn có thể tạo một chỉ mục duy nhất cho hàm, điều này không thể thực hiện được với các ràng buộc duy nhất:

Ví dụ

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

Vì vậy, fk_xyzchỉ là duy nhất cho hồ sơ có amount != 0.


7
Trong SQL Server (thẻ câu hỏi), các chỉ mục có thể được lọc bằng một WHEREmệnh đề. CREATE UNIQUE NONCLUSTERED INDEX P4_U ON DBO.P4 ( PID ) WHERE TXT = 'qwert' ;
Greenstone Walker

-3

Hạn chế UNIQUE được ưa thích hơn UNIQUE Index. Khi ràng buộc không phải là duy nhất, bạn cần sử dụng một chỉ mục thông thường hoặc không duy nhất. Ràng buộc cũng là một loại chỉ số khác. Chỉ mục được sử dụng để truy cập nhanh hơn.

Chỉ số duy nhất có thể có nơi mệnh đề. Ví dụ: bạn có thể tạo các chỉ mục cho mỗi năm dựa trên cột ngày

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

Tốt để xem các điều khoản lợi ích được đề cập.
crokusek

3
"Ràng buộc cũng là một loại chỉ mục khác." Không, không phải vậy. Một số ràng buộc (PK, UQ, FK) có thể và thường được thi hành bằng cách sử dụng các chỉ mục. Không nhất thiết mặc dù và không theo mặc định trong tất cả DBMS.
ypercubeᵀᴹ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.