做项目时发现我们项目居然是直接用时间戳做为自定义主键,导致批量新增时报错,就查了一波自定义主键策略,集众家之所长,汇成这篇文章。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.数据库管理系统自增长主键策略
优点:简单,不需要程序特别处理。字段长度小,占用存储空间小,无论是在内存还是硬盘上。类型为数字类型,方便内部的比较和排序,对于查找有优势。如果同时也将其建立为聚集索引,那么其他列上的非聚集索引所需存储的内容会更少。由于其顺序增长,磁盘碎片少。
缺点:这种方法对以后如果项目移植到其他数据库上改动会比较大,oracle和db2采用Sequence,mysql和sqlserver采用自增长,通用性不强。仅为代理键,无实际意义。
(对于系统中大部分实际的业务功能采用1的自增长策略,这样可以减少开发工作量,并且性能和并发都有保障。如果项目需要进行移植,业务功能这部分则会有变动,做二次开发可暂时不考虑移植性。如果数据不会删除可以考虑使用自增列,如果会删除且删除频繁则会造成主键的极大浪费。)
2.时间戳+随机数
优点:实现简单,与数据库无关,移植性较好。
缺点:长度太大,最少也得20位,不仅占空间并且建立索引的话性能较差。
(对于某些流水、日志类的表可采用时间戳+随机数,时间戳做主键会更有意义。但是当并发比较大时,此方案无法保证不重复,而一个系统中也就几个功能并发会较大,对这些并发大功能的可以使用其他主键生成策略,如uuid,不过uuid生成的id太长)
3.每次取主键最大值+1作为新的主键
优点:主键长度可控,移植性较好。
缺点:并发写可能会造成主键冲突,不便于控制并发。
(项目基础功能部分,例如菜单功能管理,用户管理,权限管理,机构组织管理,参数管理等采用此方案合适,这些功能一般数据量不大,基本没有大的性能问题和并发问题,进行移植改动较小。单个jvm下堪用,分布式环境下此方案不通)
4.单独建一个存放主键的表
优点:实现简单,移植性较好。
缺点:需要考虑并发问题,整个系统主键生成都依赖该表,性能影响可能较大。