この話には、実際にはアプリケーションとサーバーの2つの側面があります。
アプリケーションでは、2番目の方がはるかに高速になります。アプリケーションは、BSONドキュメント(CPUを集中的に使用する)を逆シリアル化してから、不要なデータのハッシュ(メモリを集中的に使用する)を保存する必要はありません。
サーバー上で、MongoDBはより多くのデータをネットワークに送信できるため、操作を実行する前にカーソルあたりの反復回数getMore
を増やすことができ、その前線でのパフォーマンスを向上させることができます。それだけでなく、もちろん、送信するデータも少なくなります。操作は、実際にはメモリとCPUの両方でリソースを大量に消費するgetMore
ため、節約になります。
サーバー自体の内部に関しては、予測にわずかなコストがかかりますが、それを全体に持ち込むコストよりも小さくなります。
編集
他の人が言っているように、MongoDBは実際にはプロジェクションを使用して結果セットを操作するだけなので、2つのクエリ間で同じワーキングセットが得られます。
編集
これは、プロジェクションでのインデックスの使用結果です。
> 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
。したがって、explainはこれを測定する良い方法ではありません。
別の編集
_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
また、フラグはあなたが望むものを提供しないことにも注意する必要があります。最初は、フラグは実際には書き込みロックに関係し、次に読み取りを行うことに関係します。