大部分数据库表都有一个承接的功能就是某个表每条记录的唯一性,通过唯一性来保证这张表的数据是不重复的。使用的场景很多,例如银行,每个人只能开一个1类账户,怎么来保证所有的人来银行开账户都是第一个账户,如果不是就不进行记录,而走下一个流程去二类账户。
这里讨论的不是二类账户,而是怎么能让这个承接类账户的表仅仅只能保存唯一的一个人一次的申请。这里有几种方法,
1 每次来一个人进行账户申请,我们都差一次遍历这张表的身份证号,如果查到这个身份证号,就不给他录入,如果没有就录入。
2 建立身份证号字段的唯一性,只要有重复就没法插入
1 和 2 的方法之间的差异是 1 方法是要程序来做判断,在极个别的情况下,是不能保证这个表的100%的唯一性。方法2 则是通过数据库的方式,节省了程序查询的时间,如果有重复就直接报错了,然后反馈给程序信心,程序会进行下一步的操作。
大部分情况下,开发都倾向于方法2 ,所以就有今天的话题,POSTGRESQL 的唯一约束与唯一索引,之间到底有什么区别,用哪个更好的满足开发的需求。
废话不说,我们来建立两个表,分别来看看
CREATE TABLE public.account_unique
( user_id integer NOT NULL DEFAULT nextval('account_user_id_seq'::regclass),
username character varying(50) COLLATE pg_catalog."default" NOT NULL,
password character varying(50) COLLATE pg_catalog."default" NOT NULL,
email character varying(355) COLLATE pg_catalog."default" NOT NULL,
created_on timestamp without time zone NOT NULL,
last_login timestamp without time zone,
CONSTRAINT account_unique_pkey PRIMARY KEY (user_id)
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
建两张同样表结构的表
create unique index IX_account_unique_email on account_unique (email);
alter table account_constrain add constraint unique_account_constrain_email unique(email);
同样往两张表中插入相同的数据都不能继续插入。
我们可以看到两个表,虽然功能都能达到,但采用的方法是不同的。
那么到底这两种方法有什么不同,或者有什么适用点。
首先我们使用了最常用的功能,判断插入的一行是否和现在的数据冲突,记过两种方式都是可以的,并且都可以在有重复插入与唯一索引,或约束定义的字段冲突的时候,不进行任何的数据的插入操作。
当然在设计表的时候,无法是约束还是唯一索引如果你设置的表的字段都可以为null 则这个不属于约束和唯一索引控制的范畴,会存在多个NULL的存在。
通过查询相关的文档和一些专业网站的建议,其实这两者在最后的结果上并不会有太多的差异,并且速度也是一致,或差不多的,因为建立一个约束时其实在后台就已经开始建立一个唯一索引了。只不过可能在索引的角度你看不到罢了。
这里更倾向于唯一索引的建立来替代约束,原因是如果你要进行删除约束的操作,是不会有concurrently 的操作命令,这样给清理约束带来的难度(大表)是比较难的。
同时POSTGRESQL 的索引的建立也是可以添加WHERE条件的,所以灵活性比约束要高。
实际上要说约束和唯一索引的不同点更多的时候是在应用与逻辑的层面去理解,约束更偏向于逻辑层面,是对数据的唯一性,或者其他特性的一种制约,相对于唯一索引,相关的面要多,例如你可以设置约束为只能输入的数据为大于1000的数字,这也可以叫约束。但一般来说如果是唯一性来说,还是可以建立唯一索引来更好的解决问题,查阅相关的一些资料也指明,POSTGRESQL 的唯一约束也是在列上建立了唯一索引,但是不可见的,当然你也可以建立唯一索引,在建立约束,通过挂接的方式让约束使用唯一索引。当然大部分数据库建立了唯一索引后,都会有性能上的损失或者死锁加重的一些情况(高频的访问),那天可以找一期来说说唯一索引对POSTGRESQL 数据库造成的一些影响。