关于数据库主键设计

最近要做一些系统的开发,说实话也是有些年没有在一线工作了,动手的激情和乐趣感觉慢慢的回来了。

系统是一个与微信公众平台有交互的课程系统。由于既要支持微信用户登录,又要支持其他注册登录方式,因此要自己设计会员系统。在做数据库设计的时候,一开始像多年前一样,第一反应是给每张表一个自增长数字id作为唯一标识。但总觉得哪里不太妥。于是决定重新思考这个以前认为是最佳实践的原则,参考了一些文档,得出如下结论:

1,自增长需要等待返回值才能知道主键的具体值,对于多表关联的情况,需要等主键生成后再插入该值到关联表中作为外键,程序逻辑变成了两步插入,不太方便。因此主键最好能预先赋值;(本例中会员ID要更新到微信openid与会员关系的映射表)

2,多系统数据库整合的时候,如果大家都是用自增长,那么很难保证唯一性,当值冲突的时候很麻烦。因此主键最好全局(全世界)唯一;(本例中要考虑未来与第三方的开源微信系统如weiphp或者we7等整合)

3,要满足以上要求,多半需要字符串型字段作为主键;

4,要考虑索引性能;

5,是否要考虑后生成的主键值要比之前的大,还需要再考虑。

基本确定采用字符串型的主键,能预先赋值,且能保证全局唯一性,兼顾性能。暂定GUID方案。

其实在考虑以上问题之前还有一个先确定用业务字段还是非业务字段做主键的问题。如果是选择了非业务字段做主键,再考虑主键的生成方案。其实关于用业务字段还是无意义的非业务字段做主键也有很多争论,其中有一个观点认为:非业务字段做主键也是有缺点的,很多查询语句会变得复杂很多。我是挺同意的。当然业务字段做主键则需要放置业务规则发生变化。

本例中的用户ID字段,属于本系统新增的内容,其对应的业务字段来源有多种,除了微信用户openid可能还有其他第三方的用户标识,不能保证唯一性且不排除有变化的可能,所以只能选择非业务字段。从而才有了上面的选择该字段生成方式的问题。

请参考:

博客:数据库主键的设计和思考

知乎:使用自增主键是否总是最佳实践?

segmentfault: 在数据库设计中,无论如何也该设计一个自增ID字段作为主键吗?