Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 了解SQLAlchemy在对过期查询和更新进行迭代时的性能_Python_Mysql_Sqlalchemy - Fatal编程技术网

Python 了解SQLAlchemy在对过期查询和更新进行迭代时的性能

Python 了解SQLAlchemy在对过期查询和更新进行迭代时的性能,python,mysql,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 sess

我在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()
query_all = session.query(MasterImages.id, MasterImages.project_id, 
                          MasterImages.visit, MasterImages.orbit, 
                          MasterImages.drz_mode, MasterImages.cr_mode).all()
循环中的第一次迭代非常快,但在第一次提交后似乎会停止。我尝试了很多不同的方法,但都没有成功。然后,我尝试更改我的查询,以便它只选择我需要计算更新中使用的
set\u id
set\u index
值的字段,如下所示:

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()
query_all = session.query(MasterImages.id, MasterImages.project_id, 
                          MasterImages.visit, MasterImages.orbit, 
                          MasterImages.drz_mode, MasterImages.cr_mode).all()
这产生了我期待的表现,在不到一分钟的时间里翻阅了所有记录。经过一段时间的思考,我认为我的问题是,在提交后的第一个查询中,由于我更新了一个字段(不必要地)在我迭代的查询中,该字段变成了一个过时的查询。我认为,这迫使Alchemy在每次提交后重新生成查询。通过从我迭代的查询中删除我正在更新的字段,我认为我能够使用相同的查询,从而提高了性能

我说的对吗?

关机

启用提交时的
expire\u时,SQLAlchemy会在.commit()之后将query\u中的所有对象都标记为过期(或您所说的“过时”)。过期意味着,下次尝试访问对象上的属性时,SQLAlchemy将发出SELECT以刷新对象。关闭expire\u on\u commit将阻止它这样做。expire\u on\u commit是一个选项,这样就不会破坏ORM的原始使用,所以如果您知道自己在做什么,就可以安全地将其关闭


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

因此
在提交时过期
是我可以进行的额外优化吗?什么时候以及什么时候不使用此功能的最佳实践是什么?另外,我在我的原始帖子中对陈旧查询的理解是否正确?有点像。SQLAlchemy将
query\u all
中的所有对象标记为在
.commit()
之后过期(或您所说的“过时”),而不是在
.update()
之后。过期意味着下次尝试访问对象上的属性时,SQLAlchemy将发出
SELECT
刷新对象。关闭
在提交时过期将阻止它这样做
expire\u on\u commit
是一个选项,这样就不会破坏ORM的原始使用,因此如果您知道自己在做什么,可以安全地将其关闭。我已经更新了问题,使用适当的术语“expired”而不是“stale”。但是,您能解释一下为什么在我更改迭代的查询时我的代码会加速吗?当您在
query()
中指定列(
MasterImages.id
等)而不是映射类(
MasterImages
)时,SQLAlchemy会向您返回一个普通的python元组,而不是映射类的实例。元组不提供ORM特性,也就是说,它不会过期,也永远不会从数据库中重新获取自身。这非常有意义!请将您的评论添加到主要答案正文中,我将接受。