MySQL 数据库中使用 UUID 主键的缺点及解决方案https://planetscale.com/blog/the-problem-with-using-a-uuid-primary-key-in-mysql本文探讨了在 MySQL 数据库中使用 UUID 作为主键的优缺点,并提供了解决方案。
UUID 的概述:UUID (Universally Unique Identifier) 旨在确保在分布式系统中生成唯一 ID,无需了解其他系统。 然而,错误使用 UUID 作为主键会显著降低数据库性能。
UUID 的不同版本:本文详细介绍了五种官方 UUID 版本和三种提议版本:
● UUIDv1 (时间戳型): 基于时间戳,但使用格里高利历 1568 年 10 月 10 日作为基准时间,并以 100 纳秒为增量。节点信息也包含其中。
● UUIDv2 (时间戳+用户 ID 型): 改进了 UUIDv1,用 POSIX 用户 ID 替换了低位时间戳部分,增加了冲突的可能性。实际使用较少。
● UUIDv3 和 v5 (命名型): 基于命名空间和名称,用哈希算法生成唯一值,UUIDv3 使用 MD5,UUIDv5 使用 SHA1。
● UUIDv4 (随机型): 值几乎完全随机,第三段第一个位总是 4。
● UUIDv6 和 v7 (时间戳型): 类似于 UUIDv1,但 UUIDv6 将时间戳的位翻转,UUIDv7 使用 Unix 时间戳和随机性节点。
● UUIDv8: 允许厂商特定实现,但版本号被指定在第三段的第一个位置。
UUID 作为 MySQL 主键的缺点:● 插入性能: 随机生成的 UUID 会导致索引 B+ 树重新平衡,页面分裂,影响插入性能,尤其在高负载环境下。
● 存储空间: UUID 使用 128 位,比 32 位整数占用空间大 4 倍,如果以字符串形式存储,空间消耗更大,还会影响二级索引。
● InnoDB 效率: InnoDB 假设主键是顺序递增的,随机的 UUID 使得 InnoDB 无法充分利用页面空间。
使用 UUID 作为 MySQL 主键的最佳实践:● 使用二进制类型: 将 UUID 存储为
BINARY(16),而不是
CHAR(36),减少存储空间。
● 使用有序 UUID 版本: 选择时间戳型 UUID,例如 v6 或 v7,以确保唯一性和部分顺序性。
● 使用 MySQL 内置 UUID 函数: MySQL 提供
UUID_TO_BIN 函数,可以用
swap_flag 参数优化。
● 使用替代 ID 类型: 如果可能,考虑使用 Snowflake ID、ULID 或 NanoID 等替代方案。
结论:尽管 UUID 在分布式系统中能保证唯一性,但作为 MySQL 主键时存在性能和存储空间上的缺点。 选择合适的 UUID 版本和替代方案,并结合存储类型,可以有效地降低这些负面影响。
#DB #DevOps #Doc
Planetscale
The Problem with Using a UUID Primary Key in MySQL — PlanetScale
Understand the different versions of UUIDs and why using them as a primary key in MySQL can hurt database performance.