0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在mysql中设计表为什么不建议采用uuid呢?

OSC开源社区 来源:OSCHINA 社区 作者:京东云开发者-毛辰 2022-12-02 09:49 次阅读

背景

在 mysql 中设计表的时候,mysql 官方推荐不要使用 uuid 或者不连续不重复的雪花 id (long 形且唯一),而是推荐连续自增的主键 id,官方的推荐是 auto_increment,那么为什么不建议采用 uuid,使用 uuid 究竟有什么坏处?今天我们就来分析这个问题,探讨一下内部的原因。

数据展示

user_auto_key,user_uuid,user_random_key,分别表示自动增长的主键,uuid 作为主键,随机 key 作为主键,其它我们完全保持不变。根据控制变量法,我们只把每个表的主键使用不同的策略生成,而其他的字段完全一样,然后测试一下表的插入速度和查询速度: 注:这里的随机 key 其实是指用雪花算法算出来的前后不连续不重复无规律的 id: 一串 18 位长度的 long 值

0a6e97b8-717c-11ed-8abf-dac502259ad0.png

0a8f6182-717c-11ed-8abf-dac502259ad0.png

可以看出在数据量 100W 左右的时候,uuid 的插入效率垫底,并且在后续增加了 130W 的数据,uuid 的时间又直线下降。 时间占用量总体可以打出的效率排名为:auto_key>random_key>uuid,uuid 的效率最低,在数据量较大的情况下,效率直线下滑。

原因分析

对比一下 mysql 关于两者索引的使用情况. 自增的主键的值是顺序的,所以 Innodb 把每一条记录都存储在一条记录的后面。当达到页面的最大填充因子时候 (innodb 默认的最大填充因子是页大小的 15/16, 会留出 1/16 的空间留作以后的修改):

①下一条记录就会写入新的页中,一旦数据按照这种顺序的方式加载,主键页就会近乎于顺序的记录填满,提升了页面的最大填充率,不会有页的浪费

②新插入的行一定会在原有的最大数据行下一行,mysql 定位和寻址很快,不会为计算新行的位置而做出额外的消耗

③减少了页分裂和碎片的产生 因为 uuid 相对顺序的自增 id 来说是毫无规律可言的,新行的值不一定要比之前的主键的值要大,所以 innodb 无法做到总是把新行插入到索引的最后,而是需要为新行寻找新的合适的位置从而来分配新的空间。

这个过程需要做很多额外的操作,数据的毫无顺序会导致数据分布散乱,将会导致以下的问题:

①:写入的目标页很可能已经刷新到磁盘上并且从缓存上移除,或者还没有被加载到缓存中,innodb 在插入之前不得不先找到并从磁盘读取目标页到内存中,这将导致大量的随机 IO

②:因为写入是乱序的,innodb 不得不频繁的做页分裂操作,以便为新的行分配空间,页分裂导致移动大量的数据,一次插入最少需要修改三个页以上

③:由于频繁的页分裂,页会变得稀疏并被不规则的填充,最终会导致数据会有碎片 在把随机值(uuid 和雪花 id)载入到聚簇索引 (innodb 默认的索引类型) 以后,有时候会需要做一次 OPTIMEIZE TABLE 来重建表并优化页的填充,这将又需要一定的时间消耗。

自增 ID 的缺点: 那么使用自增的 id 就完全没有坏处了吗?并不是,自增 id 也会存在以下几点问题:

①. 别人一旦爬取你的数据库,就可以根据数据库的自增 id 获取到你的业务增长信息,很容易分析出你的经营情况

②. 对于高并发的负载,innodb 在按主键进行插入的时候会造成明显的锁争用,主键的上界会成为争抢的热点,因为所有的插入都发生在这里,并发插入会导致间隙锁竞争

③. Auto_Increment 锁机制会造成自增锁的抢夺,有一定的性能损失






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • MYSQL数据库
    +关注

    关注

    0

    文章

    95

    浏览量

    9277

原文标题:为什么mysql不推荐使用雪花ID作为主键

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    mysql为什么不推荐使用uuid呢?使用uuid究竟有什么坏处?

    分别是user_auto_key,user_uuid,user_random_key,分别表示自动增长的主键,uuid作为主键,随机key作为主键,其它我们完全保持不变。
    的头像 发表于 12-22 13:52 920次阅读
    <b class='flag-5'>mysql</b>为什么不推荐使用<b class='flag-5'>uuid</b>呢?使用<b class='flag-5'>uuid</b>究竟有什么坏处?

    labview 创建mysql 时 设置时间 怎么mysql是格式是date 而不是datetime?

    选择 时间日期 但是mysql是date而不是datetime类型 ,除了sql语句创建 ,怎么能实现创建
    发表于 02-04 09:46

    mysql中文参考手册chm

    问题 10.2.2.1 为数据库和表格使用符号链接 10.2.3 调节服务器参数 10.2.4 MySQL 怎样打开和关闭数据库 10.2.5 同一个数据库创建大量数据库
    发表于 12-26 13:32

    MySQL和MongoDB的对比

    数据库管理系统(RDBMS)。像其他关系系统一样,MySQL将数据存储,并使用结构化查询语言(SQL)来进行数据库访问。
    发表于 08-28 14:51

    MySQL分区类型及介绍

    MySQL5.7社区版本的分区功能是默认开启的。但当中含有主键或唯一键时,则每个被用作分区函数的字段必须是唯一键和主键的全部或一部
    发表于 06-29 16:31

    为什么建议设备频率大于1MHz时使用FRC

    HII使用PIC18F46K22。在数据,关于选择FRC作为转换时钟的评论建议建议设备频
    发表于 08-27 08:01

    如何选择uuid以确保它与标准服务的现有uuid冲突?

    CyPress DOC,我看到:“BLE SIG建议使用128位UUID,与基础UUID不同,用于自定义属性,以确保它不与标准服务的现有
    发表于 10-12 14:08

    如何利用labview获取MySQL数据库某一列的最大值

    如题,想获取MySQL数据库的data7那一列的最大值,下面是程序框图一直报语法错误,但是该语句mysql command line
    发表于 12-06 21:37

    请问UUID申明可以声明GATT_CHAR_USER_DESC_UUID吗?

    UUID申明可以声明GATT_CHAR_USER_DESC_UUID,和有通知功能的UUID可以声明GATT_CLIENT_CHAR_C
    发表于 03-09 09:02

    mysqlprofile如何使用

    mysqlprofile的使用
    发表于 04-24 15:05

    mysql的结构修改、约束

    mysql结构修改、约束(二)
    发表于 05-21 10:26

    JAVA如何生成UUID并作为数据库的ID

    JAVA生成UUID并作为数据库的ID
    发表于 06-02 16:59

    nRF51822S110协议栈用LightBlue收进来的UUID仍然是原来的UUID是为什么?

    本人昨天刚刚接手这个nRF51822芯片,之前项目是利用心率那个协议栈例程改的,现在要把心率的那个CHAR的UUID换掉,我协议站里面找到了一个static uint32_t
    发表于 06-09 15:08

    怎样低功耗蓝牙中使用服务uuid AD类型

    有没有哪位大神可以解释怎样低功耗蓝牙中使用服务uuid AD类型??
    发表于 12-12 06:15

    为什么不选择UUIDUUID有哪些特性

    这里面常用的就是 UUID4 了,但是,即使是随机的,但是也是存在冲突的风险。和 UUID 要么基于随机数,要么基于时间戳不同,ULID 是既基于时间戳又基于随机数,时间戳精确到毫秒,毫秒内有1.21e + 24个随机数,不存在冲突的风险,而且转换成字符串比
    的头像 发表于 10-13 10:29 933次阅读