MongoDB ObjectId的优化
ObjectID,也就是我们在进行insert操作时会自动生成的_id字段。我们经常会看到它,这个字段的组成及其设计思路我们可以参考NoSQLFan之前的文章《 MongoDB文档(Document)全局唯一ID的设计思路》。
今天我们想讲一下对这个字段的一些优化,内容主要来源于 MongoDB官方文档。
1.使用业务中的唯一ID
_id字段在不指定时是自动生成的,也就是说,我们也可以在insert操作时自己指定它的值。如果你的业务中对每一条数据都有一个唯一ID,那么建议使用这个ID的值作为_id的值。比如存用户信息的collection,那么你可以使用用户的uid作_id的值,这样做有两个好处:
- 减少原有_id对空间的占用
- 让你的_id值意义更明确
2.使用自增数据为_id
由于_id字段是会自动创建索引的,所以如果你按上面的方法用业务中的唯一ID作为_id的值,那么它也会创建一个索引。所以如果你的ID值是一个自增长的字段,那么在insert操作修改索引时,就不需要将_id的索引整个加载到内存中了。(实际上自动生成的_id就有这个特性)
3.使用二进制数据,而非编码字符串
如果你打算设置的_id值是一个二进制的串,那么你不需要将它进行16进制编码后存在一个字符串,因为MongoDB支持BinData类型,你可以直接将二进制串作为_id的值进行存储。
而你也可以通过下面一些方法将二进制串转换为可读的字符串
> // mongo shell bindata info: > help misc b = new BinData(subtype,base64str) create a BSON BinData value b.subtype() the BinData subtype (0..255) b.length() length of the BinData data in bytes b.hex() the data as a hex encoded string b.base64() the data as a base 64 encoded string b.toString()
4.从 ObjectId中获取insert时间
如果你使用了默认的ObjectId作为_id值,并且你还存在一个addtime字段保存添加时间,那么你已经在犯错了。因为MongoDB默认的ObjectId本身就保存了一些信息。其中就包括本条记录生成的时间。你只需要通过下面方法就能获取到其中的信息:
> // ObjectId支持的方法 > help misc o = new ObjectId() create a new ObjectId o.getTimestamp() return timestamp derived from first 32 bits of the OID o.isObjectId() o.toString() o.equals(otherid)
5.使用默认_id进行排序
如果使用了默认的ObjectId作为_id值,而你又希望通过insert的时间进行排序查询,那么一切就简单了,你可以直接使用_id字段进行排序,因为它本身是按insert的时间自增生成的。
> // 获取最新加入的10条记录 > db.mycollection.find().sort({id:-1}).limit(10);
参考: http://www.mongodb.org/display/DOCS/Optimizing+Object+IDs