MySQL主键不推荐UUID,因其作为聚簇索引导致随机插入引发频繁页分裂、随机I/O和索引碎片,INSERT延迟升至1.5–4ms(自增ID仅0.2–0.5ms),单页存储量下降约60%,且二级索引体积膨胀、缓存命中率降低。

主键过长会显著拖慢插入性能
因为InnoDB的主键就是聚簇索引,新数据必须按主键值大小“插队”到B+树合适位置。如果主键是VARCHAR(36)(比如UUID),每次插入都可能触发页分裂、数据移动甚至磁盘回写——实测100万行插入,VARCHAR(36)主键比BIGINT慢10倍以上。顺序写入被破坏后,I/O从顺序变成随机,瓶颈立刻暴露。
二级索引体积爆炸且查询变慢
InnoDB所有二级索引的叶子节点都存储完整的主键值(不是指针)。主键越长,每个二级索引项就越大:
- 一个
VARCHAR(36)主键,UTF8MB4下实际占144字节(36×4) - 而
BIGINT只占8字节,相差18倍 - 同样100万条记录,二级索引可能多占上百MB磁盘空间
-
COUNT(*)这类全索引扫描操作,读取更多数据页 → 更多次磁盘I/O → 查询慢10倍以上
内存缓存效率急剧下降
InnoDB缓冲池(innodb_buffer_pool_size)里能缓存的索引页数量,和单页内能存多少索引项强相关。主键字段大,一页能存的索引项就少:
- 假设页大小16KB,
BIGINT主键 + 两个整型字段,一页可存约2000条索引记录 - 换成
VARCHAR(36)主键,一页可能只剩300条左右 - 缓存命中率下降 → 更多磁盘读 → QPS掉得明显
隐式主键风险:没设主键时MySQL自己选
如果建表时完全没定义PRIMARY KEY,InnoDB会悄悄找一个NOT NULL UNIQUE索引当主键;找不到就自建隐藏的ROW_ID(6字节)。但一旦你误设了个长字符串的唯一索引,比如email VARCHAR(255),它就可能被选为隐式主键——后果和显式用长字符串主键一样严重,而且更难察觉。
真正容易被忽略的是:主键长度影响的不只是“这个字段本身”,而是整个表的物理组织、所有二级索引、缓冲池效率,甚至备份恢复速度。哪怕业务上觉得“UUID看着方便”,也该先转成BINARY(16)再考虑是否放主键——但绝大多数场景,直接用AUTO_INCREMENT BIGINT仍是更稳的选择。


















