Postgres唯一的约束与索引

我可以理解文档 ,下面的定义是等价的:

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); 

但是,您可以阅读注释: 向表中添加唯一约束的首选方法是ALTER TABLE … ADD CONSTRAINT。 使用索引来执行唯一约束可以被认为是不应该直接访问的实现细节

这只是一个很好的风格问题吗? select这些变体之一(例如,在演奏中)有什么实际后果?

我对这个基本而重要的问题有些怀疑,所以我决定以身作则。

我们创build两个列的testing表 ,具有唯一约束的con_id和由唯一索引索引的ind_id

 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) 

在表格描述(psql中的\ d)中,您可以从唯一索引中指出唯一约束。

唯一性

为了以防万一,我们来检查唯一性。

 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=# 

它按预期工作!

外键

现在我们将定义具有两个引用master的两个外键的详细表。

 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) 

那么,没有错误。 让我们确保它的工作。

 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=# 

这两列可以在外键中引用。

约束使用索引

您可以使用现有的唯一索引来添加表约束。

 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) 

现在列约束描述没有区别。

部分索引

在表约束声明中,您不能创build部分索引。 它直接来自create table ...的定义 。 在唯一索引声明中,可以设置WHERE clause来创build部分索引。 您也可以在expression式上创build索引 (不仅在列上),还可以定义其他一些参数(sorting规则,sorting顺序,NULLs布局)。

您不能使用部分索引添加表约束。

 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. 

使用UNIQUE INDEXUNIQUE CONSTRAINT另外一个好处是你可以很容易地DROP / CREATE一个索引CONCURRENTLY ,而有一个约束你不能。

唯一性是一个约束。 它恰好通过创build唯一索引来实现,因为索引能够快速search所有现有值,以确定给定值是否已经存在。

从概念上来说,索引是一个实现细节,唯一性只应与约束关联。

全文

所以速度performance应该是一样的