2016-09-06 39 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