【问题标题】:Mongoose aggregate pipeline: sorting indexed date in MongoDB is slowMongoose 聚合管道:在 MongoDB 中排序索引日期很慢
【发布时间】:2020-07-08 14:33:15
【问题描述】:

我在我的应用程序上处理这个错误已经有一段时间了,希望有人能帮忙找出这个聚合查询的错误。

我正在使用运行 MongoDB shell 版本 v4.2.8 的 docker 容器。该应用使用 Express.js 后端和 Mongoose 中间件与数据库交互。

我想创建一个聚合管道,它首先与名为“platform_number”的索引字段匹配。然后我们按索引字段“日期”(存储为 ISODate 类型)对其进行排序。剩下的管道似乎不会影响性能,它只是一些预测和过滤。

{$sort: {date: -1}} 是整个聚合的瓶颈,即使只返回了大约 250 个文档。我确实有一个名为“cycle_number”的未索引键,它与“日期”字段直接相关。将 {date: -1} 替换为 {cycle_number: -1} 会加快查询速度,但随后出现内存不足错误。排序在 Ram 上有一个最大 100MB 的上限,这种排序在 250 个文档时失败。

一个可能的解决方案是包含附加选项{ "allowDiskUse": true }。但在此之前,我想知道为什么“日期”一开始就没有正确排序。另一种选择是索引“cycle_number”,但同样,为什么“date”会举手?

下面提供了聚合管道。首先是匹配,然后是排序,依此类推。我很乐意解释其他函数在做什么,但是当我将它们注释掉时,它们并没有太大区别。

    let agg = [ {$match: {platform_number: platform_number}} ] // indexed number
    agg.push({$sort:  {date: -1}}) // date is indexed in decending order
    if (xaxis && yaxis) {
        agg.push(helper.drop_missing_bgc_keys([xaxis, yaxis]))
        agg.push(helper.reduce_bgc_meas([xaxis, yaxis]))
    }
    const query = Profile.aggregate(agg)

    query.exec(function (err, profiles) {
        if (err) return next(err)
        if (profiles.length === 0) { res.send('platform not found') }
        else {
            res.json(profiles)
        }
    })

再一次,我一直在小心翼翼地处理这个问题。解决问题会很棒,但更好地理解问题也很棒,感谢您的帮助!

【问题讨论】:

    标签: mongodb sorting mongoose aggregation-framework


    【解决方案1】:

    查询执行器无法在第二阶段使用不同的索引。 MongoDB 索引将键值映射到数据文件中文档的位置。 一旦$match 阶段完成,文档就在管道中,因此无法进一步使用索引。

    但是,如果您在 {platform_number:1, date:-1} 上创建复合索引,则查询规划器可以将 $match$sort 阶段组合成一个不需要阻塞排序的阶段,这将大大提高此管道的性能.

    【讨论】:

    • 做到了。 Here 是正在运行的应用程序!
    猜你喜欢
    • 2018-11-25
    • 2014-10-16
    • 1970-01-01
    • 2018-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    相关资源
    最近更新 更多