【发布时间】:2018-09-19 00:11:00
【问题描述】:
我正在使用 Python 3、带有 mongodb 4.0 的 Pymongo 和 Ifxpy 来查询 Informix 数据库。我的 MongoDB 数据库中有 4 个集合:
- 用户
- 办公室
- 宠物
- 汽车
一个用户有一个办公室,一个宠物和一辆汽车。所以我对 User 集合中的每个字段都有 3 个引用。
我需要这样的东西:
- 我想查找是否有名称为
John的用户和名称为Mickey的宠物以及模型为Tesla和状态为inactive的汽车。之后,我将用户状态更新为active。我必须查询 Office,但在此示例中我没有使用它。
我为每个字段创建了索引:
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)])
这是我的代码:
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 秒。我有 20 000 件物品。我认为它真的很慢。
我试图通过删除所有 find_one 并只保留一个来查看每个带有 start = time.time()
的 find_one 的时间。如果我只让 Office find_one 它需要大约 12 秒,另一个相同。如果我让客户 find_one 也需要大约 12 秒。所以 ~12 * 4 这就是为什么所有 find_one 需要 ~47 秒。
你能告诉我我做错了什么吗?
【问题讨论】:
-
索引集合以支持您的查询。
-
对不起,我已经有索引了。我会编辑
-
抱歉,刚刚意识到您对每个集合执行 20k 次查询,这相当于每个查询半毫。我怀疑除非您更改应用程序,否则您是否可以使其更快。例如。一次将所有办公室加载到本地列表中,然后在不接触 mongo 的情况下检查它是否存在。
-
我不能这样做,因为如果您观看用户的 find_one,我需要检查多个属性:用户名 car_id 和 pet_id
-
我提出这个问题是因为@dnickless 让我解释我的循环:stackoverflow.com/a/52371589/2519631 因为等待 47 秒是不正常的
标签: python mongodb optimization