加速400万mongodb更新

时间:2014-02-26 19:01:17

标签: python performance mongodb indexing pymongo

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

my_dict = {'page_abc': 1234545, 'page_asdf': 54231}

我们有一个mongoDB集合,有大约1000万个条目,每个文档都是:

{'page':'page_abc', 'volume': 321, '_id':whatever}

这是由_id(mongodb默认)和page(我设置)索引。

我只需要使用存在的页面更新集合。我的代码最初是:

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 seagate st2000dm001 cc43)

2 个答案:

答案 0 :(得分:0)

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

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

由于upsert参数未设置为True,因此当且仅当文档存在时才会更新文档。

编辑: 即使您想要添加新属性,也可以在一次调用中完成。我不明白为什么你需要做这个发现。这是代码:

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

答案 1 :(得分:0)

您的MongoDB系列中有多少个条目? 如果它减少了一个数量级,你可以将c.db.coll.distinct(' page')的结果放到内存中,然后在内存中过滤,而不是一个一个地查询到mongoDB。 如果集合包含太多条目,您可以将页面块化为块(让我们说 - 块中的1000页),然后在查找结果上运行不同({'页面&# 39;:{' $ in':block_of_pages}})。