首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加速Pymongo查询

加速Pymongo查询
EN

Stack Overflow用户
提问于 2018-09-18 13:07:11
回答 1查看 1.8K关注 0票数 0

我使用Python3、Pymongo和MongoDB4.0以及Ifxpy查询Informix数据库。我在我的MongoDB数据库中有4个集合:

  • 用户
  • 办公室
  • 宠物
  • 小汽车

一个用户有一个办公室,一个宠物和一辆汽车。因此,我在用户集合中的每个字段上都有3个引用。

我需要这样的东西:

  • 我想知道是否有一个名为John的用户和一个名为Mickey的宠物,以及一个带有Tesla模型和状态inactive的汽车。在此之后,我只需将用户状态更新为active。我必须查询Office,但在本例中我没有使用它。

我为每个字段创建了索引:

代码语言:javascript
复制
office.create_index([("code", pymongo.DESCENDING)], unique=True)
pet.create_index([("name", pymongo.DESCENDING)], unique=True)
car.create_index([("model", pymongo.DESCENDING)], unique=True)
user.create_index([("username", pymongo.DESCENDING)], unique=True)
user.create_index([("pet", pymongo.DESCENDING)])
user.create_index([("car", pymongo.DESCENDING)])
user.create_index([("status", pymongo.DESCENDING)])

这是我的代码:

代码语言:javascript
复制
office_id = None
car_id = None
pet_id = None
ifx_connection = IfxPy.connect(ifx_param, "", "")
stmt = IfxPy.exec_immediate(ifx_connection, sql)
dictionary = IfxPy.fetch_assoc(stmt) # Get data key / value
start = time.time()

# Loop on informix data (20 000 items)
while dictionary != False:
    # Trim all string in dict
    dictionary = {k: v.strip() if isinstance(v, str) else v for k,v in dictionary.items()}

    # Get office
    office_code = dictionary['office_code']
    existing_office = office.find_one({"code": office_code})

    if bool(existing_office):
        office_id = existing_office['_id']

    # Get pet
    existing_pet = pet.find_one({"name": dictionary['pet_name']})
    if bool(existing_pet):
        pet_id = existing_pet['_id']

    # Get car
    existing_car = car.find_one({"model": dictionary['car_model']})

    if bool(existing_car):
        car_id = existing_car['_id']

    # Get user
    existing_user = user.find_one({
        "username": dictionary['username'],
        "car": car_id,
        "pet": pet_id,
        "status" : "inactive"
    })

    if bool(existing_user):
        # Change user status
        user.update_one({'_id': existing_user['_id']}, {"$set": {"status" : "active"}}, upsert=False)

    # Next row
    dictionary = IfxPy.fetch_assoc(stmt)

如果从循环中删除MongoDB代码,则需要1,33秒。如果我查询MongoDB,它需要47秒。我有两万件东西。我觉得真的很慢。

我试图通过删除所有的find_one并只允许一个find_one来查看每个start = time.time()的时间。如果我只让Office find_one,它需要12秒的时间,其他的也是一样的。如果我让客户find_one,它也需要12秒。所以~12 *4这就是为什么所有的find_one都需要47秒。

你能告诉我我做错了什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-18 14:27:47

为了加快算法的速度,您需要减少MongoDB查询的数量,这可以通过利用您对数据的了解来完成。因此,如果您知道您只有几个不同的办公室,或者您可能在某个阶段(或者是相同的一个重复)查询它们,那么您可能希望在循环之外的一个初步步骤中加载所有的办公室(!)并使用字典缓存它们,以便在循环中进行快速查找,而不需要另一次数据库往返。宠物和汽车也一样。

所以,更确切地说,我会:

  1. 按照您已经完成的方式运行informix查询
  2. 使用三个预先查询检索所有办公室、宠物和汽车。如果您想优化这个阶段,您将只检索包含在informix数据集中各自列的不同值中的内容。还要确保在输出中添加一个只包含name/model/code + _id字段的投影,以减少所涉及的BSON处理量。
  3. 将返回的值放入三个字典(name->_idmodel->_idcode->_id)。
  4. 循环遍历informix结果集,您已经这样做了
  5. 对于informix结果集中的每个用户,在列表中附加一个更新模型,其中选择条件由以前收集的所有细节组成,并且更新部分是静态的。
  6. 在外部(之后)循环使用批量更新更新所有用户
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52387322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档