3

コレクションがphotosあり、各エントリがビューの詳細や詳細な賛成/反対を含む写真に関するすべての情報を含む大きなドキュメントである場合。

{
_id:ObjectId('...'),
title:'...',
location:'...',
views:[
    {...},
    {...},
    ...
    ],
upvotes:[
    {...},
    {...},
    ...
    ],
downvotes:[
    {...},
    {...},
    ...
    ],
}

どのクエリがより速く、より効果的に機能するか(メモリ、CPU使用率):

db.photos.find().limit(100)

また

db.photos.find({}, {views:0,upvotes:0,downvotes:0}).limit(100)

4

2 に答える 2

5

この話には、実際にはアプリケーションとサーバーの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また、フラグはあなたが望むものを提供しないことにも注意する必要があります。最初は、フラグは実際には書き込みロックに関係し、次に読み取りを行うことに関係します。

于 2012-12-20T09:51:15.350 に答える
3

あなたはそれを自分で行うことができます。explain()クエリの最後に追加するだけです。

例えば:

db.photos.find().limit(100).explain()


{
  "cursor" : "<Cursor Type and Index>",
  "isMultiKey" : <boolean>,
  "n" : <num>,
  "nscannedObjects" : <num>,
  "nscanned" : <num>,
  "nscannedObjectsAllPlans" : <num>,
  "nscannedAllPlans" : <num>,
  "scanAndOrder" : <boolean>,
  "indexOnly" : <boolean>,
  "nYields" : <num>,
  "nChunkSkips" : <num>,
  "millis" : <num>,
  "indexBounds" : { <index bounds> },
  "allPlans" : [
                 { "cursor" : "<Cursor Type and Index>",
                   "n" : <num>,
                   "nscannedObjects" : <num>,
                   "nscanned" : <num>,
                   "indexBounds" : { <index bounds> }
                 },
                  ...
               ],
  "oldPlan" : {
                "cursor" : "<Cursor Type and Index>",
                "indexBounds" : { <index bounds> }
              }
  "server" : "<host:port>",
}

ミルズパラメータはあなたが望むものです

CPU使用率を確認したい場合は、起動スクリプトに--cpu キーを追加するだけです。mongod

--cpu
Forces mongod to report the percentage of CPU time in write lock. mongod generates output every four seconds. MongoDB writes this data to standard output or the logfile if using the logpath option.

http://docs.mongodb.org/manual/reference/explain/

あなたはこのようにsmthのためhint()にmongoに提供することができます:projection()

簡単なコレクションがあります。

> db.performance.findOne()
{
        "_id" : ObjectId("50d2e4c08861fdb7e1c601ea"),
        "a" : 1,
        "b" : 1,
        "c" : 1,
        "d" : 1
}

23の要素で構成されています:

> db.performance.count()
23

これで、複合インデックスを作成できます。

> db.performance.ensureIndex({'c':1, 'd':1})

そして、投影にインデックスを使用するためのヒントをmongoに提供します。

> db.performance.find({'a':1}, {'c':1, 'd':1}).hint({'c':1, 'd':1}).explain()
{
        "cursor" : "BtreeCursor c_1_d_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 23,
        "nscanned" : 23,
        "nscannedObjectsAllPlans" : 23,
        "nscannedAllPlans" : 23,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "c" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ],
                "d" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ]
        },
        "server" : ""
}
>
于 2012-12-20T09:38:56.397 に答える