2016-09-06 79 views
0

以下代码块查询具有〜2000行的表。循环需要20s执行!从我有限的知识中,我不认为我正在做2000个查询,只是一个,但也许我不理解'。'。运营商以及它在幕后做了些什么。我怎样才能修复这个循环以更快地运行?有没有办法调整顶级查询s.t.第二个for循环不总共提供3000个查询(如果这实际上是发生了什么)?SQLAlchemy在迭代中性能不佳

这里是一个代码的测试块,用于验证它实际上是导致大量时间消耗的内部循环。

block = [] 
cnt = 0 
for blah in dbsession.query(mytable): 
    tic = time.time() 
    for a in blah.component: 
     cnt += 1 
    block.append(time.time()-tic) 
print "block: %s seconds cnt: %s" % (sum(block), cnt) 

# block: 20.78191 seconds cnt: 3021 

使用从所选择的最佳答案的建议,for循环成为:

for blah in dbsession.query(mytable).options(joinedload(mytable.componentA)).options(mytable.componentB)).options(mytable.componentC) 

这导致每个部件从每个20-25s去的内部循环,以0.25 0.59和0.11 s。查询本身现在需要大约18秒...所以我总共节省了大约55秒的时间。

+0

什么是'blah.component'?一列?关系? – RazerM

+0

“我不认为我在做2000个查询”:您应该启用日志记录或将'echo = True'传递给引擎。 – RazerM

+0

我不熟悉数据库,但我相信有一段感情。它列在orm.mapper(a,b,properties = {'component':orm.relationship(othercomponent,secondary = ,primaryjoin = == ,secondaryjoin = == }) – pyInTheSky

回答

2

每次访问.component时都会发出另一个SQL查询。

你可以阅读更多的Relationship Loading Techniques,但加载它一下子就可以查询更改为以下:

from sqlalchemy.orm import joinedload 

dbsession.query(mytable).options(joinedload('component')) 
+0

for循环会变成:对于blah,blahcomponent在dbsession.query ...? – pyInTheSky

+0

不,只是'在dbsession.query中查找blah(...',SQLAlchemy知道,当你然后访问'.component'时,它已经被加载。 – RazerM

+0

单词不能开始表达我的感激之情... 21s到0.37s – pyInTheSky