MongoDB聚合查询运行速度很慢

时间:2016-11-03 17:24:24

标签: mongodb aggregation-framework document-versioning

我们在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/

1 个答案:

答案 0 :(得分:0)

为了完成这个问题,我们选择了选项3:一个集合用于保留最新版本,一个集合用于保留历史版本。这里介绍了http://www.askasya.com/post/trackversions/,并在http://www.askasya.com/post/revisitversions/中找到了一些进一步的描述(包含一些不错的代码片段)。

它已经在生产中运行了6个月。到现在为止还挺好。以前的方法意味着我们总是使用聚合框架,一旦修改原始模式(使用$ group,$ project ...)就会远离索引,因为它不再匹配原始集合。随着数据的增长,这使我们的表现变得非常糟糕。

虽然问题已经消失,但采用新方法。我们90%的查询都是针对最新数据的,这意味着我们使用简单的ObjectId作为标识符来定位集合,我们不再需要聚合框架,只需定期查找。

我们针对历史数据的查询始终包含idversion,因此可以将这些内容编入索引(我们将其包含为_id,以便我们开箱即用),对这些集合的读取是同样快。这一点虽然不容忽视。在设计集合/模式在MongoDB中的样子时,应用程序中的读取模式至关重要,因此在做出此类决策时必须确保了解它们。