mongodb查询一个文档与一个字段的差别

  1. mongodb集群复制集分片部署环境中. 中有一个collection device, device有2个索引a,b
  2. 有一条查询, 两种写法
// 耗时很稳定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的书(中文版的最好.英文不太好).羡慕你很专业,感觉有知识真的好酷.

阅读 2.7k
1 个回答

不知道你说的查询流程是指什么?我理解你想看到的是执行计划

db.getCollection('device').find({'a':'value'},{'b':1}).explain(true);
db.getCollection('device').find({'a':'value'}).explain(true);

可以确定的是这两条查询的查询计划几乎是一样的。第二条少一个project stage,但通常这都不会造成这么大的影响。影响你查询时间的很可能不是查询本身,而是运行这些查询时服务器的资源状况。直白地说,可能有其他消耗很大的查询的执行影响到这条查询。

对补充问题的答复

这两个查询确实本质上没有太大的差别,有些场景可能造成性能差异,但不至于太大。

再次补充

不管你是取一个字段还是整个文档,磁盘上读出来的都是整个文档。因为文档是没有结构的,不整个读出来分析你怎么知道里面有哪些字段?所以想直接读出某个字段的内容在现阶段的WiredTiger引擎中是做不到的(但是确实在roadmap中)。我也考虑过covered query的可能性,但是你的写法明显也是做不到的,除非是:

db.getCollection('device').find({'a':'value'},{'b':1, _id: 0})

才有可能跳过FETCH阶段。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏