我有一个 MongoDB 集合,用于存储一些测试提交。高级架构如下所示。
{
"lessonType": "quiz",
"userId": "639cb6d9513a420026eddca1"
"courseId": "639cb6d9513a420026eddca2",
"lessonId": "639cb6d9513a420026eddca3",
...some_more_fields
}
现在这个集合有两个索引。
第一个:
{ courseId: 1, lessonId: 1, userId:1 }
第二个:
{ lessonType: 1, courseId: 1 }
lessonType 只有两个值,分别是
quiz
和 assignment
。
现在我想查找特定课程的所有提交,其类型为
quiz
。
示例查询:
{ courseId: ObjectId("63a2eb428899436daf7eb489"),lessonType: "quiz" }
上面的查询始终考虑上面提到的第一个索引,而不是第二个索引。
在第一个索引中,只有
courseId
才有用,但在第二个索引中,它可以同时使用 courseId
和 lessonType
。
如果使用第二个索引,需要扫描的文档将减少2倍。
这里有什么建议吗?
我浏览了一些建议在执行查询时提供提示的文章。
还有其他办法吗?
如果第二个索引性能更高,为什么 mongo 默认不使用它?
在 MongoDB 中,查询规划器尝试通过考虑多种因素来为查询选择最有效的执行路径。
请注意,出于以下几个原因,查询计划器可能不会选择您认为最有效的索引:
courseId
是第一个键,而在第二个索引中,lessonType
是第一个,这可能会影响选择。至于你关于提示的问题,是的,提示是一种手动指示 Mongo 数据库引擎使用特定索引进行查询的方法,绕过查询规划器的自动选择过程。
但要小心,如果操作不当,使用提示强制使用特定索引可能会适得其反,由 MongoDB 规划者来决定可能会更有效。理想情况下,MongoDB 应该能够自动为您的查询选择最佳索引,但情况并非总是如此。
如果索引效率始终是一个问题,您可能需要考虑修改索引策略。也许像
{ courseId: 1, lessonId: 1 }
或 { courseId: 1, lessonType: 1}
这样的索引更适合您的工作负载。请记住,每个索引决策都是存储空间、写入性能和读取性能之间的权衡。
这里是建议如何使用复合索引的官方文档
索引前缀是索引字段的开始子集。复合索引支持对索引前缀中包含的所有字段进行查询。 (https://www.mongodb.com/docs/manual/core/indexes/index-types/index-compound/#index-prefixes)