最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
为什么MySQL建议使用自增主键而不是UUID作为索引?
时间:2026-08-22 20:13:48 编辑:袖梨 来源:一聚教程网
AUTO_INCREMENT主键比UUID更优,因其顺序插入避免页分裂、提升缓存局部性、降低I/O开销;UUID随机性导致索引碎片率高3倍、范围查询退化为随机IO、存储膨胀且易因传参不匹配导致索引失效。
AUTO_INCREMENT 主键在绝大多数场景下比 UUID() 更适合做 MySQL 的主键,核心原因不是“UUID 不够唯一”,而是它直接破坏了 InnoDB 聚簇索引的物理组织逻辑。自增ID插入不触发页分裂,UUID几乎必然触发
InnoDB 的聚簇索引把数据行和主键值绑在一起存,B+ 树叶子节点必须按主键顺序链接。AUTO_INCREMENT 总是追加到末尾,新页分配简单、连续,INSERT 延迟稳定在 0.2–0.5ms;UUID() 返回的是随机字符串(如 '550e8400-e29b-41d4-a716-446655440000'),每次插入都要搜索整棵树定位位置,大概率落在中间页——已有页填满就拆,指针重连,I/O 成倍增加。实测百万级写入,UUID 表的 Data_free 值(SHOW TABLE STATUS 输出)通常是自增表的 3 倍以上,说明碎片严重。UUID主键让范围查询退化为随机IO
WHERE id BETWEEN 1000 AND 2000 这类查询,在自增主键下只需读取连续几个数据页;换成 UUID 主键,逻辑上“相邻”的 ID 在磁盘上可能散落在数百个不同页里,变成大量随机读,缓存命中率暴跌。更隐蔽的问题是:ORM 或应用层传参稍有不慎(比如传 '9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d' 漏横杠,或大小写混用),WHERE id = ? 就完全走不了索引,执行计划里 type 显示 ALL 而不是 const。存储空间膨胀影响所有索引
主键不只是自己占空间,它还被所有二级索引作为“行指针”重复引用。BIGINT 主键只占 8 字节,CHAR(36) 却占 36 字节——单表 1000 万行,主键索引就多占约 280MB;若有 5 个二级索引,总膨胀接近 1.4GB。即使改用 BINARY(16) + UUID_TO_BIN(UUID(), TRUE),仍比 BIGINT 多出 8 字节,且无法解决根本的随机性问题。真正需要 UUID 的场景极少,基本只有两个:分库分表又没全局序列服务、或多库数据要合并且无法重映射主键。其他所谓“防爬”“安全”“分布式友好”,都该用映射表或前端脱敏来解,而不是拿索引性能换。