我有一个在Postgres中的多对多连接表,我想索引到A)增加性能(显然)和B)强制唯一性。例如:Postgres独特的多列索引连接表
a_id | b_id
1 | 2 <- okay
1 | 3 <- okay
2 | 3 <- okay
1 | 3 <- not okay (same as row 2)
是否有可能在两列上实现一个强制唯一性的值的索引?我应该使用什么类型的索引?
我有一个在Postgres中的多对多连接表,我想索引到A)增加性能(显然)和B)强制唯一性。例如:Postgres独特的多列索引连接表
a_id | b_id
1 | 2 <- okay
1 | 3 <- okay
2 | 3 <- okay
1 | 3 <- not okay (same as row 2)
是否有可能在两列上实现一个强制唯一性的值的索引?我应该使用什么类型的索引?
这样做,如果是唯一的主键:
create table tbl(
a_id int not null,
b_id int not null,
constraint tbl_pkey primary key(a_id,b_id)
);
这样做,如果是唯一的非主键:
create table tbl(
-- other primary key here, e.g.:
-- id serial primary key,
a_id int not null,
b_id int not null,
constraint tbl_unique unique(a_id,b_id)
);
如果现有的表,而是执行此操作:
alter table tbl
add constraint tbl_unique unique(a_id, b_id)
能改变表显示此消息:
NOTICE: ALTER TABLE/ADD UNIQUE will create implicit index "tbl_unique" for table "tbl"
Query returned successfully with no result in 22 ms.
如果你想丢弃约束(您可能要使3个字段的组合独特):
ALTER TABLE tbl DROP CONSTRAINT tbl_unique;
关于索引,从Postgres的DOC:
PostgreSQL自动当一个独特 约束或主键对表
源定义的唯一索引: http://www.postgresql.org/docs/9.1/static/indexes-unique.html
如果唯一依赖于一些规则,您应使用CREATE UNIQUE INDEX
,例如:
鉴于此:
CREATE TABLE tbl
(
a_id integer NOT NULL,
b_id integer NULL
);
alter table tbl
add constraint tbl_unique unique(a_id, b_id);
独特能赶上这些重复,这将是由数据库拒绝:
insert into tbl values
(1,1),
(1,1);
然而,唯一约束不能捕获重复的空值。空值用作未知数,它们用作通配符,这就是为什么允许有多个空值的唯一约束。这将通过数据库被接受:中UNIQUE CONSTRAINT
insert into tbl values
(1,1),
(1,null), -- think of this null as wildcard, some real value can be assigned later.
(1,null); -- and so is this. that's why both of these nulls are allowed
认为它允许延期的独特性,因此接受上述空值。
如果每个a_id只需一个通配符(空b_id),除了唯一约束之外,您需要添加一个UNIQUE INDEX
。唯一约束不能有一个表达式。 INDEX
和UNIQUE INDEX
即可。这将是您完整的DDL拒绝多个null;
这将是你的完整DDL:
CREATE TABLE tbl
(
a_id integer NOT NULL,
b_id integer NULL
);
alter table tbl
add constraint tbl_unique unique(a_id, b_id);
create unique index tbl_unique_a_id on tbl(a_id) where b_id is null;
这将通过你的数据库现在被拒绝:
insert into tbl values
(1,1),
(1,null),
(1,null);
这将被允许:
insert into tbl values
(1,1),
(1,null);
相关http://www.ienablemuch.com/2010/12/postgresql-said-sql-server2008-said-non.html
除了使用由@迈克尔布恩作为解释PRIMARY KEY
和UNIQUE
语法,你也可以创建一个明确的指标:
CREATE UNIQUE INDEX foo_a_b ON tbl(a_id, b_id);
这仅仅是一个正常的,多列B树索引(这正是KEY语法隐式创建)。
请注意,虽然(a_id,b_id)上的多列索引也可用于仅在a_id上进行搜索,但它不能用于仅b_id上的搜索。所以你可能想在b_id上创建第二个单列索引。 – Eelke
@Eelke感谢您添加该信息。我链接到这里的文档以供参考:http://www.postgresql.org/docs/7.4/static/indexes-multicolumn.html我只是想知道他们为什么不再强调多列索引仍然可以被使用版本9.1文档中单独使用a_id(但不能使用b_id)doc http://www.postgresql.org/docs/9.1/static/indexes-multicolumn.html –
@Eelke很棒的观察!当我解释一些查询并且切换索引的顺序来修复它时,我只是有一个WTF时刻。 – bloudermilk