MongoDB中的_id和ObjectId介绍
MongoDB中的_id和ObjectId介绍
一书生 发表于1年前
MongoDB中的_id和ObjectId介绍
  • 发表于 1年前
  • 阅读 90
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 本文来源于《MongoDB权威指南 (第二版)》 [美]Kristina Chodorow 著 邓强,王明辉 译 人民邮电出版社, 我只是个搬运工,文章版权归原作者所有。

MongoDB中存储的文档必须有一个id键。这个键的值可以是任何类型的,默认是个ObjectId对象。在一个集合里面,每个文档都有唯一的_id,确保集合里面每个文档都能被唯一标识。如果有两个集合的话,两个集合可以都有一个_id的值为123,但是每个集合里面只能有一个文档的_id 值为123。

ObjectId

ObjectId_id的默认类型。它设计成轻量型的,不同的机器都能用全局唯一的同种方法方便地生成它。这是MongoDB采用ObjectId,而不是其他比较常规的做法(比如自动增加的主键)的主要原因,因为在多个服务器上同步自动增加主键值既费力又费时。因为设计MongoDB 的初衷就是用作分布式数据库,所以能够在分片环境中生成唯一的标示符非常重要。

ObjectId使用12字节的存储空间,是一个由24个十六进制数字组成的字符串(每个字节可以存储两个十六进制数字)。由于看起来很长,不少人会觉得难以处理。但关键是要知道这个长长的ObjectId是实际存储数据的两倍长。

如果快速连续创建多个ObjectId,会发现每次只有最后几位数字有变化。另外,中间的几位数字也会变化(要是在创建的过程中停顿几秒钟)。这是ObjectId的创建方式导致的。ObjectId的12字节按照如下方式生成:

0 1 2 34 5 67 89 1 0 1 1
时间戳机器PID计数器

ObjectId的前4个字节是从标准纪元开始的时间戳,单位为秒。这会带来一些有用的属性。

  • 时间戳,与随后的5字节(稍后介绍)组合起来,提供了秒级别的唯一性。
  • 由于时间戳在前,这意味着ObjectId大致会按照插入的顺序排列。这对于某些方面很有用,比如可以将其作为索引提高效率,但是这个是没有保证的,仅仅是“大致”。
  • 这4字节也隐含了文档创建的时间。绝大多数驱动程序都会提供一个方法,用于从ObjectId获取这些信息。

因为使用的是当前时间,很多用户担心要对服务器进行时钟同步。虽然在某些情况下,在服务器间进行时间同步确实是个好主意,但是这里其实没有必要,因为时间戳的实际值并不重要,只要它总是不停增加就好了(每秒一次)。

接下来的3字节是所在主机的唯一标识符。通常是机器主机名的散列值(hash)。这样就可以确保不同主机生成不同的ObjectId,不产生冲突。

为了确保在同一台机器上并发的多个进程产生的ObjectId是唯一的,接下来的两字节来自产生ObjectId的进程的进程标识符(PID)。

前9字节保证了同一秒钟不同机器不同进程产生的ObjectId是唯一的。最后3字节是一个自动增加的计数器,确保相同进程同一秒产生的ObjectId也是不一样的。一秒钟最多允许每个进程拥有2563(16 777 216)个不同的ObjectId

自动生成_id

前面讲到,如果插入文档时没有_id键,系统会自动帮你创建一个。可以由MongoDB服务器来做这件事,但通常会在客户端由驱动程序完成。这一做法非常好地体现了MongoDB 的哲学:能交给客户端驱动程序来做的事情就不要交给服务器来做。这种理念背后的原因是,即便是像MongoDB这样扩展性非常好的数据库,扩展应用层也要比扩展数据库层容易得多。将工作交由客户端来处理,就减轻了数据库扩展的负担。

标签: MongoDB
共有 人打赏支持
粉丝 4
博文 13
码字总数 5030
×
一书生
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: