mongo查询时候如何选择索引
问题描述
mongo中有以下两个索引,第一个索引是:{_id}字段的单字段索引;
第二个索引是{chat_id, _id}组合成的复合索引。当我使用查询db.collection.find({"chat_id" : ObjectId("*********"), "the_time":{"$lt" : ISODate("2010-01-01T00:00:00Z")}}).sort({"the_time":-1}).explain("executionStats")
,为什么会得到下面这种结果分析
......
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"the_time" : -1
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"the_time" : {
"$lt" : ISODate("2010-01-01T00:00:00Z")
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"chat_id" : 1,
"_id" : 1
},
"indexName" : "chat_id_1__id_1"
......
为什么会使用到{chat_id, _id}组合成的复合索引?
我所了解到的复合索引是这样的
索引前缀指的是复合索引的子集
假如存在如下索引
{ "item": 1, "location": 1, "stock": 1 }
那存在下列索引前缀
{ item: 1 }
{ item: 1, location: 1 }
在MongoDB中,下列查询过滤条件情形中,索引将会被使用到
item字段
item字段 + location字段
item字段 + location字段 + stock字段
item字段 + location字段(尽管索引被使用,但不高效)
以下过滤条件查询情形,索引将不会被使用到
location字段
stock字段
location + stock字段
问题一: 难道是,复合索引中{chat_id, _id},即使使用的查询是{chat_id, the_time}中the_time字段不在复合索引中,但是chat_id在复合索引中,所以就会走这个复合索引么?
问题二: 另外,我额外加了一个索引{chat_id,third_field},依然查询{chat_id,the_time},最后得到的分析结果走的是{chat_id,third_field}这个索引,却没有走{chat_id, _id}此索引。mongo在索引选择上,是什么策略?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题一
如果走了第二条路,显然是相当耗费资源和时间的,因此我们所有的查询都要尽可能命中索引,或者部分命中索引。你的疑问可能是没有理解部分命中索引是怎么回事。假设你的集合有100w条记录,查询条件
{"chat_id" : ObjectId("*********"), "the_time":{"$lt" : ISODate("2010-01-01T00:00:00Z")}}
下:{chat_id: 1, _id: 1}
存在,它虽然不能完全满足你的查询,但是第一个条件是满足的。假设这个条件帮你过滤了90w条记录(只剩10w条),那么其余条件就只需要在这10w条中遍历就好了,是不是比遍历100w条要更优呢?如果选择了
{_id: 1}
,对查询没有任何帮助,跟第一种情况是一样的;如果选择{chat_id: 1, _id: 1}
,至少可以有一定帮助,所以为什么不选择后者?问题二
首先要理解一个问题,同一个条件就算使用相同的索引运行2次,执行时间也不一定就相同,因为服务器的压力情况不一定相同。那么你提到的两个索引
{chat_id,third_field}
和{chat_id,the_time}
它们对你的执行条件的作用几乎是没有什么差异的,先客观上两者取最高效者,总会选出一个更快者,一旦选出更快的一个,执行计划缓存会确保重启前一直使用它,而不是每次都来评估(浪费资源)。所以这里比较它们两个其实没有什么意义。其他
满足这个查询的最佳索引应该是:
{chat_id: 1, the_time: -1}