数据库主键的选择 (原创)

工作了这么多年什么数据库的主键都用过,各种项目各种主键的变更,硬伤等等的问题都遇见过。

关与主键首先不要整个系统只使用一种方式的主键,要彻底吃透业务需求,根据需求考虑每张表的主键要怎么设计能给你带来最大的收益。

数据库常用的主键常用的四种:自增编号、Guid、自定义唯一、联合主键。 关于数据库主键的设计,如果设计的合理,会给整个系统带来很多优势。例如:降低开发难度少写很多代码、数据库检索效率、开移植性、可扩展性、可维护性、易读性等...对与主键来说,没有最好的,只有最合适的。

下面我根据我的经验以打分的形式来说说自己的看法,顺便介绍一下使用场景,这里主要对比【自增编号】与【GUID】,如果有不同看法的希望大家可以留言多交流。

一.对比

1.执行效率:自增编号由于采用int数值类型加上是有序存储,无论是检索、外键关联、还是操作增删改性能都是最高的。当然如果自定义唯一如果能保证有序并且使用数据类型效率也是很高的。GUID是无序的,而且varchar类型等检索速度肯定是不如int高。

自增编号(5分)、GUID(2分)、自定义唯一(3分,有序+1分,数据类型+1分)、联合主键(1~4分)

2.占用空间:自增编号一般是int占4位,GUID一般是占32位,可见如果是有几百万条数据的表int类型会节省不少空间。(当然现在的时代硬盘容易比起十几年前越来越大基本可以忽略不计)。注:这里在补充一句如果考虑流量的话是要考虑的例如你的终端需要跟服务接口有一次交易需要一次传输1000条数据的主键,如果使用int的话这里会省很多流量。

自增编号(5分)、GUID(2分)、自定义唯一(看自己设计的长度1~4)、联合主键(看自己设计的长度1~4)

3.安全性:这里我所只的安全性是大家在做BS项目中经常会在页面与页面之间或是页面与后台程序接口之间传递一些主键来实现要达到的目地。假如所有的参数都不做加密处理,那么int类型很容易可以被联想到其它的数据,可以在URL参数上随便改URL参数来操作数据库。GUID的话很难猜中联想到其它主键的数据。

 自增编号(1分)、GUID(5分)、自定义唯一(看情况)、联合主键(看情况)

4.可编程性:GUID可以在数据库操作之前就生成GUID,在操作数据库之前就可以赋值给其它从表,使得一次事务提交操作数据库。自增编号要做预插入得到数据库返回的一个主键值,再赋给其它从表做外键,再事务提交操作数据库。同样都使用事务自增编号要比GUID多与数据库产生一次交互。影响程序执行性能。由其是在做分布式开发项目中。这种方式是非常不可行的。在网络中传输的越频繁次数越多证明带来的风险执行成功率。

 自增编号(1分)、GUID(5分)、自定义唯一(看情况)、联合主键(看情况)

5.可扩展性:这里主要是只例如客户端业务数据向服务器汇总到一张表。或是EXCEL等其它做数据导入等。。。GUID由于是全球唯一优势明显,自增编号是硬伤,由于客户端本地数据库都是从1开始编号这样做服务端汇总到一张表肯定是实现不了的。

 自增编号(1分)、GUID(5分)、自定义唯一(看情况)、联合主键(看情况)

还有一些其它方面的小细节大家可在平时做设计开发中多总结。

二.使用场景

1.自增编号:一般用于表的操作简单单一不存在事务操作、像系统的基础信息表码表、菜单表,等等。。。

2.GUID:一般用于表的业务操作复杂涉及到做从表的主键、或者表导入导出修改回填操作、或者表做分布式开发需要客户端向服务端表汇总操作

3.自定义唯一:如果根据系统的业务需求能做出一套唯一体系的主键也是很不错的,主要是要考虑大并发获取生成主键这里能解决用这个是最好的。

4.联合主键:系统主键涉及到要有意义使用这个.例如你有100个客户端,每个客户端的名称缩写不同。你可以用客户端缩写+订单号两个列做联合主键。但是联合主键在开发的时候由其是从表要对应主表是联合主键外数就要写几个联合外键。

三.总结

1.有些时候你使用GUID做主键,你也可以加一个自增编号例在同一表中,只要对你的系统有用就有存在的价值。

2.在经常需要做数据迁移的系统中,建议用Guid。并且在相应的外键字段,也就是用来做连接查询的字段添加非聚集索引,对于改善性能有极大的好处。where条件的字段也可以适当添加非聚集索引。

3.在使用Guid类型作为主键时,数据类型应为uniqueidentifier,并且一定要记得取消主键的“聚集索引”

4.对于不需要做迁移,或小型系统,用int做主键还是很方便的,并且在效率方面还是有一定提升的。

5.如果涉及大并发执行插入数据最好不要使用自增编号会遇到瓶颈。建议大并发使用GUID。