简介:了解MySQL为何推荐使用自增ID作为主键,深入分析UUID和雪花ID在性能、索引、页分裂等方面的劣势,帮助你优化数据库设计与性能
在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究竟有什么坏处?本篇博客我们就来分析这个问题,探讨一下内部的原因。
分别是user_auto_key, user_uuid, user_random_key,分别表示自动增长的主键,uuid作为主键,随机key作为主键,其它我们完全保持不变.根据控制变量法,我们只把每个表的主键使用不同的策略生成,而其他的字段完全一样,然后测试一下表的插入速度和查询速度:
注:这里的随机key其实是指用雪花算法算出来的前后不连续不重复无规律的id:一串18位长度的long值
id自动生成表:
CREATE TABLE user_key_auto (
id int UNSIGNED PRIMARY KEY auto_increment,
user_id BIGINT(64) nOt NULL DEFAULT O,
user_name VARCHAR(64) NOT NULL DEFAULT ''
sex INT ( 2 ) NOT NULL,
address VARCHAR (255) NOT NULL DEFAULT '',
city VARCHAR (64) NOT NULL DEFAULT ''
email VARCHAR (64) NOT NULL DEFAULT '',
state INT(6) NOT NULL DEFAULT O,
key user_name key(user_name)
)ENGINE=INNODB;
用户uuid表
CREATE TABLE user_ uuid(
id varchar(36) PRIMARY KEY,
user_id BIGINT(64) nOt NULL DEFAULT O,
user_name VARCHAR(64) NOT NULL DEFAULT ''
sex INT ( 2 ) NOT NULL,
address VARCHAR (255) NOT NULL DEFAULT '',
city VARCHAR (64) NOT NULL DEFAULT ''
email VARCHAR (64) NOT NULL DEFAULT '',
state INT(6) NOT NULL DEFAULT O,
key user_name key(user_name)
)ENGINE=INNODB;
随机主键表:
CREATE TABLE user_ random_key(
id int UNSIGNED PRIMARY KEY,
user_id BIGINT(64) nOt NULL DEFAULT O,
user_name VARCHAR(64) NOT NULL DEFAULT ''
sex INT ( 2 ) NOT NULL,
address VARCHAR (255) NOT NULL DEFAULT '',
city VARCHAR (64) NOT NULL DEFAULT ''
email VARCHAR (64) NOT NULL DEFAULT '',
state INT(6) NOT NULL DEFAULT O,
key user_name key(user_name)
)ENGINE=INNODB;
现在我们已经创建好了测试表,接下来就可以通过脚本插入测试数据。我们来看看不同表插入数据的结果:
在已有数据量为130W的时候:我们再来测试一下插入10w数据,看看会有什么结果:
可以看出在数据量100W左右的时候,uuid的插入效率垫底,并且在后序增加了130W的数据,uudi的时间又直线下降。时间占用量总体可以打出的效率排名为:
auto_key>random_key>uuid
uuid的效率最低,在数据量较大的情况下,效率直线下滑。那么为什么会出现这样的现象呢?带着疑问,我们来探讨一下这个问题:
使用自增id的内部结构:
自增的主键的值是顺序的,所以Innodb把每一条记录都存储在一条记录的后面。当达到页面的最大填充因子时候(innodb默认的最大填充因子是页大小的15/16,会留出1/16的空间留作以后的 修改):
使用uuid的索引内部结构:
因为uuid相对顺序的自增id来说是毫无规律可言的,新行的值不一定要比之前的主键的值要大,所以innodb无法做到总是把新行插入到索引的最后,而是需要为新行寻找新的合适的位置从而来分配新的空间。这个过程需要做很多额外的操作,数据的毫无顺序会导致数据分布散乱,将会导致以下的问题:
在把随机值(uuid和雪花id)载入到聚簇索引(innodb默认的索引类型)以后,有时候会需要做一次OPTIMEIZE TABLE来重建表并优化页的填充,这将又需要一定的时间消耗。
结论:
使用innodb应该尽可能的按主键的自增顺序插入,并且尽可能使用单调的增加的聚簇键的值来插入新行
有遗漏或者不对的可以在我的公众号留言哦