2

カウンターとして機能しているフィールドの場合、つまり、値は時間の経過とともに変更され、順序付けられたエンティティを返すために使用されます(フィルター処理されたエンティティのこのフィールドに対してソートされます)、このフィールドのインデックスを作成する必要がありますか?

4

2 に答える 2

4

完全には明確ではありませんが、問題は、頻繁に更新されるフィールドでインデックスを作成することの短所が、そのフィールドでの高速クエリと並べ替えの利点を上回るかどうかということだと思います。また、クエリが別のフィールドでフィルタリングされることを意味し、次にこのフィールドで並べ替えます。正確なユースケースについて自由に詳しく説明してください。

私があなたが欲しいと思うのはこのようなものです:

db.test.save({filter: "stuff", count: "1"});
db.test.save({filter: "stuff", count: "3"});
db.test.save({filter: "stuff", count: "2"});
db.test.save({filter: "notstuff", count: "2"});
db.test.save({filter: "notstuff", count: "2"});

そして、そのようなインデックス:

db.test.ensureIndex({filter:1, count:1});

そして、次のようなクエリ:

db.test.find({filter:"stuff"}).sort({count:1});
{ "_id" : ObjectId("4f24353eef88b8b53a20fdf5"), "filter" : "stuff", "count" : "1" }
{ "_id" : ObjectId("4f24353eef88b8b53a20fdf7"), "filter" : "stuff", "count" : "2" }
{ "_id" : ObjectId("4f24353eef88b8b53a20fdf6"), "filter" : "stuff", "count" : "3" }

これはbtreeを使用します:

db.test.find({filter:"stuff"}).sort({count:1}).explain();
{
"cursor" : "BtreeCursor filter_1_count_1",
"nscanned" : 3,
"nscannedObjects" : 3,
...

さて、それは本当にあなたが取り戻す必要がある結果の数に依存するかもしれません。結果がわずかしかない場合は、インデックスなしでフィールドで並べ替えることができます。これにより、更新のパフォーマンスが向上します。興味があるので、実際にいくつかのテストを行うと思います。少し更新します。

更新このベンチマークを作成したのは、インデックスでの並べ替えとそうでない場合の並べ替えと、インデックスでのカウントフィールドの更新とではない場合の違いを示すためです。ここに完全なコード:https ://gist.github.com/1696041

700Kと7Mのドキュメントを(いくつかのバリエーションを取得するために)7つの「フィルター」に分けて挿入します。次に、ドキュメントをランダムに選択して、100万回のカウントをインクリメントします。フィルタごとの1Mドキュメントは大きすぎて制限なしで並べ替えることができないため、その部分がどのように機能するかを示す唯一の方法は、制限を設定することです。

結論は予想通りです。インデックスがある場合、カウントフィールドの更新には時間がかかります(このテストではほぼ2倍の長さですが、それでもかなり高速です)。ただし、クエリを実行する方がはるかに高速です。あなたはどちらがあなたにとってより重要であるかを決定しなければなりません。

出力はここにあります(SSD付きの私のmacbookproで実行されています):

> bench();
benchmarking with index on {filter,data}, 700K docs  
initialInsert of 700000 done in: 58304ms, 0.08329142857142857ms per insert
updateCounts 1000000 times done in: 103915ms, 0.103915ms per update
explain find({filter:"abcd"}).sort({count:-1}): 
   cursor: BtreeCursor filter_1_data_1
   nscanned: 100000
   scanAndOrder: true
   millis: 1235
explain find({filter:"abcd"}).limit(100).sort({count:-1}): 
   cursor: BtreeCursor filter_1_data_1
   nscanned: 100000
   scanAndOrder: true
   millis: 614
benchmarking with index on {filter,data} and {filter, count}, 700k docs
initialInsert of 700000 done in: 72108ms, 0.10301142857142857ms per insert
updateCounts 1000000 times done in: 202778ms, 0.202778ms per update
explain find({filter:"abcd"}).sort({count:-1}): 
   cursor: BtreeCursor filter_1_count_-1
   nscanned: 100000
   scanAndOrder: undefined
   millis: 139
explain find({filter:"abcd"}).limit(100).sort({count:-1}): 
   cursor: BtreeCursor filter_1_count_-1
   nscanned: 100
   scanAndOrder: undefined
   millis: 0
benchmarking with index on {filter,data}, 7M docs
initialInsert of 7000000 done in: 616701ms, 0.08810014285714286ms per insert
updateCounts 1000000 times done in: 134655ms, 0.134655ms per update
explain find({filter:"abcd"}).sort({count:-1}): 
***too big to sort without limit!***
explain find({filter:"abcd"}).limit(100).sort({count:-1}): 
   cursor: BtreeCursor filter_1_data_1
   nscanned: 1000000
   scanAndOrder: true
   millis: 6396
benchmarking with index on {filter,data} and {filter, count}, 7M docs
initialInsert of 7000000 done in: 891556ms, 0.12736514285714284ms per insert
updateCounts 1000000 times done in: 280885ms, 0.280885ms per update
explain find({filter:"abcd"}).sort({count:-1}): 
   cursor: BtreeCursor filter_1_count_-1
   nscanned: 1000000
   scanAndOrder: undefined
   millis: 1337
explain find({filter:"abcd"}).limit(100).sort({count:-1}): 
   cursor: BtreeCursor filter_1_count_-1
   nscanned: 100
   scanAndOrder: undefined
   millis: 0
于 2012-01-28T17:53:36.327 に答える
0

奇妙な質問。インデックスは効率的なクエリに使用されます。フィールドでクエリを実行し、興味があると思われる場合は、インデックスを作成します。Explain()は実行プランについて教えてくれます。これはすべてMongoDBのドキュメントで詳しく説明されています...では、なぜこのような非常に基本的な質問をするのですか?

于 2012-01-28T17:24:33.060 に答える