【问题标题】:mongodb aggregation very slow when $match key not in index (does tablescan?)当 $match 键不在索引中时,mongodb 聚合非常慢(表扫​​描吗?)
【发布时间】:2026-02-10 21:10:02
【问题描述】:
db.collection.aggregate(

{  "$match" : {
        "key" : "mykey"

    }
}, 
{
    "$sort" : {
        "time" : -1
    }
},
{
    "$limit" : 1 
}

)

示例文档:

{
   key: "key1",
   time: ISODate("2014-07-04T20:04:46.904Z")
}

索引

"time" : -1
"key" : 1,
"_id" : 1

当集合中存在“mykey”时查询需要30ms,当“mykey”不存在时需要10s, 解释告诉我使用了索引。 这是一个有上限的集合,因此通常会出现“键”丢失的情况。 为什么需要这么长时间。 顺便提一句。 MongoDB 2.4

进一步探索:

删除排序的索引可以减少查找时间:

解释在排序字段上带有和不带索引的聚合表明,带有索引的排序在管道的开头执行,没有排序的索引它作为管道的最后一步执行

【问题讨论】:

  • 您有问题吗?
  • 为什么钥匙丢了这么久。
  • “存在”是什么意思?该值是否存在于该键或该字段存在于架构中?
  • 当“key”的值不存在时。如果有帮助,我正在大型(>20M 文档)日志集合中扫描 ObjectId。
  • 如果您将架构与创建的任何索引和示例文档一起共享,那么通过此操作会更容易一些。

标签: performance mongodb aggregation-framework


【解决方案1】:

您的查询在key 上是相等的,并且在time 上排序,这意味着您为此使用了错误的索引(您的索引本质上是在time:1, key:1 上)。

您正在运行的查询的字段顺序应为key:1, time:1(作为前两个字段),以便从中获得有效帮助。使用该索引,可以直接跳转到匹配的key 值,然后如果该key 有多个time 值,则将它们排序并立即获取最高的值。如果在索引中找不到key,那么您就完成了。

事实上,查询被强制扫描索引(前导字段)中的所有时间值,以便当您找到第一个匹配键时,您将能够返回。当您要查找的键不存在时,查询最终会扫描整个索引,然后才能返回。

【讨论】:

  • 所以基本上我需要使用 1 个多键索引,它具有正确顺序的所有匹配和排序参数。我为这些字段使用了单独的索引。但是多键 ideed 成功了
  • "multikey" index 是数组的索引。您想使用“复合”索引 - 这是您已经在使用的,只是顺序错误。