目录
数据库主键设计原则
- 确保主键无意义
- 减少主键变动(应该与重构索引有关)
- 采用整型主键
常见的主键方案:
自增ID:
优点:
数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利。
数字型,占用空间小,易排序,在程序中传递方便。
缺点:
当系统与其他系统集成时,需要数据导入时,很难保证原系统的ID不发生主键冲突。在多个数据库间进行数据的复制时(SQL Server的数据分发、订阅机制允许我们进行库间的数据复制操作),自动增长式字段可能造成数据合并时的主键冲突及表关联关系的丢失。
如果其他系统主键不是数字型,会导致修改主键数据类型,导致其他相关表的修改。
在数据缓冲模式下,很难预先填写主键与外键的值。
自增量的值都是需要在系统中维护一个全局的数据值,每次插入数据时即对此次值进行增量取值。当在产生唯一标识的并发环境中,每次的增量取值都必须为此全局值加锁解锁以保证增量的唯一性。造成并发瓶颈,降低查询性能。每创建一条记录都需要对表加一次锁,在高并发环境下开销较大。
UUID:
优点:
全局唯一性、安全性、可移植性。
能够保证独立性,程序可以在不同的数据库间迁移,效果不受影响。
保证生成的ID不仅是表独立的,而且是库独立的,在你切分数据库的时候尤为重要。
缺点:
InnoDB为聚集主键类型的引擎,数据会按照主键进行排序,由于UUID的无序性,InnoDB会产生巨大的IO压力。InnoDB主键索引和数据存储位置相关(簇类索引),uuid 主键可能会引起数据位置频繁变动,严重影响性能。
作为主键,UUID长度过长,主键索引KeyLength长度过大,而影响能够基于内存的索引记录数量,进而影响基于内存的索引命中率,而基于硬盘进行索引查询性能很差。严重影响数据库服务器整体的性能表现。
时间戳作为主键(主键冲突问题)
在设计数据库时,我们可以使用时间戳作为主键,但不应该使用时间戳作为主键,否则会产生问题
首先,当我们每次修改数据时,主键值会随着当前修改时间进行更新,如果同时更新多条数据就会造成主键冲突问题
例如:update student set name = 'bbbgsbz' where class = '1';
我们知道一个班级有多名学生,这样就好同时更新多名学生,造成主键冲突
当然我们可以设置主键在更新操作时不更新,但还是会出问题,例如:在高并发访问下同一秒钟插入的数据也会造成主键冲突,因为时间戳的粒度为秒级别,如果一秒钟插入多条数据仍会造成主键冲突,即使我们在业务层产生主键也是同一个道理