针对计数器字段构建索引

时间:2012-01-28 17:08:43

标签: mongodb indexing mongodb-indexes

对于作为计数器运行的字段,即,值将随时间变化,并将用于返回有序实体(将针对已过滤实体的此字段进行排序),是否应为此字段构建索引?

2 个答案:

答案 0 :(得分: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个“过滤器”。然后它随机选择一个doc来增加1M次的计数。每个过滤器的1M文档太大而无法在没有限制的情况下进行排序,因此显示该部分如何工作的唯一方法是设置限制。

结论如预期。它需要更长的时间(在这个测试中几乎是两倍 - 但是仍然相当快两倍),当有一个索引时更新计数字段。但查询速度要快得多。你必须决定哪一个对你更重要。

输出在这里(在我的macbook pro w / SSD上运行):

> 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

答案 1 :(得分:0)

奇怪的问题。索引用于高效查询。如果您在某个字段上查询,并且您可能有兴趣创建一个索引。 explain()告诉你执行计划。 MongoDB文档对此进行了全面介绍......那么为什么要问这样一个非常基本的问题呢?