文章目录
- 1.原因
- 2.使用uuid(或雪花ID)和自增id的索引结构对比
- 2.1 使用自增id的内部结构
- 2.2 使用uuid(或雪花ID)的索引内部结构
- 2.3 使用自增id的缺点
1.原因
使用UUID或雪花ID(Snowflake ID)作为主键并不是完全不推荐的,而是根据具体的应用场景和需求来决定是否适合。
以下是一些不推荐使用UUID或雪花ID作为主键的原因:
- 存储空间:UUID是一个
128位的值
,而雪花ID通常是64位
。相比之下,使用较短的整数或自增ID作为主键将占用更少的存储空间
。这在大规模的数据库中尤为重要,可以节省磁盘空间、内存和网络带宽。 - 索引效率:UUID和雪花ID是
随机生成
的,没有顺序性可言。这导致在使用这些主键作为索引时,索引树的深度增加,查询效率下降
。相比之下,使用自增ID或有序的整数主键可以使索引更加紧凑和快速。 - 数据库碎片化:使用UUID作为主键可能会导致
数据库碎片化
的问题。因为UUID是随机生成的,数据写入时经常涉及到页面的分裂和重组
,增加了磁盘I/O操作的频率
,影响了性能。 - 难以读取和调试:由于UUID和雪花ID是较长的字符串或数字,对于人类来说不太易读和理解。在调试、分析以及人工处理数据时,使用较短的整数或自增ID作为主键更加方便。
然而,使用UUID或雪花ID作为主键也有其优势。例如,在分布式环境中,使用UUID或雪花ID可以确保全局唯一性
,而不需要单个中心化的发号器。此外,使用UUID可以提供更好的数据隐私保护,因为它们具有较高的随机性。
2.使用uuid(或雪花ID)和自增id的索引结构对比
2.1 使用自增id的内部结构
自增的主键的值是顺序的
,所以Innodb把每一条记录都存储在一条记录的后面。当达到页面的最大填充因子
时候(innodb默认的最大填充因子是页大小的15/16
,会留出1/16的空间留作以后的修改
):
①下一条记录就会写入新的页中,一旦数据按照这种顺序的方式加载,主键页就会近乎于顺序的记录填满
,提升了页面的最大填充率
,不会有页的浪费
②新插入的行一定会在原有的最大数据行下一行
,mysql定位
和寻址很快
,不会为计算新行的位置而做出额外的消耗
③减少了页分裂和碎片的产生
2.2 使用uuid(或雪花ID)的索引内部结构
因为uuid相对顺序的自增id来说是毫无规律可言的,新行的值不一定要比之前的主键的值要大,所以innodb无法做到总是把新行插入到索引的最后
,而是需要为新行寻找新的合适的位置从而来分配新的空
。这个过程需要做很多额外的操作,数据的毫无顺序会导致数据分布散乱
,将会导致以下的问题:
①:写入的目标页很可能已经刷新到磁盘上并且从缓存上移除,或者还没有被加载到缓存中,innodb在插入之前不得不先找到并从磁盘读取目标页到内存中,这将导致大量的随机IO
②:因为写入是乱序的,innodb不得不频繁的做页分裂操作
,以便为新的行分配空间
,页分裂导致移动大量的数据
,一次插入最少需要修改三个页以上
③:由于频繁的页分裂
,页会变得稀疏并被不规则的填充
,最终会导致数据会有碎片
在把随机值(uuid和雪花id)载入到聚簇索引(innodb默认的索引类型)以后,有时候会需要做一次OPTIMEIZE TABLE来重建表并优化页的填充
,这将又需要一定的时间消耗。
2.3 使用自增id的缺点
- 安全问题:如果采用自增主键,可能存在根据
ID值爬取数据库记录
,有安全风险; - 系统重构:系统重构或者与其他系统集成时,可能存在
新老主键冲突
; - 高并发负载,innodb在按主键进行
插入
的时候会造成明显的锁争用
,主键的上界会成为争抢的热点,因为所有的插入都发生在这里
,并发插入会导致间隙锁竞争
; - Auto_Increment锁机制会造成
自增锁的抢夺
,有一定的性能损失; - 自增
主键有限
,要考虑主键长度问题。
参考链接:MySql为什么不推荐使用UUID做主键