【问题标题】:MongoDB Aggregation query running very slowMongoDB聚合查询运行很慢
【发布时间】:2017-03-17 09:42:19
【问题描述】:

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

【问题讨论】:

  • 为什么第一阶段没有$match?
  • 为文档的 docId 字段添加索引。
  • @DanieleTassone 恐怕这不是一个选择。解释在我提供的链接中。基本上,如果您在开始时进行过滤,您最终会得到不是最新的版本,但排序组阶段会将它们视为最新版本。执行这样的版本控制时,这是一个常见错误。
  • @Parshuram 为 docId 添加索引会加快组操作,但不会加快后面的 $match,不是吗?
  • @jbernal 我看到了带有详细信息的链接。链接 (db.docs.find({"docId":174}).sort({"v":-1}).limit(-1);) 中解释了最有效的方法想。如果您需要 1 个文档,这可以正常工作。如果您同时需要更多文件是另一回事:这是我不明白的事情,您能更好地解释一下吗?有不同的解决方案,但我应该更好地理解。另外 - 我们可以考虑 MongoDB 3.4 吗?

标签: mongodb aggregation-framework document-versioning


【解决方案1】:

为了完成这个问题,我们选择了选项 3:一个集合保留最新版本,一个集合保留历史版本。此处介绍:http://www.askasya.com/post/trackversions/ 和一些进一步的描述(带有一些漂亮的代码 sn-ps)可以在http://www.askasya.com/post/revisitversions/ 中找到。

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

虽然问题消失了,但使用新方法。我们 90% 的查询都针对最新数据,这意味着我们以简单的 ObjectId 作为标识符的集合为目标,我们不再需要聚合框架,只需常规查找即可。

我们对历史数据的查询始终包括 idversion,因此通过对它们进行索引(我们将两者都包括为 _id,因此我们可以直接使用),读取这些集合的速度同样快。这是一个不容忽视的问题。在设计 MongoDB 中的集合/模式的外观时,应用程序中的读取模式至关重要,因此您必须确保在做出此类决定时了解它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    • 2014-06-14
    • 1970-01-01
    相关资源
    最近更新 更多