2014-05-08 17 views
88

Như tôi có thể hiểu được documentation các định nghĩa sau đây là tương đương:Postgres hạn chế duy nhất vs index

create table foo (
    id serial primary key, 
    code integer, 
    label text, 
    constraint foo_uq unique (code, label)); 

create table foo (
    id serial primary key, 
    code integer, 
    label text); 
create unique index foo_idx on foo using btree (code, label);  

Tuy nhiên bạn có thể đọc trong các lưu ý: Cách ưa thích để thêm một hạn chế duy nhất cho một bảng là ALTER TABLE. .. THÊM XIN. Việc sử dụng các chỉ mục để thực thi các ràng buộc duy nhất có thể được coi là chi tiết triển khai không nên truy cập trực tiếp.

Đây có phải là vấn đề có phong cách tốt không? Hậu quả thực tế của việc chọn một trong các biến thể này (ví dụ: về hiệu suất) là gì?

+19

The (chỉ) chênh lệch thực tế là bạn có thể tạo ra một khóa ngoại đến một hạn chế duy nhất nhưng không một chỉ số duy nhất. –

+20

Một lợi thế theo cách khác xung quanh ([như đã đưa ra trong một câu hỏi khác gần đây] (http://stackoverflow.com/a/23449309/157957)) là bạn có thể có chỉ mục * một phần * duy nhất, chẳng hạn như "Duy nhất (foo) Thanh ở đâu là Null ". AFAIK, không có cách nào để làm điều đó với một ràng buộc. – IMSoP

+0

[Ở đây] (http://flatiron.engineering/technology/2016/09/13/uniqueness-in-postgres.html) bài viết hay về sự khác biệt –

Trả lời

82

Tôi đã có một số nghi ngờ về vấn đề cơ bản nhưng quan trọng này, vì vậy tôi quyết định tìm hiểu bằng ví dụ.

Hãy tạo bảng thử nghiệm chủ với hai cột, con_id với chế độc đáo và ind_id lập chỉ mục của chỉ số duy nhất.

create table master (
    con_id integer unique, 
    ind_id integer 
); 
create unique index master_unique_idx on master (ind_id); 

    Table "public.master" 
Column | Type | Modifiers 
--------+---------+----------- 
con_id | integer | 
ind_id | integer | 
Indexes: 
    "master_con_id_key" UNIQUE CONSTRAINT, btree (con_id) 
    "master_unique_idx" UNIQUE, btree (ind_id) 

Trong mô tả bảng (\ d trong psql) bạn có thể nói ràng buộc duy nhất từ ​​chỉ mục duy nhất.

độc đáo

Hãy kiểm tra tính độc đáo, chỉ trong trường hợp.

test=# insert into master values (0, 0); 
INSERT 0 1 
test=# insert into master values (0, 1); 
ERROR: duplicate key value violates unique constraint "master_con_id_key" 
DETAIL: Key (con_id)=(0) already exists. 
test=# insert into master values (1, 0); 
ERROR: duplicate key value violates unique constraint "master_unique_idx" 
DETAIL: Key (ind_id)=(0) already exists. 
test=# 

Nó hoạt động như mong đợi!

phím Ngoại

Bây giờ chúng ta sẽ xác định chi tiết bảng với hai phím nước ngoài tham chiếu đến hai cột của chúng tôi trong chủ.

create table detail (
    con_id integer, 
    ind_id integer, 
    constraint detail_fk1 foreign key (con_id) references master(con_id), 
    constraint detail_fk2 foreign key (ind_id) references master(ind_id) 
); 

    Table "public.detail" 
Column | Type | Modifiers 
--------+---------+----------- 
con_id | integer | 
ind_id | integer | 
Foreign-key constraints: 
    "detail_fk1" FOREIGN KEY (con_id) REFERENCES master(con_id) 
    "detail_fk2" FOREIGN KEY (ind_id) REFERENCES master(ind_id) 

Vâng, không có lỗi. Hãy chắc chắn rằng nó hoạt động.

test=# insert into detail values (0, 0); 
INSERT 0 1 
test=# insert into detail values (1, 0); 
ERROR: insert or update on table "detail" violates foreign key constraint "detail_fk1" 
DETAIL: Key (con_id)=(1) is not present in table "master". 
test=# insert into detail values (0, 1); 
ERROR: insert or update on table "detail" violates foreign key constraint "detail_fk2" 
DETAIL: Key (ind_id)=(1) is not present in table "master". 
test=# 

Cả hai cột đều có thể được tham chiếu bằng khóa ngoài.

Hạn chế sử dụng chỉ số

Bạn có thể thêm bảng hạn chế sử dụng chỉ số duy nhất hiện có.

alter table master add constraint master_ind_id_key unique using index master_unique_idx; 

    Table "public.master" 
Column | Type | Modifiers 
--------+---------+----------- 
con_id | integer | 
ind_id | integer | 
Indexes: 
    "master_con_id_key" UNIQUE CONSTRAINT, btree (con_id) 
    "master_ind_id_key" UNIQUE CONSTRAINT, btree (ind_id) 
Referenced by: 
    TABLE "detail" CONSTRAINT "detail_fk1" FOREIGN KEY (con_id) REFERENCES master(con_id) 
    TABLE "detail" CONSTRAINT "detail_fk2" FOREIGN KEY (ind_id) REFERENCES master(ind_id) 

Bây giờ không có sự khác biệt giữa mô tả ràng buộc cột.

chỉ số phần

Trong tuyên bố hạn chế bảng bạn không thể tạo chỉ một phần. Nó đến trực tiếp từ số definition của create table .... Trong khai báo chỉ mục duy nhất, bạn có thể đặt WHERE clause để tạo chỉ mục một phần. Bạn cũng có thể create index trên biểu thức (không chỉ trên cột) và xác định một số thông số khác (đối chiếu, sắp xếp thứ tự, vị trí NULL).

Bạn không thể thêm ràng buộc bảng bằng chỉ mục từng phần.

alter table master add column part_id integer; 
create unique index master_partial_idx on master (part_id) where part_id is not null; 

alter table master add constraint master_part_id_key unique using index master_partial_idx; 
ERROR: "master_partial_idx" is a partial index 
LINE 1: alter table master add constraint master_part_id_key unique ... 
          ^
DETAIL: Cannot create a primary key or unique constraint using such an index. 
21

hơn Một lợi thế của việc sử dụng UNIQUE INDEX vs UNIQUE CONSTRAINT là bạn có thể dễ dàng DROP/CREATE một chỉ số CONCURRENTLY, trong khi với một hạn chế bạn không thể.

+2

AFAIK nó không thể thả đồng thời một chỉ số duy nhất. https://www.postgresql.org/docs/9.3/static/sql-dropindex.html "Có một số lưu ý cần lưu ý khi sử dụng tùy chọn này. Chỉ có thể chỉ định một tên chỉ mục và tùy chọn CASCADE không được hỗ trợ (Do đó, một chỉ mục hỗ trợ một ràng buộc UNIQUE hoặc PRIMARY KEY không thể bị loại bỏ theo cách này.) " –

2

Tính duy nhất là một ràng buộc. Nó sẽ xảy ra được thực hiện thông qua việc tạo ra của một chỉ mục duy nhất vì chỉ mục có thể nhanh chóng tìm kiếm tất cả các giá trị hiện tại để xác định xem một giá trị đã cho đã tồn tại hay chưa.

Khái niệm chỉ mục là chi tiết triển khai và tính duy nhất phải là chỉ được liên kết với các ràng buộc.

The full text

Vì vậy hiệu suất tốc độ nên cùng

Các vấn đề liên quan