Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL不推荐使用雪花和UUID做主键

一文详解为什么MySQL不推荐使用雪花和UUID做主键

作者:天天摸鱼的java工程师

这篇文章主要介绍了为什么MySQL不推荐使用雪花和UUID做主键的相关资料,本文从MySQL索引机制、数据存储原理、性能影响等角度解析,指出UUID和Snowflake做主键存在存储空间浪费、索引碎片化、查询性能低下等缺陷,需要的朋友可以参考下

前言

在 MySQL 表设计中,主键选择是影响性能的关键因素。雪花 ID(Snowflake)和 UUID 作为分布式系统中常用的唯一标识符,虽能解决全局唯一性问题,但在 MySQL 中却并非主键的最佳选择。本文将从 MySQL 索引机制、数据存储原理、性能影响等角度,解析为何不推荐使用这两种 ID 作为主键。

一、MySQL 主键的设计核心:聚簇索引与数据组织

1. 聚簇索引的本质

MySQL 的 InnoDB 存储引擎采用聚簇索引(Clustered Index) ,即数据行的物理存储顺序与主键索引的顺序一致。这意味着:

2. 理想主键的特性

为了优化聚簇索引的性能,理想的主键应具备:

  1. 固定长度:便于快速定位数据页
  1. 顺序增长:新数据插入时按顺序追加,减少页分裂
  1. 紧凑存储:占用磁盘空间小,提升索引缓存效率

二、UUID 做主键的四大性能缺陷

1. 存储长度大,浪费磁盘空间

2. 无序性导致索引碎片化

3. 字符串比较效率低下

4. 影响二级索引性能

三、雪花 ID 的优化与局限性

1. 雪花 ID 的改进点

1bit(符号位)+41bit(时间戳)+10bit(工作节点)+12bit(序列号)

2. 仍存在的问题

(1)非完全顺序性

(2)分布式场景的隐藏成本

(3)扩容困难

四、MySQL 主键的最佳实践:自增 ID vs 分布式 ID

1. 单机场景:自增主键(AUTO_INCREMENT)

优势:

实现方式:

CREATE TABLE `users` (
  `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(50) NOT NULL,
  ...
) ENGINE=InnoDB;

2. 分布式场景:推荐组合方案

方案 1:自增主键 + 分库分表

方案 2:使用 MySQL 原生分布式 ID(如 8.0 + 的 SERVER_UUID)

-- 生成128位UUID(优化存储为16字节二进制)
SET @uuid = UUID_TO_BIN('550e8400-e29b-41d4-a716-446655440000');
INSERT INTO `table` (`id`) VALUES (@uuid);
-- 查询时转换为字符串
SELECT BIN_TO_UUID(`id`) FROM `table`;

方案 3:引入分布式 ID 生成器(如百度 UidGenerator、美团 Leaf)

五、不得不使用 UUID/Snowflake 的应对策略

1. 优化存储格式

-- 插入时转换
INSERT INTO `table` (`uuid_bin`) VALUES (UUID_TO_BIN(UUID()));
-- 查询时转换
SELECT BIN_TO_UUID(`uuid_bin`) FROM `table`;

2. 强制顺序化(仅适用于雪花 ID)

3. 非聚簇索引表(牺牲一致性换性能)

CREATE TABLE `non_clustered_table` (
  `uuid` CHAR(36) PRIMARY KEY,
  `data` TEXT,
  INDEX `idx_data` (`data`)
) ENGINE=InnoDB DISABLE_KEY_CACHE=1;

六、性能对比实测(InnoDB 引擎,100 万条数据)

主键类型插入速度(条 / 秒)主键索引大小范围查询耗时(SELECT * FROM t WHERE id < 10000)
自增 ID(BIGINT)12,3458.2MB12ms
雪花 ID(BIGINT)10,8908.2MB15ms
UUID(CHAR(36))6,54338.5MB28ms

测试环境:MySQL 8.0,4 核 8GB,SSD 磁盘

七、总结:主键选择的核心原则

  1. 优先遵循聚簇索引优化:利用自增 ID 的顺序性提升写入性能
  1. 空间优先原则:避免使用长字符串作为主键(如 UUID)
  1. 分布式场景权衡
  1. 避免过度设计:单机场景无需引入分布式 ID,自增主键已足够高效

MySQL 的主键设计本质上是在数据唯一性、查询性能、存储效率之间的权衡。除非有明确的分布式唯一性需求,否则应优先选择自增整数作为主键。对于必须使用雪花 ID 或 UUID 的场景,需通过二进制存储、顺序化插入等手段尽可能减少性能损耗。

到此这篇关于MySQL不推荐使用雪花和UUID做主键的文章就介绍到这了,更多相关MySQL不推荐使用雪花和UUID做主键内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文