ObjectId使用12字节的存储空间,是一个由24个16进制数字组成的字符串(每个字节可以存储两个16进制数字)。

说明:

12字节(每个字节用2个16位的组成),

因此,总共24个16位的数字。

 

1:如果快速的连续创建多个ObjectId,会发现每次只有最后几位数字有变化。

另外,中间的几位数字也会变化(要是在创建的过程中停顿几秒)

这是ObjectId的创建方式导致的。

2:ObjetId的12字节按照如下方式生成:

java mongodb字段存object mongodb中的objectid_mongoDB

实际举例:

571094e2976aeb1df982ad4e

57    10     94     e2     97     6a     eb     1d     f9     82     ad     4e

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

2.1:时间戳,于随后的5字节(稍后介绍)组合起来,提供了秒级别的唯一性。

2.2:由于时间戳在前,这意味着ObjectId大致会按照插入的顺序排列。这对于某些方面很有用,

比如可以将其作为索引提高效率,但是这个是没有保证的,仅仅是“大致”。

2.3:这4个字节也隐含了文档的创建时间。绝大多数驱动程序都会提供一个方法,用于从ObjectId获取这些信息。

 

因为使用的是当前时间,很多用户担心要对服务器进行时钟同步。虽然在某些情况下,在服务器间进行时间同步

确实是个好主意,但是这里其实没有必要,因为时间戳的实际值并不重要,只要他总是不停增加就好了(每秒一次)。

--------------------------------------------

接下来的3个字节是所在主机的唯一标识符。

通常是机器主机名的散列值(hash)。

这样就可以确保不同主机生成不同的ObjectId,不产生冲突。

--------------------------------------------

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

--------------------------------------------

前9个字节保证了同一秒钟不同机器不同进程产生的ObjectId是唯一的。

最后3个字节是一个自动增加的计数器,确保相同进程同一秒产生的ObjectId也是不一样的。

一秒钟最多允许每个进程拥有256的3次方(16777216)个不同的ObjectId。

============================================================

因此在生产中我们可以根据id做一些事情:

1:按照_id升序《等价于》即按照插入时间升序

2:按照_id降序《等价于》即按照插入时间降序

为什么这么说呢?

因为前4位是一个unix的时间戳,是一个int类别,我们将上面的例子中的objectid的前4位进行提取“4df2dcec”,然后再将他们转为十进制:“1307761900”,这个数字就是一个时间戳,为了让效果更佳明显,我们将这个时间戳转换成我们习惯的时间格式( 精确到秒)

$ date -d '1970-01-01 UTC 1307761900  sec'  -u 

2011年 06月 11日 星期六 03:11:40 UTC

 

前 4个字节其实隐藏了文档创建的时间,并且时间戳处在于字符的最前面,这就意味着ObjectId大致会按照插入进行排序,这对于某些方面起到很大作用,如 作为索引提高搜索效率等等。使用时间戳还有一个好处是,某些客户端驱动可以通过ObjectId解析出该记录是何时插入的,这也解答了我们平时快速连续创 建多个Objectid时,会发现前几位数字很少发现变化的现实,因为使用的是当前时间,很多用户担心要对服务器进行时间同步,其实这个时间戳的真实值并 不重要,只要其总不停增加就好。

ObjectId("53102b43bf1044ed8b0ba36b").getTimestamp();  

ISODate("2014-02-28T06:22:59Z");