Python 加快400万个mongodb更新

Python 加快400万个mongodb更新,python,performance,mongodb,indexing,pymongo,Python,Performance,Mongodb,Indexing,Pymongo,我们有一个大约400万条的defaultdict,如: my_dict = {'page_abc': 1234545, 'page_asdf': 54231} 我们有一个mongoDB集合,大约有1000万条条目,其中每个文档都是: {'page':'page_abc', 'volume': 321, '_id':whatever} 这是由\u id(mongodb默认值)和页面(我设置的)索引的 我只需要用现有的页面更新集合。我的代码最初是: for page, volume in my_

我们有一个大约400万条的defaultdict,如:

my_dict = {'page_abc': 1234545, 'page_asdf': 54231}
我们有一个mongoDB集合,大约有1000万条条目,其中每个文档都是:

{'page':'page_abc', 'volume': 321, '_id':whatever}
这是由
\u id
(mongodb默认值)和
页面
(我设置的)索引的

我只需要用现有的页面更新集合。我的代码最初是:

for page, volume in my_dict.iteritems():
    entry = c.db.coll.find_one({'page':page})
    if entry:
        c.db.coll.update({'_id':entry['_id']}, 
                         {'$set':{'volume':entry['volume']+volume}})
但结果证明这需要大约3个小时。我只抓取了一次收藏品,加快了速度:

for entry in c.db.coll.find():
    if entry['page'] in my_dict:
        c.db.coll.update({'_id':entry['_id']}, 
                         {'$set':{'volume'+log_file_date:my_dict[entry['page']]}})
这大约需要58分钟。考虑到我每天都要这样做,这仍然是非常缓慢的。 这能加快速度吗

我现在的想法是:

  • 也许删除默认的_id索引,或者甚至一起删除?双重指数可能会让事情放缓
  • 可能会从字典中删除重复经过的键?尽管如此,我认为字典在O(1)查找方面还是相当快的

编辑:我对我的更新进行了计时,准确地说,我每秒可以完成3227次。这能改进吗?或者我已达到硬件限制(7200rpm希捷st2000dm001 cc43)

我建议您使用$inc运算符。这样,您就不需要进行查找,并且可以立即进行更新。代码如下:

for page, volume in my_dict.iteritems():
    c.db.coll.update({'page':page},{'$inc':{'volume':volume}})
for page, volume in my_dict.iteritems():
    c.db.coll.update({'page':page},{'$set': {'volume'+log_file_date:my_dict['page']}})
由于upsert参数未设置为True,因此仅当文档存在时才会更新该文档

编辑: 即使您想添加新属性,也可以在一次调用中完成。我不明白你为什么要找。代码如下:

for page, volume in my_dict.iteritems():
    c.db.coll.update({'page':page},{'$inc':{'volume':volume}})
for page, volume in my_dict.iteritems():
    c.db.coll.update({'page':page},{'$set': {'volume'+log_file_date:my_dict['page']}})

您的MongoDB集合中有多少个条目? 如果数量级少一个数量级,您可以将c.db.coll.distinct('page')的结果放入内存,然后在内存中进行过滤,而不是逐个查询mongoDB。
如果集合包含的条目太多,则可以将页面分块(例如,一个块中有-1000个页面),然后在find的结果上运行distinct({'page':{'in':block_of_pages}).

您的底层代码仍然执行400万个您不需要执行的
查找一个操作。啊,是的,对不起,只是一个拼写错误问题仍然存在。啊,对不起,我认为我太简化了问题。实际上,它在每个文档中为每个日期设置一个新属性(请参见上面的编辑)。也许我可以将这些卷计数作为每个文档中的一个列表,并使用push将[date,volume]添加到每个列表中?我不确定是否完全理解您的编辑。但我在我的回答中添加了一个编辑,可能解决了您的问题。我的观点是,你不需要去寻找。您可以直接执行更新。感谢您的帮助。我查找的原因也是因为以后我想插入不存在的页面。我将尝试升级-也许这会加快速度,所以我尝试了你的升级想法。实际上,上升速度大约是我的解决方案的两倍:(