首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >大量调用SQLAlchemy的InstanceState类的到期方法

大量调用SQLAlchemy的InstanceState类的到期方法
EN

Stack Overflow用户
提问于 2013-12-13 20:46:46
回答 1查看 68关注 0票数 0

我使用11个并行进程执行数据处理任务,每次计算的结果都记录在一个InnoDB数据库的MySQL表中,使用SQLAlchemy的ORM。然而,处理时间比预期的要大。如果我分析了其中一个并行进程的执行情况,我可以看到大约30%的时间都花在了InstanceState类的that方法上,这个方法被称为.292,957,736次!

计算用17,106次迭代执行循环,并对每个迭代执行一次提交。在概要文件中,我看到提交方法被称为17,868,这似乎是一个良好的数量级( 761补充提交可能来自周围代码的其他部分)。然而,我不太清楚这个过期方法是干什么的,为什么要多次调用它。它是在每次提交时调用表的每一行吗?它看起来有点像,因为如果17,106^2 == 292,615,236…这种行为正常吗?在这种情况下,如何做得更好,有什么食谱或建议吗?确切的代码有点复杂(在computeForEvent(.)此文件的方法中),但是,SQLAlchemy部分在概念上等价于以下内容:

代码语言:javascript
复制
for i in range(17106):
    propagations = []
    for i in range(19):
        propagations.append(Propagation(...))
    session.add_all(propagations)
    session.commit()

其中Propagation是一个基子类。任何关于如何加快速度和避免爆炸的建议(.)打电话会很感激的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-12-25 19:16:18

在调用commit()时,将有292M调用将意味着内存中有这么多对象,这实际上是一个令人难以置信的巨大数字。

消除这些过期调用的一种直接方法就是将提交转换为False:

代码语言:javascript
复制
sess = Session(expire_on_commit=False)

要解决这个问题,一个更微妙的方法,但这需要更多的注意,就是不要在记忆中保存所有的对象,如果我们这样做的话:

代码语言:javascript
复制
for i in range(17106):
    session.add_all([Propagation() for i in range(19)])
    session.commit()

如果这个Propagation()对象的列表没有在没有引用周期的情况下被强引用,那么假设cPython将在去引用点上收集垃圾,并且不会受制于commit()中的过期调用。

还有一种策略可能只是将commit()延迟到循环之后,而不是使用flush()一次处理每一组项。这样,在到达commit()时,大多数对象将被垃圾收集。

不过,expire_on_commit仍然是解决这一问题的最直接方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20575692

复制
相关文章

相似问题

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