返回列表 发布新帖
查看: 33|回复: 0

为什么MySQL不推荐使用雪花ID和UUID做主键?

发表于 前天 15:59 | 查看全部 |阅读模式

这里或许是互联网从业者的最后一片净土,随客社区期待您的加入!

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 mrkong 于 2025-8-28 16:01 编辑

在 MySQL 表设计中,主键的选择对性能影响极大。雪花 ID(Snowflake)和 UUID 虽然常用于分布式系统中保证全局唯一性,但在 MySQL 中却并不是最佳的主键选择。本文将从 索引机制、存储原理、性能影响 等角度深入分析原因,并给出最佳实践方案。

一、MySQL 主键的设计核心:聚簇索引与数据组织1. 聚簇索引的本质MySQL 的 InnoDB 引擎使用 聚簇索引(Clustered Index)
  • 数据行的物理存储顺序与主键索引顺序一致。
  • 主键不仅是唯一标识,也是数据存储的顺序依据。
  • 二级索引存储的是 主键值 而不是数据地址,查询时必须回表。
2. 理想主键的特征
  • 固定长度:便于快速定位数据页。
  • 顺序增长:插入时顺序追加,避免频繁页分裂。
  • 紧凑存储:占用空间小,提高缓存利用率。
二、UUID 做主键的四大性能缺陷
  • 存储空间大
    • UUID 通常为 36 字符的字符串,如 550e8400-e29b-41d4-a716-446655440000。
    • CHAR(36):36 字节,VARCHAR(36):37 字节。
    • 对比 BIGINT(8 字节),UUID 占用空间多近 5 倍。
  2. 无序性导致索引碎片化
  • UUID 随机分布,插入时位置不可控。
  • 导致 B+ 树频繁分裂,写入性能大幅下降,索引碎片增加。
   3. 字符串比较效率低
  • UUID 按字典序比较,需要逐字符扫描。
  • 范围查询性能差,无法利用主键的顺序性。
  • 实测:查询性能比自增主键慢 30%+。
    4. 影响二级索引性能
  • 二级索引存储主键值,UUID 主键过长导致:
  • 索引体积增大,缓存命中率下降。
  • 回表查询需更多随机 I/O。

三、雪花 ID 的优化与局限性1. 优势
  • 紧凑存储:使用 BIGINT(8 字节),比 UUID 高效。
  • 趋势有序:基于时间戳生成,整体递增,插入较平稳。
  • 分布式唯一:不同节点生成的 ID 全局唯一。
2. 局限性
  • 非完全顺序
    • 同一毫秒内的 ID 顺序由序列号决定,可能局部乱序。
    • 多节点之间的 ID 顺序可能跳跃,仍有页分裂风险。
  • 分布式管理成本高
    • 需独立 ID 生成服务。
    • 存在时钟回拨、节点数限制等问题。
四、MySQL 主键的最佳实践1. 单机场景:自增 ID
  1. CREATE TABLE users (
  2. id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  3. name VARCHAR(50) NOT NULL
  4. ) ENGINE=InnoDB;
复制代码
优点
  • 顺序插入,页分裂少。
  • 存储空间小,索引紧凑。
  • 插入查询性能最佳。
2. 分布式场景的推荐方案
  • 方案 1:分库分表 + 自增主键
    • 每个分库自增 ID 起始值不同,避免冲突。
  • 方案 2:MySQL 原生 UUID(二进制存储)
  1. INSERT INTO t (id) VALUES (UUID_TO_BIN(UUID()));
  2. SELECT BIN_TO_UUID(id) FROM t;
复制代码
存储空间缩减至 16 字节。
方案 3:分布式 ID 生成器(Leaf、UidGenerator)
  • 基于数据库号段或雪花算法,生成趋势递增 ID。

五、必须使用 UUID/雪花 ID 时的优化策略
  • UUID 转为二进制存储
BINARY(16) 代替 CHAR(36)。

   存储效率提升,索引更紧凑。
   2. 顺序化插入(适用雪花 ID)
   应用层按时间戳排序后写入。
   高并发场景可能造成插入阻塞。

   3. 控制页分裂
   定期 OPTIMIZE TABLE。
   合理设置 innodb_fill_factor。

六、性能对比实测(100 万条数据,MySQL 8.0 InnoDB)
主键类型插入速度(条/s)主键索引大小范围查询耗时
自增 ID (BIGINT)12,3458.2MB12ms
雪花 ID (BIGINT)10,8908.2MB15ms
UUID (CHAR(36))6,54338.5MB28ms
环境:4核8GB,SSD。

七、总结:主键选择的核心原则
  • 优先顺序性:自增 ID 写入性能最佳。
  • 优先紧凑性:避免长字符串主键。
  • 分布式权衡
    • 单机场景:自增主键。
    • 分布式场景:趋势递增 ID(雪花或号段方案)。
除非有 全局唯一性强需求,否则不建议直接用 UUID 或雪花 ID 作为 MySQL 主键。若必须使用,应通过 二进制存储 + 顺序化插入 等手段尽量降低性能损耗。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2001-2025 Suike Tech All Rights Reserved. 随客交流社区 (备案号:津ICP备19010126号) |Processed in 0.092844 second(s), 7 queries , Gzip On, MemCached On.
关灯 在本版发帖返回顶部
快速回复 返回顶部 返回列表