为什么不建议使用UUID做MySQL主键?

74 阅读2分钟

一、前言

小伙伴们可能都听过MySQL不推荐使用UUID作为主键,但是却不知道其中原因,下面我们来一起分析一下。

二、什么是UUID

UUID(通用唯一识别码)的标准长度是128位(16字节),通常表示为32个十六进制字符,分为五段(8-4-4-4-12格式),如下图所示:

image-20250924150903418.png

我们可以看到,UUID的生成不依赖于数据库,可以在应用层生成。UUID的128位长度是其核心设计特征,确保了全球范围内的唯一性。具体表现为:

  1. 二进制位长‌:固定为128位(16字节),通过算法生成时直接占用此空间。‌‌
  2. 十六进制表示‌:
    • 转换为32个十六进制字符(每个字符代表4位),例如550e8400-e29b-41d4-a716-446655440000。‌‌
    • 连字符分隔的五段结构(8-4-4-4-12)仅为可读性设计,不影响实际位长。‌‌

三、为什么不推荐使用UUID作为MySQL主键?

1.占用太多存储空间

UUID是字符串类型,每个UUID字符串由36个字符组成(32个十六进制数字+4个连字符),每个字符通常占用1字节,因此存储它需要占用总计‌36字节的空间‌。而自增ID如果使用BIGINT类型,那么只需要8个字节。如果你的表中有一千万条数据,如果使用的是UUID作为主键,那么光是主键字段就要多占用280MB的存储空间。

2.无序性和性能问题

UUID的值是随机生成的,是没有顺序的。在MySQL中,索引的数据结构通常是B+树,节点的数据是有序的,如果使用UUID作为主键,每次插入数据,新的UUID可能需要插入到索引树的中间位置,造成页分裂,表的再平衡,在数据量越大的情况,性能影响越严重。自增ID是顺序生成的,这意味着新数据总是按顺序插入,这有利于保持索引的连续性和紧凑性。

页分裂:数据页正常被写满时,B+树被“拆分”,部分数据被移到新页。页分裂主要出现在数据乱序插入时,需要插入到数据页的中间位置,并且数据页已经没有办法存下插入的数据(页的大小是16K),就需要考虑页分裂,拉取一个新的空白页,并将新纪录和原数据页的部分内容迁移,顺序插入能极大降低页分裂。页分裂的目的就是保证:后一个数据页中的所有行主键值比前一个数据页中主键值大。