Mysql中关于主键设计的引发的思考
一、主键设计原则
- 尽量单列,提高连接和筛选效率
- 不包含动态变化的数据(时间戳,创建、修改时间列)
- 由计算机自动生成(选取合适的生成策略)
二、添加方式
- 手动建表指定生成策略
- 基于JPA的自动建表的合适的ID策略选取
三、常用方案(基于JPA的自动建表指定)
- GenerationType.TABLE:使用一个特定的数据库表格来保存主键,持久化引擎通过关系数据库的一张特定的表格来生成主键,这种策略的好处就是不依赖于外部环境和数据库的具体实现,在不同数据库间可以很容易的进行移植,但由于其不能充分利用数据库的特性,所以不会优先使用。
- GenerationType.SEQUENCE:在某些数据库中,不支持主键自增长,比如Oracle,其提供了一种叫做"序列(sequence)"的机制生成主键。此时,GenerationType.SEQUENCE就可以作为主键生成策略。
- GenerationType.IDENTITY:此种主键生成策略就是通常所说的主键自增长,数据库在插入数据时,会自动给主键赋值,比如MYSQL可以在创建表时声明"auto_increment" 来指定主键自增长。
- GenerationType.AUTO:把主键生成策略交给持久化引擎(persistence engine),持久化引擎会根据数据库在以上三种主键生成策略中选择其中一种。
-
还可使用注解@GenericGenerator,是HIbernate提供的自定义主键策略生成器,它需要和@GeneratedValue一起使用,并且它的name属性要和@GeneratedValue中的generator名称要一致,支持13种策略(包括uuid等)。
四、比较uuid和主键自增的区别
1.自增主键
优点
1) 数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利。
2) 数字型,占用空间小,易排序,在程序中传递方便。
缺点:
1) 不支持水平分片架构,水平分片的设计当中,这种方法显然不能保证全局唯一。
2) 表锁,InnoDb 5.1.22版本,为了解决自增主键锁表的问题,引入了参数innodb_autoinc_lock_mode。
3) 自增主键不连续,对表增加属性AUTO_INCREMENT=16时,主键就会从16开始自增起;实际的插入数据操作中,可 能存在不连续的主键值。
2. UUID
优点:
1) 全局唯一性、安全性、可移植性。
2) 能够保证独立性,程序可以在不同的数据库间迁移,效果不受影响。
3) 保证生成的ID不仅是表独立的,而且是库独立的,在你切分数据库的时候尤为重要
缺点:
1) 针对InnoDB引擎会徒增IO压力,InnoDB为聚集主键类型的引擎,数据会按照主键进行排序,由于UUID的无序性, InnoDB会产生巨大的IO压力。InnoDB主键索引和数据存储位置相关(簇类索引),uuid 主键可能会引起数据位置频繁 变动,严重影响性能。
2) UUID长度过长,一个UUID占用128个比特(16个字节)。主键索引KeyLength长度过大,而影响能够基于内存的索引记 录数量,进而影响基于内存的索引命中率,而基于硬盘进行索引查询性能很差。严重影响数据库服务器整体的性能表现。