Skip to main content

MySQL 数据库中使用 UUID 主键的缺点及解决方案

  1. 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 The Problem with Using a UUID Primary Key in MySQL — PlanetScale
OKHK