我们在Mongodb中版本我们的大多数集合。选择的版本控制机制如下:
{ "docId" : 174, "v" : 1, "attr1": 165 } /*version 1 */
{ "docId" : 174, "v" : 2, "attr1": 165, "attr2": "A-1" }
{ "docId" : 174, "v" : 3, "attr1": 184, "attr2" : "A-1" }
因此,当我们执行查询时,我们总是需要以这种方式使用聚合框架来确保获得最新版本的对象:
db.docs.aggregate( [
{"$sort":{"docId":-1,"v":-1}},
{"$group":{"_id":"$docId","doc":{"$first":"$$ROOT"}}}
{"$match":{<query>}}
] );
这种方法的问题是,一旦你完成了分组,你在内存中有一组与你的集合无关的数据,因此,你的索引不能使用。
因此,集合中的文档越多,查询就越慢。
有没有办法加快速度?
如果没有,我将考虑转移到这篇文章中定义的方法之一:http://www.askasya.com/post/trackversions/
为了完成这个问题,我们选择了选项3:一个集合保存最新版本,一个集合保存历史版本。这里介绍它:http://www.askasya.com/post/trackversions/和一些进一步的描述(带有一些漂亮的代码片段)可以在http://www.askasya.com/post/revisitversions/中找到。
它已经在生产中运行了6个月。到目前为止一切顺利。以前的方法意味着我们总是使用聚合框架,一旦修改原始模式(使用$group, $project…),它就会远离索引,因为它不再匹配原始集合。当数据不断增长时,这会使我们的性能变得很糟糕。
有了新的方法,问题就解决了。我们90%的查询都是针对最新数据的,这意味着我们的目标是一个简单的ObjectId
作为标识符的集合,我们不再需要聚合框架,只需要常规查找。
我们对历史数据的查询总是包括id
和version
,所以通过索引它们(我们包括_id
,所以我们把它从盒子里拿出来),对这些集合的读取同样快。这是一个不容忽视的问题。当你设计你的集合/模式在MongoDB中的样子时,应用程序中的读取模式是至关重要的,所以你必须确保在做出这样的决定时你知道它们。