在大量查询结果的循环中,更新操作花费了奇怪的时间
Posted
技术标签:
【中文标题】在大量查询结果的循环中,更新操作花费了奇怪的时间【英文标题】:in the loop of large quantity query result, update operation costs strange time 【发布时间】:2014-12-10 14:03:55 【问题描述】:当我查询大量记录时,然后循环结果。 如果我更新一条记录,会花费很多时间。
_users = db.session.query(WxUser).limit(10000).all()
for _user in _users:
t1 = time()
db.session.query(WxUser).filter_by(id=_user.id).update(dict(sex=WxUser.Sex.MALE))
db.session.commit()
t2 = time()
print t2 - t1
输出:
0.242075920105
15.5323040485
16.6957418919
提交操作花费时间超过正常。 打开“SQLALCHEMY_ECHO”时,显示 SQLAlchemy 按 id 查询每条记录。
它是怎么发生的?
【问题讨论】:
你在问为什么 SQLAlchemy 会更新每条记录吗?因为您正在查询您的 foo 循环中的每个 WxUser 并更新其性别。在您的情况下,您正在对数据库进行 10001 次查询。 查询本身看起来非常缓慢。你为什么不尝试像db.session.query(WxUser).limit(10000).update(dict(sex=WxUser.Sex.MALE))
这样更简单的方法,即使那样也会花费很多时间。
【参考方案1】:
https://bitbucket.org/zzzeek/sqlalchemy/issue/3270/in-the-loop-of-large-quantity-query-result
我问 SQLAlchemy 的作者。 他给出了答案:
两种技术将解决所花费的时间。
轮流在 Python 中评估对象以查看它们是否符合条件:
s.query(WxUser).filter_by(id=_user.id).update(dict(data='M'), synchronize_session=False)
文档:http://docs.sqlalchemy.org/en/rel_0_9/orm/query.html?highlight=query.update#sqlalchemy.orm.query.Query.update.params.synchronize_session
在调用 update() 之前不要使会话中的所有 10000 个对象过期,这表明为了使上述 synchronize_session='evaulate' 起作用,它必须命中每个 WxUser 对象并评估它们的“id”,这需要从数据库中重新加载它们:
会话 = 会话(expire_on_commit=False)
文档:http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#committing
【讨论】:
以上是关于在大量查询结果的循环中,更新操作花费了奇怪的时间的主要内容,如果未能解决你的问题,请参考以下文章