【问题标题】:Doctrine Annotations type="guid" and strategy="UUID" Behavior?Doctrine Annotations type="guid" 和 strategy="UUID" 行为?
【发布时间】:2026-01-14 04:10:01
【问题描述】:

好的,所以我只想知道这个注释的行为是什么:

/**
 *
 * @ORM\Id
 * @ORM\Column(name="id", type="guid")
 * @ORM\GeneratedValue(strategy="UUID")
 */
protected $id;

在我向表中插入行时,键是否按递增顺序排列?

我确实知道键不像00001000002 那样简单,它的行为就像

  • 007f13ff-ce26-11e4-8e3d-a0b3cce9bb7e
  • 00805a63-ce26-11e4-8e3d-a0b3cce9bb7e
  • 0b1b6ca9-d178-11e4-8e3d-a0b3cce9bb7e

但我的问题是,键是否按特定顺序排列,例如插入的第一行是比最后一个值低的字母数字值.. 总是?

【问题讨论】:

  • 不建议使用uuid进行PK。我将在内部使用整数 PK,并在前端事务中使用额外的 uuid 字段。

标签: php symfony doctrine-orm


【解决方案1】:

简答:UUID 没有特定的顺序。

一些背景

UUID 是自动增量整数的替代品,因为它们有一些优点,所以越来越多地使用它们。

  1. 当您插入 65537 记录(或类似的 2^x + 1,取决于 ID 的原始大小)时,您不会破坏您的应用程序。最糟糕的情况是您有一个重复的标识符,但这不太可能:https://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

  2. 您可以在代码中存储记录之前生成它们;您不必从数据库中获取“last_insert_id”。这很好,例如当您还必须将一些相关记录存储在不同的表中时(当然 Doctrine 可能会为您处理这个问题,但这是另一回事)。

  3. 您不会将表中的记录数泄露给可以读取当前订单 ID 的聪明人 :-)

关于排序

在目前最常用的版本 (v4) 中,UUID 是完全随机的,因此它们没有特定的顺序。

版本 1 UUID 是 60 位时间戳和 48 位 MAC 地址的组合。

当你使用 Doctrine UUID 策略时,你基本上是在使用数据库特定的实现(即UUID() 函数)。在 MySQL 5.7 的情况下,它是一个 v1 兼容模式,它生成 UUID 为

aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

在哪里

  • aaaaaaaa 是时间戳的低位部分
  • bbbb 是时间戳的中间部分
  • cccc 是时间戳的高位部分
  • dddd 添加时间唯一性以防时间调整
  • eeeeeeeeeeee 是节点 ID(MAC 地址)

由于时间戳是反转的,如果您在短时间内产生多个 UUID,您将会对它们进行排序,但从长远来看,它们不会被排序。考虑使用当前秒作为 UUID 的第一部分。

注意:感谢@Etki 评论改进了答案,这增加了宝贵的贡献并迫使我了解更多有关该主题的信息。

【讨论】:

  • UUID 没有特定顺序 - 取决于版本和生成器
  • @Etki 感谢您的加入。你能链接到一些关于这方面的文献吗?
  • 我手头只有无聊的RFC。通常提到的 UUID 是版本 4 UUID,应该是纯随机的,因此不保留顺序。然而,版本 1 基本上是时间和节点特定值的串联,这迫使它单调递增,所以如果只有一个节点发出版本 1 UUID,它们将是完美排序的(我什至听说有些人坚持使用 v1所以他们的数据将在插入点已经排序)。
  • 我阅读了更多关于它的内容,我认为我的原始答案仍然有效。它们没有排序,除非在很短的时间内。如果我仍然缺少某些东西,请随时指出。谢谢!
  • 另一个很大的好处是您可以合并不同的数据集而不会发生键冲突