2014-08-28 61 views
1

我有一个有10-15万条目的mongodb数据库。对于他们每个人,我必须更新最初不存在的字段。假设应用程序因意外的服务器关闭而崩溃,那么最好如何更新剩余的条目?

我应该使用field: {$exists: false}并更新它们,还是应该遍历整个集合并检查每个文档是否有该字段,如果有,请执行更新?我认为这是因为你不能将一个索引与一个字段的存在联系起来,$ exists基本上是一样的。哪一个会更快,为什么?

请注意,该字段的值将依赖于文档的其他字段,因此我无法执行multi:true更新。

解决方案:作为@DhruvPathak和@Sammaye建议,而索引相关的数据,而不是自己的领域(所以你不能有一个索引链接到一个场的存在),$存在可以利用对存在这些字段的文档的索引,这大大提高了速度。

附加:虽然这是一个侧面的追求,我现在知道为什么应用程序崩溃的原因。服务器超时使用游标,因为它的使用时间太长(给定集合的大小)。这可以通过使用batch_size来解决,如here所述。

+0

[explain()](http://docs.mongodb.org/manual/reference/method/cursor.explain/)可能有帮助 – soulcheck 2014-08-28 13:26:00

+1

您可以为文档添加“field_exists”字段,默认为false。如果你更新文件,你将“field_exists”设置为true。你可以轻松地在这个领域建立一个索引。 – thomas 2014-08-28 13:30:49

+0

@soulcheck真的,解释将有助于$ exists查询,但在另一种情况下,我手动更新每个字段,解释不能给我关于循环更新每个文档的效率的数据。这是一个pymongo脚本。 – thehousedude 2014-08-28 13:31:56

回答

1

是的,你是对的,在这两种情况下,mongodb都会遍历整个集合。 完成此操作的另一个好方法是在此字段上创建索引, 使用$exists运算符选择目标索引,然后删除索引。 确保所创建的索引不稀疏,因为它在$存在的情况下无效。 http://docs.mongodb.org/manual/core/index-sparse/

+0

谢谢。有问题的字段是一个整数,所以我想升序索引会好吗? – thehousedude 2014-08-28 13:45:27

+1

创建索引然后删除它会增加开销。 – vmr 2014-08-28 13:48:27

1

附加到您的查询的explain()将显示$exists有一个类型为Basic的游标:这意味着它将扫描集合中的所有文档。因此,您可以遍历整个集合并检查每个文档是否有该字段,如果是,则执行更新。 $exists的性能类似于完整地扫描集合。

2

我对这个问题的看法是,现在,因为你不能用场

的存在的指标关联Acccording到MongoDB的2.6可以:

> use f 
switched to db f 
> db.t.insert({a:1}) 
WriteResult({ "nInserted" : 1 }) 
> db.t.ensureIndex({b:1}) 
{ 
     "createdCollectionAutomatically" : false, 
     "numIndexesBefore" : 1, 
     "numIndexesAfter" : 2, 
     "ok" : 1 
} 
> db.t.find({b:{$exists:false}}) 
{ "_id" : ObjectId("53e88a7dde0848171584d296"), "a" : 1 } 
> db.t.find({b:{$exists:false}}).explain() 
{ 
     "cursor" : "BtreeCursor b_1", 
     "isMultiKey" : false, 
     "n" : 1, 
     "nscannedObjects" : 1, 
     "nscanned" : 1, 
     "nscannedObjectsAllPlans" : 1, 
     "nscannedAllPlans" : 1, 
     "scanAndOrder" : false, 
     "indexOnly" : false, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "millis" : 0, 
     "indexBounds" : { 
       "b" : [ 
         [ 
           null, 
           null 
         ] 
       ] 
     }, 
     "server" : "ubuntu:27017", 
     "filterSet" : false 
} 
> 

从我可以找到它似乎是从v2.0添加的东西:https://stackoverflow.com/a/7503114/383478不幸的是该答案中的文档链接已经死亡。

因此,除非您的版本早于v2.0,否则查询显然会更快。

+0

谢谢,我不知道。尽管这似乎是一个上升的指标。从我发现的其他问题中,人们希望将一个指数与该领域的实际存在联系起来,而不是其价值。虽然它也可以使用这个版本,但它是好的。 – thehousedude 2014-08-28 14:22:15

+1

@thehousedude当然,这对于关键价值商店来说会更好,mongodb一直在评估http://rocksdb.org/从我最近在他们的JIRA上得到的结果。这就是他们制作可插拔存储引擎的原因之一,所以他们可以为您提供这些东西,就像您可以在其他技术如MySQL等 – Sammaye 2014-08-28 14:29:08