问题 MongoDB中的集合ID长度


我是mongodb和堆栈溢出的新手。

我想知道为什么mongodb集合ID是24个十六进制字符? 这有什么重要意义?


2879
2017-08-18 04:06


起源

官方文档是一个很好的起点: 的ObjectId - Neil Lunn
为主键生成的默认唯一标识符(_id) 是一个 的ObjectId。这是一个12字节的二进制值,通常表示为24个字符的十六进制字符串。如果您有更合适的唯一标识符,则可以为其提供自己的值 _id。 ObjectId的重要性在于可以在分布式系统中生成唯一值(通常由客户端驱动程序生成)。这类似于 的GUID,虽然更紧凑。 - Stennie


答案:


为什么是默认值 _id 24个字符的十六进制字符串

作为主键生成的默认唯一标识符(_id)对于MongoDB文档是一个 的ObjectId。这是一个12字节的二进制值,通常表示为24个字符的十六进制字符串,以及MongoDB支持的标准字段类型之一 BSON规范

ObjectId的12个字节使用以下内容构造:

  • 一个4字节的值,表示自Unix纪元以来的秒数
  • 一个3字节的机器标识符
  • 一个2字节的进程ID
  • 一个3字节的计数器(以随机值开始)

ObjectId的重要性是什么?

ObjectIds(或根据a生成的类似标识符) GUID 公式)允许在分布式系统中独立生成唯一标识符。

当您扩展到多个应用程序服务器(或者可能是多个数据库节点)时,独立生成唯一ID的能力变得非常重要 分片群集)。您不希望像序列计数器那样存在中央协调瓶颈(例如,您可能拥有自动递增主键),并且您将希望插入新文档而不存在新标识符将成为重复。

ObjectId通常由MongoDB生成 客户司机,但也可以在MongoDB服务器上生成,如果您的客户端驱动程序或应用程序代码或尚未添加 _id 领域。

我必须使用默认的ObjectId吗?

不可以。如果您有更合适的唯一标识符,您可以随时提供自己的值 _id。这可以是单个值,也可以是使用多个字段的复合值。

主要限制因素 _id 值是,它们必须是集合的唯一,并且您无法更新或删除 _id 对于现有文档。


12
2017-08-21 04:56



这个4字节值是无符号的吗?如果不是MongoDB将不得不在大约22年内进行大修...... - Kenneth Worden
@KennyWorden ObjectIds目前使用带符号的32位int(即 unixtime),所以你说时间组件最终会翻转是正确的(另见: 在2038年,ObjectID会发生什么?)。生成的ObjectIds应该在翻转后继续保持唯一(按字节顺序)一段时间,但某些假设(例如按单调增加的时间前缀排序)将不再成立。我假设之前会有一个替换的ObjectId子类型:)。 - Stennie
我相信unixtime组件最初包含在唯一性和生成的ObjectIds的粗略排序中,而不是默认情况下嵌入时间戳 _ids(虽然从那时起开发人员肯定对时间戳方面做出了假设)。已经有几个ObjectId变体,由不同的传统驱动程序实现(参见 “亚型” 在BSON规范中或写入 Robomongo的UUID支持)。 - Stennie
签?为什么?他们不需要在时代之前追踪时间! - Kenneth Worden
@KennyWorden参见: unix时间:“Unix时间是一个单一的有符号整数,每秒递增一次”。我认为“当时对于Unix内核开发者来说似乎是一个好主意”(类似于1970年1月1日作为unix时代的选择)。为方便起见,ObjectId生成中的用法遵循既定约定。想要唯一地生成整体ObjectId,但如前所述,我认为它不一定要嵌入时间戳。您也可以自由使用自己的唯一标识符 _id 而不是默认的ObjectId。 - Stennie