自增主键和UUID的区别和选择
自增主键的介绍和优缺点
- 设计表时,将id字段的值设置为自增的形式,当插入一行数据时,无需指定id会自动根据前一字段的ID值+1 进行填充,mysql中可通过
auto-increment
来实现。 - 在分布式业务环境下,需要考虑业务的拓展情况设置步长,比如有三台服务器,就把步长设置为3,起始值分别为(1,2,3),这样三张表的主键就绝对不会重复了,而且也不用另外做三张表的逻辑关联了。
修改MySQL【默认自动增长的步长】
set global auto_increment_increment=1; — 设置序列的增长值
show global variables; — 显示所有的global变量
show global variables like ‘%test%’ — 查询包含test字符串的global变量
自增主键的好处
- 字段长度小于uuid,可以是bigint甚至int类型,使用innodb引擎时,根据索引找到主键,再找记录。–读取性能高。
- 自增的主键是有顺序的,所以innodb把新的记录存储在最后一条记录的后面。因为如此,mysql定位和寻址的速度很快,不会为了计算新行的位置而额外的消耗性能–写入性能高
- 当页面达到最大填充因子的时候(默认是
15/16
,会留出1/16
的空间留作以后的修改)下一条记录会写入新的页中,主键页近乎于顺序的方式把记录填满,提升了页面的最大填充率,不会有页的浪费。-- 空间占用小 - 增加记录时,可以不指定id字段,也不需要担心主键重复问题
自增主键的问题
- 高并发的情况下,插入时会造成明显的锁争用,并发插入会导致间隙锁的竞争。
Auto_increment
锁机制会造成自增锁的抢夺,会有性能损失。- 如果数据被爬取了,竞争对手可以通过自增id的数字来判断出业务增长信息以及经营状况。
UUID的介绍和优缺点
在一台机器上生成的数字,保证对同一时空中所有的机器都是唯一的,在一定范围内保证主键id的唯一性
UUID的好处
- 不会产生冲突,进行数据拆分,合并存储时都可以做到全局唯一
- 在应用层生成,提高数据库吞吐能力(自增的会产生自增锁竞争)
- 安全性高,无法被分析业务和经营情况
UUID的问题
- 严重影响插入速度!uuid是毫无规律可言的,innodb无法做到总是把新行插入索引的最后,所以在插入时需要为新行寻找合适的位置来分配新的空间,这个过程会产生很多额外的操作。
- 写入的目标页可能已经刷新到磁盘上或者从缓存中移除了,或者还没加载到缓存。
innodb在插入这条数据时不得不先找到该页,并加载到内存中,这将导致大量的随机IO。 - 因为写入是乱序的,innodb不得不频繁的做页分裂操作,以便为新的行分配空间,页分裂会导致移动大量的数据,而且一次插入最少需要修改三个页以上。
- 由于频繁的页分裂,页会变得稀疏并被不规则地填充,最终会导致数据有碎片。
- 写入的目标页可能已经刷新到磁盘上或者从缓存中移除了,或者还没加载到缓存。
为什么uuid插入时比自增ID要慢
对于InnoDB这种聚集主键类型的引擎来说,数据会按照主键进行排序,由于UUID的无序性,InnoDB会产生巨大的IO压力,而且由于索引和数据存储在一起,字符串做主键会造成存储空间增大一倍。
在存储和检索的时候,innodb会对主键进行物理排序,这对auto_increment_int
是个好消息,因为后一次插入的主键位置总是在最后。
但是对uuid来说,这却是个坏消息,因为uuid是杂乱无章的,每次插入的主键位置是不确定的,可能在开头,也可能在中间,在进行主键物理排序的时候,势必会造成大量的 IO操作影响效率,在数据量不停增长的时候,特别是数据量上了千万记录的时候,读写性能下降的非常厉害。
其他数据库主键生成方式
1.ID生成服务器(不推荐)
- 建立两台以上的数据库ID生产服务器,每个服务器都有一张记录当前各表当前ID的MaxId表,MaxId中Id的增长步长是id生成服务器的数量。
ID生成服务器的好处
- 生成id较短,友好型比较好
- 将产生ID的压力均匀分散在多台id生成服务器上
- 当一个服务器失效后,系统能自动切换到另外一个服务器获取id,解决了因为单点问题导致的系统的错误。
ID生成服务器的坏处
- 把主键生成放到外部服务器进行,那么就不得不通过网络通信来完成主键值的传递,而网络是计算机体系里效率最低的方式,在数据量大,新增操作频繁时会成为关键的短板和瓶颈。
- 当要添加id生成器的新节点时,需要对原有数据重新根据步长计算迁移数据。
- 多服务器会面临引入集群系统带来的风险和工作量,为系统开发增加了开发难度和运维风险,没有必要自讨苦吃。
2.COMB主键:GUID+时间戳 (推荐)
“COMB”(combined guid/timestamp),意思是:组合GUID/时间截
- 传统使用GUID会因为数据毫无规律可言而导致数据库插入时产生的性能问题,以及索引效率低下。(见UUID部分)
- COMB方式通过保留GUID的10个字节,用另外6个字节表示生成GUID的时间,这样再组合起来成为COMB主键。
COMB主键的好处
- 保留了GUID的全局唯一性
- 增加了GUID的有序性,提升了索引效率,也避免了插入时诸如页分裂这些的操作。
COMB主键的坏处
- 生成的id不友好,占据了32位
- 因为id长度问题,索引效率较差
500w级数据测试
- 2.1 录入500W数据,自增ID节省一半磁盘空间
- 2.2 单个数据走索引查询,自增id和uuid相差不大
- 2.3 范围like查询,自增ID性能优于UUID
- 2.4 写入测试,自增ID是UUID的4倍
- 2.5、备份和恢复,自增ID性能优于UUID