这个故事实际上有两个方面,应用程序和服务器。
在应用程序中,第二个会更快。应用程序不必反序列化 BSON 文档(CPU 密集型),然后存储不需要数据的散列(内存密集型)。
在服务器上,MongoDB 可以在线发送更多数据,从而允许每个游标进行更多迭代,然后您必须执行getMore
操作,从而提高这方面的性能。不仅如此,您当然会发送更少的数据。对于getMore
内存和 CPU 而言,操作本身实际上是资源密集型的,因此这是一种节省。
至于在服务器本身内,投影的成本很小,但它会比把它全部带来的成本要小。
编辑
正如其他人所说,MongoDB 实际上使用投影来操作结果集,因此您将在两个查询之间拥有相同的工作集。
编辑
这是投影索引使用的结果:
> db.g.insert({a:1,b:1,c:1,d:1})
> db.g.ensureIndex({ a:1,b:1,c:1 })
> db.g.find({}, {a:0,b:0,c:0}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 3,
"nscannedObjects" : 3,
"n" : 3,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
> db.g.find({}, {a:1,b:1,c:1}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 3,
"nscannedObjects" : 3,
"n" : 3,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
这也是不使用投影的结果:
> db.g.find({}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 3,
"nscannedObjects" : 3,
"n" : 3,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
如您所见,milis
在文档上花费的时间实际上在两者之间是相同的:0
. 所以解释不是衡量这一点的好方法。
另一个编辑
排除 _id 不会应用覆盖索引:
> db.g.find({}, {a:1,b:1,c:1,_id:0}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 3,
"nscannedObjects" : 3,
"n" : 3,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
又一个编辑
并且有 300K 行:
> db.g.find({}, {a:1,b:1,c:1}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 300003,
"nscannedObjects" : 300003,
"n" : 300003,
"millis" : 95,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
> db.g.find({}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 300003,
"nscannedObjects" : 300003,
"n" : 300003,
"millis" : 85,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
因此,在庞大的结果集上进行投影确实成本更高,但请记住,在 300K 行上进行投影……我的意思是 WTF?谁会,在他们正确的头脑中,会这样做?所以这部分论点实际上并不存在。无论哪种方式,差异就像我的硬件上的 10 毫秒,几乎只有您查询的 1/10,因为这种投影在这里不是您的问题。
我还应该注意,该--cpu
标志不会给您想要的东西,对于初学者来说,它实际上与写锁定有关,其次是您进行读取。