38

我在 mongo 中有一个查询,因此我想优先考虑第一个字段,然后是第二个字段。

说我必须这样查询

db.col.find({category: A}).sort({updated: -1, rating: -1}).limit(10).explain()

所以我创建了以下索引

db.col.ensureIndex({category: 1, rating: -1, updated: -1})

它可以根据需要扫描尽可能多的对象,即10.

但现在我需要查询

db.col.find({category: { $ne: A}}).sort({updated: -1, rating: -1}).limit(10)

所以我创建了以下索引:

 db.col.ensureIndex({rating: -1, updated: -1})

但这会导致扫描整个文档,当我创建

 db.col.ensureIndex({ updated: -1 ,rating: -1})

它扫描的文档数量更少:

我只想问清楚对多个字段进行排序以及这样做时要保留的顺序是什么。通过阅读 MongoDB 文档,很明显我们需要对其执行排序的字段应该是最后一个字段。这就是我在$ne上面的查询中假设的情况。我做错什么了吗?

4

4 回答 4

46

MongoDB查询优化器通过尝试不同的计划来确定哪种方法最适合给定查询。然后缓存该查询模式的获胜计划以供接下来的约 1,000 个查询使用,或者直到您执行explain().

要了解考虑了哪些查询计划,您应该使用explain(1),例如:

db.col.find({category:'A'}).sort({updated: -1}).explain(1)

allPlans详细信息将显示比较的所有计划。

如果您运行的查询不是很有选择性(例如,如果许多记录与您的条件匹配{category: { $ne:'A'}}),MongoDB 使用 BasicCursor(表扫描)而不是匹配索引来查找结果可能会更快。

查询中字段的顺序通常不会对索引选择产生影响(范围查询有一些例外)。排序中字段的顺序确实会影响索引选择。如果您的sort()条件与索引顺序不匹配,则必须在使用索引后重新排序结果数据(scanAndOrder:true如果发生这种情况,您应该在解释输出中看到)。

还值得注意的是,MongoDB每次查询只会使用一个索引$ors 除外)。

因此,如果您尝试优化查询:

db.col.find({category:'A'}).sort({updated: -1, rating: -1})

您将希望在索引中包含所有三个字段:

db.col.ensureIndex({category: 1, updated: -1, rating: -1})

仅供参考,如果您想强制特定查询使用索引(通常不需要或不推荐),hint()您可以尝试一个选项。

于 2012-09-21T11:58:02.080 回答
1

确实如此,但是由于您是在复合索引上排序,因此您在这里有两层排序。

正如您注意到的,当索引的第一个字段与排序的第一个字段匹配时,它起作用并且索引被看到。但是,当以相反的方式工作时,它不会。

因此,根据您自己的观察,需要保留的顺序是从第一个到最后一个字段的查询顺序。mongo 分析器有时可以在字段中移动以匹配索引,但通常它只会尝试匹配第一个字段,如果不能,它将跳过它。

于 2012-09-20T17:28:39.370 回答
0

试试这个代码,它将首先根据名称对数据进行排序,然后将“名称”保留在密钥持有者中,它将对“过滤器”进行排序

 var cursor = db.collection('vc').find({   "name" :   { $in: [ /cpu/, /memo/ ]   }     }, { _id: 0, }).sort( { "name":1  ,  "filter": 1 } );
于 2017-01-12T09:14:49.890 回答
0
Sort and Index Use¶

MongoDB can obtain the results of a sort operation from an index which includes the sort fields. MongoDB may use multiple indexes to support a sort operation if the sort uses the same indexes as the query predicate. ... Sort operations that use an index often have better performance than blocking sorts.

db.restaurants.find().sort( { "borough": 1, "_id": 1 } )

更多信息: https ://docs.mongodb.com/manual/reference/method/cursor.sort/

于 2021-09-27T06:47:14.600 回答