- mongodb集群复制集分片部署环境中. 中有一个collection device, device有2个索引a,b
- 有一条查询, 两种写法
// 耗时很稳定1ms. 根据索引a查询b字段的内容(b也是索引,返回结果为1条,内容在45字符左右)
db.getCollection('device').find({'a':'value'},{'b':1});
// 不稳2~2000ms都有可能, 根据索引a查询整个文档(返回结果为1条,内容在600字符左右)
db.getCollection('device').find({'a':'value'});
问题1: 求科普下整个查询的流程?
问题2: 同样走索引,返回文档也都是一条,只有返回内容大小有一些差异,但结果却天差地别.这其中的原理又是什么?
问题补充:
@Mongoing中文社区 大神,非常感谢你的回答. 本次提问其实是 mongodb走了索引,依旧是慢查询,请看执行计划 问题的续集(你在这个问题里也有回答. 叩谢).
上个问题的解决方式是将第2个查询语句改成第1个查询语句的方式,在我项目里面的到很好的效果.
所以非常想知道这两个查询直接的联系与不同点,以及整个查询的流程.
另外,能不能推荐几本好的mongodb的书(中文版的最好.英文不太好).羡慕你很专业,感觉有知识真的好酷.
不知道你说的查询流程是指什么?我理解你想看到的是执行计划
可以确定的是这两条查询的查询计划几乎是一样的。第二条少一个project stage,但通常这都不会造成这么大的影响。影响你查询时间的很可能不是查询本身,而是运行这些查询时服务器的资源状况。直白地说,可能有其他消耗很大的查询的执行影响到这条查询。
对补充问题的答复
这两个查询确实本质上没有太大的差别,有些场景可能造成性能差异,但不至于太大。
再次补充
不管你是取一个字段还是整个文档,磁盘上读出来的都是整个文档。因为文档是没有结构的,不整个读出来分析你怎么知道里面有哪些字段?所以想直接读出某个字段的内容在现阶段的WiredTiger引擎中是做不到的(但是确实在roadmap中)。我也考虑过covered query的可能性,但是你的写法明显也是做不到的,除非是:
才有可能跳过
FETCH
阶段。