mongo 在聚合中匹配前排序
mongo sort before match in aggregation
给定一个包含几百万个文档的集合,如下所示:
{
organization: ObjectId("6a55b2f1aae2fe0ddd525828"),
updated_on: 2019-04-18 14:08:48.781Z
}
和 2 个索引,在键 {organization: 1} 和 {updated_on: 1}
上
以下查询需要 ages 到 return:
db.getCollection('sessions').aggregate([
{
"$match" : {
"organization" : ObjectId("5a55b2f1aae2fe0ddd525827"),
}
},
{
"$sort" : {
"updated_on" : 1
}
}
])
需要注意的一点是,结果是 0 个匹配项。经过进一步调查,explain() 中的规划器实际上 return 如下:
{
"stage" : "FETCH",
"filter" : {
"organization" : {
"$eq" : ObjectId("5a55b2f1aae2fe0ddd525827")
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"updated_on" : 1.0
},
"indexName" : "updated_on_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"updated_on" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"updated_on" : [
"[MinKey, MaxKey]"
]
}
}
}
- 为什么 Mongo 将这些合并到一个阶段并决定在过滤之前对所有文档进行排序?
- 我该如何预防?
MongoDB 会使用 $sort
上的索引,因为这是一个繁重的操作,即使之前匹配也会限制要排序的结果,
您可以强制使用 $match
:
的索引
db.collection.aggregate(pipeline, {hint: "index_name"})
或者创建一个更好的索引来解决这两个问题,查看更多信息here
db.collection.createIndex({organization: 1, updated_on:1}, {background: true})
Why would Mongo combine these into one stage and decide to to sort ALL
documents BEFORE filtering? How can I prevent that?
排序确实发生在比赛阶段之后。查询计划 没有 显示 SORT 阶段 - 这是因为排序键 updated_on
上有一个索引。如果删除 updated_on
字段上的索引,您 将 在查询计划中看到一个 SORT 阶段(并且它将是内存中排序)。
见Explain Results - sort stage。
一些想法:
(i) 您可以使用复合索引,而不是两个单字段索引:
{ organization: 1, updated_on: 1 }
它将正常工作。在 Sort and Non-prefix Subset of an Index.
上查看此主题
(ii) 此外,find()
查询可以完成相同的工作,而不是聚合:
db.test.find( { organization : ObjectId("5a55b2f1aae2fe0ddd525827") } ).sort( { updated_on: 1 } )
注意:请使用 explain()
进行验证并查看它们的性能。另外,尝试使用 executionStats
模式。
给定一个包含几百万个文档的集合,如下所示:
{
organization: ObjectId("6a55b2f1aae2fe0ddd525828"),
updated_on: 2019-04-18 14:08:48.781Z
}
和 2 个索引,在键 {organization: 1} 和 {updated_on: 1}
上以下查询需要 ages 到 return:
db.getCollection('sessions').aggregate([
{
"$match" : {
"organization" : ObjectId("5a55b2f1aae2fe0ddd525827"),
}
},
{
"$sort" : {
"updated_on" : 1
}
}
])
需要注意的一点是,结果是 0 个匹配项。经过进一步调查,explain() 中的规划器实际上 return 如下:
{
"stage" : "FETCH",
"filter" : {
"organization" : {
"$eq" : ObjectId("5a55b2f1aae2fe0ddd525827")
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"updated_on" : 1.0
},
"indexName" : "updated_on_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"updated_on" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"updated_on" : [
"[MinKey, MaxKey]"
]
}
}
}
- 为什么 Mongo 将这些合并到一个阶段并决定在过滤之前对所有文档进行排序?
- 我该如何预防?
MongoDB 会使用 $sort
上的索引,因为这是一个繁重的操作,即使之前匹配也会限制要排序的结果,
您可以强制使用 $match
:
db.collection.aggregate(pipeline, {hint: "index_name"})
或者创建一个更好的索引来解决这两个问题,查看更多信息here
db.collection.createIndex({organization: 1, updated_on:1}, {background: true})
Why would Mongo combine these into one stage and decide to to sort ALL documents BEFORE filtering? How can I prevent that?
排序确实发生在比赛阶段之后。查询计划 没有 显示 SORT 阶段 - 这是因为排序键 updated_on
上有一个索引。如果删除 updated_on
字段上的索引,您 将 在查询计划中看到一个 SORT 阶段(并且它将是内存中排序)。
见Explain Results - sort stage。
一些想法:
(i) 您可以使用复合索引,而不是两个单字段索引:
{ organization: 1, updated_on: 1 }
它将正常工作。在 Sort and Non-prefix Subset of an Index.
上查看此主题(ii) 此外,find()
查询可以完成相同的工作,而不是聚合:
db.test.find( { organization : ObjectId("5a55b2f1aae2fe0ddd525827") } ).sort( { updated_on: 1 } )
注意:请使用 explain()
进行验证并查看它们的性能。另外,尝试使用 executionStats
模式。