python - 迭代过期查询和更新时了解 SQLAlchemy 性能

标签 python mysql sqlalchemy

我在 SQLAlchemy 中迭代查询并对行执行更新,我遇到了意想不到的低性能,比我预期的慢了几个数量级。该数据库有大约 12K 行。我的原始查询和循环如下所示:

query_all = session.query(MasterImages).all()

for record_counter, record in enumerate(query_all):
    # Some stuff happens here, set_id and set_index are defined
    session.query(MasterImages).\
            filter(MasterImages.id == record.id).\
            update({'set_id':set_id, 'set_index':set_index})
    if record_counter % 100 == 0:
        session.commit()
        print 'Updated {:,} records'.format(record_counter)
session.commit()

循环的第一次迭代非常快,但在第一次提交后它似乎会停止。我尝试了多种不同的方法,但无处可去。然后我尝试更改我的查询,以便它只选择我需要的字段来计算我在更新中使用的 set_idset_index 值,如下所示:

query_all = session.query(MasterImages.id, MasterImages.project_id, 
                          MasterImages.visit, MasterImages.orbit, 
                          MasterImages.drz_mode, MasterImages.cr_mode).all()

这产生了我预期的性能,在不到一分钟的时间内翻遍了所有记录。考虑了一段时间后,我认为我的问题是在我的第一个查询中,在提交之后,变成了一个陈旧的查询,因为我已经更新了一个字段,这个字段(不必要地)在我正在迭代的查询中。我认为,这迫使 Alchemy 在每次提交后重新生成查询。通过从我正在迭代的查询中删除我正在更新的字段,我认为我能够使用相同的查询,这导致我的性能提高。

我说的对吗?

最佳答案

关闭 expire_on_commit .

启用 expire_on_commit 后,SQLAlchemy 在 .commit() 之后将 query_all 中的所有对象标记为已过期(或如您所说的“陈旧”)。过期意味着下次您尝试访问对象上的属性时,SQLAlchemy 将发出 SELECT 以刷新对象。关闭 expire_on_commit 将阻止它这样做。 expire_on_commit 是一个选项,因此 ORM 的天真使用不会被破坏,所以如果你知道你在做什么,你可以安全地关闭它。

您的修复工作有效,因为当您在 query() 中指定列(MasterImages.id 等)而不是映射类 (MasterImages) 时,SQLAlchemy 返回给您一个普通的 python 元组而不是映射类的实例。该元组不提供 ORM 功能,即它不会过期并且永远不会从数据库中重新获取自身。

关于python - 迭代过期查询和更新时了解 SQLAlchemy 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21766023/

相关文章:

mysql - 构建数据库模式时,字段类型有多重要?

mysql - 如何从 varchar 中删除变量字符串

python-3.x - 未实现错误 : executemany is implemented for simple INSERT statements only

android - OLA API 集成给出错误作为无效的合作伙伴 key

python - 测量 python 多处理中浪费的时间

python - 捕获网页的浏览器特定呈现?

python - Flask url_for 停止接受两位数的用户 ID。漏洞?

python - Selenium 如何在某些目标类中获取href的内容

MySql case语句性能

python - 如何使用 sqlalchemy 核心 api 多次正确连接同一个表?