【问题标题】:When using UUIDs, should I also use AUTO_INCREMENT?使用 UUID 时,我是否也应该使用 AUTO_INCREMENT?
【发布时间】:2013-02-27 21:47:37
【问题描述】:

我们正在构建一个新的网络应用程序,该应用程序将在许多本地设备上提供离线 iPad/Android 应用程序版本,这将涉及插入新数据。因此,我们需要使用 UUID 以允许与主数据库进行必要的双向同步。为此,我们将 UUID 存储为 BINARY(16) 主键。

我在研究后了解到的问题是,非顺序主键插入所需的时间会随着时间的推移而增加,并且这些插入会导致碎片(如回答here)。 AUTO_INCREMENT 的好处是新行通常只会添加到表的末尾,因此不会遇到 UUID 的速度问题。

我的问题是使用AUTO_INCREMENT 列作为主键然后将UUID 列作为非空唯一索引是否更好?据推测,这将具有顺序插入的速度优势,同时保留同步分布式数据库所需的必要 UUID。

我可以看到的一个问题是 UUID 需要用作其他表的参考(使用外键约束)(即附加到检查的问题列表,而检查又附加到站点,所有这些都涉及插入,因此所有这些都需要 UUID)。从语义上讲,主键作为参考更有意义,但作为分布式系统,我们不能使用 AUTO_INCREMENTS 来表示这些。对这些引用(当然还有随之而来的JOINs)使用(非空)唯一索引而不是主键是否有缺点?

另外值得注意的是,主(在线)数据库使用 MySQL (InnoDB),而分布式(离线)数据库使用 SQLite。

编辑:

考虑到将 UUID 作为主键可能会更好(因为它在语义上就是这样),如果我将 UUID 设置为主键并将 AUTO_INCREMENT 列设置为非空唯一索引?还是只有在确定在哪里插入新行时相关的主键?

【问题讨论】:

    标签: mysql sql sqlite auto-increment uuid


    【解决方案1】:

    使用自动增量作为主要加上一个 uuid 列是一个有效的模型,但您仍然需要解决自动增量带来的一些问题,这完全取决于您如何进行同步。

    无论如何,我一直在使用 uuid 作为主键(我当前的数据库有 50 万条记录)并且它仍然非常快,它只会减慢插入速度,但除非您每天的插入量非常大它不应该吓到你。

    如果你使用 Sql-Server,你可以看看另一个解决方案是 Sequential UUID,它比普通 UUID 的碰撞几率略大,但绝对碰撞几率仍然很低,因为它们是部分顺序的涵盖了碎片化的问题。

    【讨论】:

      【解决方案2】:

      您可以使用复合主键,由离线客户端分配的自动递增 bigint ID 值加上分配给客户端的 bigint ID 组成。因此,您将在客户端 1235 上创建条目 15。

      客户端最好在进行第一次编辑之前向服务器请求其 ID,例如,当它首次检索服务器的主数据时。

      【讨论】:

        【解决方案3】:

        一旦你有一个大的分布式数据仓库,如果你使用 UUID 或 GUID 作为唯一键,然后在 join 中使用它,那就不好了。

        请在您的主数据库或数据管道中创建顺序代理键,而不是使用 UUID 或 GUID。

        分享我们的项目经验作为参考。我们在并行数据仓库中保存了 3000 亿条记录,在我们的系统中,甚至不支持自动增量密钥。我们使用 8 字节的 bigint 作为主键(实际上我们系统中的唯一键也不支持,但这不影响逻辑唯一性),当我们处理文件和加载文件时,我们使用 3 字节生成文件 ID,即 2^24文件,我们每天需要加载大约 2,000 个文件,所以,2^24 可以支持大约 25 年,如果没有错的话。

        我们使用剩余的 4 个字节作为行 ID,即 40 亿行,我们在任何文件中都没有 40 亿行。我们保留 1 个字节。在ETL处理过程中,我们只需要跟踪master数据库中的文件ID,它支持自动增量ID,当我们在处理文件时需要生成记录ID时,我们结合FileID+reserve 1字节+4字节rowID。

        【讨论】:

          【解决方案4】:

          来自https://uuid.fyi/uuidorint

          UUID

          优点

          • 全球独一无二。
          • 无状态,可以动态生成。
          • 安全,因为恶意用户无法猜测 ID。
          • 版本 1 UUID 存储时间戳信息,有时可能很有用。

          缺点

          • 不可读。
          • 对于 MySQL、Oracle 等使用集群主键的数据库,版本 4 随机生成的 UUID 如果用作主键会影响插入性能。这是因为它需要对行重新排序,以便将新插入的行放在聚集索引内的正确位置。另一方面,PostgreSQL 使用堆而不是集群主键,因此使用 UUID 作为 PK 不会影响 PostgreSQL 的插入性能。

          自动递增整数/序列

          优点

          • 可读。如果我们将其暴露在外部,这尤其有价值。考虑到 issue id,显然 issue-123 比 issue-b1e92c3b-a44a-4856-9fe3-925444ac4c23 更具可读性。

          缺点

          • 它不能在分布式系统中使用,因为不同的主机很可能产生完全相同的数字。
          • 不能即时生成。相反,我们必须查阅数据库以找出下一个可用的 PK。
          • 可能会暴露一些业务数据,因为最新的 ID 可能代表库存总数。攻击者还可以扫描整数范围以探索泄漏(尽管如果正确实施 ACL,则不会发生这种情况)。

          【讨论】:

            猜你喜欢
            • 2019-06-13
            • 2022-06-10
            • 1970-01-01
            • 2012-05-28
            • 1970-01-01
            • 2021-04-06
            • 1970-01-01
            • 1970-01-01
            • 2011-02-11
            相关资源
            最近更新 更多