ObjectId
mongoDB中存储的文档必须有一个"_id"键,这个键的值可以是任何类型的,默认是ObjectId对象。通常也不建议存成其他类型,例如字符串,原因有以下三个方面:
- 不方便查询(字符串和OjbectId不能相互匹配);
- OjbectId含有有用的信息,绝大多数驱动都有方法从OjbectId中获取文档的创建日期等信息;
- 字符串表示的OjbectId会多占两倍的磁盘空间。
在一个集合里面,每个文档都有唯一的"_id"值,来确保集合里面每个文档都能被唯一标识。那么你可能会问,既然ObjectId的作用是用来标识文档,那为什么不用普通递增id呢?后文有解释。
这就需要了解MongoDB的特点,MongoDB是一个基于分布式文件存储的数据库。因此在高并发的场景下,自增id与MongoDB的设计背道而驰。在分布式环境中,自增id要保证正确递增必然会影响效率,因此MongoDB采用ObjectId作为对象标识。ObjectId是bson(binary json)类型的数据,由12位值组成:
- 前4个字节表示时间戳,是文档创建时的时间,它是递增的,可以保证ObjectId总体递增的顺序。
但是上面的递增不是绝对的,因为这个时间只是精确到秒,而同一台机器同一秒内生成的ObjectId还会因pid不同而不同,pid小的ObjectId始终排在pid大的那个前面。 - 接着3位是机器识别码
也就是在同一台机器中,每次生成ObjectId中,这三个字节总相等 - 紧接2位着是进程id的值
- 最后3位是随机值