常用主键
常用主键
1)自增
int、bigint等,顺序递增。
2)雪花
雪花算法是因为有时间参数,所以是有序地,而且都是由数字组成。雪花id最大为64位,符合java中long的长度64位,适用于大规模分布式场景。
3)UUID
在一定的范围内唯一的机器生成的标识符,通用唯一标识符
优劣分析
1)UUID
优势:
随机生成,永不重复。
缺点:
uuid中带有字符串,32位字符串会占用更大的空间,无序的字符串作数据库主键,每次插入数据库的时候,MySQL为了维护B+树结构,需要频繁调整节点顺序,影响性能。
2)雪花
优势:
2.1引入了时间戳,保证ID能够按照时间有序生成,索引效率高。
2.2 分布式系统不会产生ID碰撞,并且效率较高。
2.3高性能高可用:不依赖第三方库或者中间件,完全在内存中生成,可用性强
2.4 容量大:每秒中能生成数百万的自增ID。
缺点:
依赖与系统时间的一致性,如果系统时间被回调,或者改变,可能会造成id冲突或者重复。
3)自增
优势:
3.1 InnoDB为聚集索引,索引查询效率更高。
3.2 存储和索引文件占用磁盘空间更少(500W数据,UUID占5.4G,自增ID占2.5G,该数据有待验证)
3.3 表读写效率高
缺点:
3.1分布式架构,多个Mysql实例ID重复问题控制不方便。
3.2 容易被外界猜测业务实际数据量。如:文章内容aritle?id=3,易被篡改为aritle?id=5,从而获取id为5的内容。
3.3 对于分库操作id自增控制不方便。
自增溢出问题
有人或许会担心自增id用完后又如何?
先说结论:不必担心。
再说原因:
MySQL常用数字及其占用字节与其范围:
其中bigint有符号值:-9223372036854775808 到9223373036854775807(- 2 ^ 63 到 2 ^ 63-1)
无符号值:0到18446744073709551615(0到2^64 – 1)
创建表时 自增长字段 选择无符号bigint,那么自增长最大值是 18446744073709551615
如果达到最大值后,不主动设置主键则报错,如果主动设置后重复同样报错。
业务概念
一秒增加的记录条数 | 大约多少年后才会用完 |
---|---|
1/秒 | 584942417355 年 |
1万/秒 | 58494241 年 |
100万/秒 | 584942 年 |
1亿/秒 | 5849年 |
每秒1亿的数据量,需要五千年才能用完,五千年什么概念?中华上下五千年吗?^_^
每秒1亿数据量又是什么概念,网络不会有瓶颈??MySQL单表数据量分库的上限是多少??读写瓶颈的上限又是多少??2KW纯读已不可接受,1亿能忍??在此之前网络、读写瓶颈恐怕早已出现。
无主键又如何
如果在创建表没有显示申明主键,InnoDB会自动帮你创建一个不可见的、长度为6字节的row_id,而且InnoDB 维护了一个全局的 dictsys.row_id,所以未定义主键的表都共享该row_id,每次插入一条数据,都把全局row_id当成主键id,然后全局row_id加1,该全局row_id在代码实现上使用的是bigint unsigned类型,但实际上只给row_id留了6字节,这种设计就会存在一个问题:如果全局row_id一直涨,一直涨,直到2的48幂次-1时,这个时候再+1,row_id的低48位都为0,结果在插入新一行数据时,拿到的row_id就为0,存在主键冲突的可能性,但也不必担心,原因见上述bigint业务量说明。
但是,实际开发中每个表都必须定主键。