【转】数据库主键的设计和思考
自增主键
这种方式是使用数据库提供的自增数值型字段作为自增主键,它的优点是:
- 数据库自动编号,速度快,而且是增量增长,按顺序存放,对于检索非常有利;
- 数字型,占用空间小,易排序,在程序中传递也方便;
- 如果通过非系统增加记录时,可以不用指定该字段,不用担心主键重复问题。
其实它的缺点也就是来自其优点,缺点如下:
- 因为自动增长,在手动要插入指定ID的记录时会显得麻烦,尤其是当系统与其它系统集成时,需要数据导入时,很难保证原系统的ID不发生主键冲突(前提是老系统也是数字型的)。特别是在新系统上线时,新旧系统并行存在,并且是异库异构的数据库的情况下,需要双向同步时,自增主键将是你的噩梦;
- 在系统集成或割接时,如果新旧系统主键不同是数字型就会导致修改主键数据类型,这也会导致其它有外键关联的表的修改,后果同样很严重;
- 若系统也是数字型的,在导入时,为了区分新老数据,可能想在老数据主键前统一加一个字符标识(例如“o”,old)来表示这是老数据,那么自动增长的数字型又面临一个挑战。
MySQL(auto_increment)、SQL Server(IDENTITY)、Informix、Oracle(首先创建自增序列,接着为自增主键的表创建插入时的触发器,给自增主键ID赋值)等数据库都支持这种自增主键,这种主键在各种系统中应用广泛,但是如果考虑到有新旧系统并存等问题,为了避免不必要的麻烦,使用自增主键要三思。
GUID主键
目前一个比较好的主键是采用GUID(Globally Unique Identifier,全球唯一标识符),GUID的特点如下:
- 在空间上和时间上具有唯一性,保证同一时间不同地方产生的数字不同;
- 世界上的任何两台计算机都不会生成重复的GUID值;
- 需要GUID的时候,可以完全由算法自动生成,不需要一个权威机构来管理;
- GUID的长度固定,并且相对而言较短小,非常适合于排序、标识和存储。
可以将GUID主键定义为字符型,但值由GUID生成,GUID是可以自动生成,也可以程序生成,而且键值不可能重复,可以解决系统集成问题,几个系统的GUID值导到一起时,也不会发生重复,就算有“o”老数据也可以区分,而且效率很高。在SQL里也可以使用 NewID()生成。主要优点是:
- 同 IDENTITY 列相比,uniqueidentifier列可以通过 NewID()函数提前得知新增加行的ID,为应用程序的后续处理提供很大方便;
- 便于数据库移植,其它数据库中并不一定具有 IDENTITY 列,而 GUID列可以作为字符型列转换到其它数据库中,同时将应用程序中产生的GUID值存入数据库,它不会对原有数据带来影响。
缺点是:
- GUID值较长,不容易记忆和输入,而且这个值是随机、无顺序的。
- GUID的值有16个字节,与其它诸如 4 字节的整数相比要相对大一些。这意味着如果在数据库中使用uniqueidentifier键,可能会带来两方面的消极影响:存储空间增大、索引时间较慢。
基于上面的分析,使用GUID的利大于弊,笔者推荐可以采用此种方式。