2013-06-28 12 views
0

這是我的數據庫的簡化項目。如何立即加載所有與SQLAlchemy中指定的對象相關的對象?

enter image description here

我的模型是由SQLAlchemy的創建,它看起來像這樣

#!/usr/bin/python 

class Book(Base): 
    id = Column(Integer, primary_key = True) 
    title = Column(Unicode(512)) 
    sentenses = relationship("Sentense", backref = backref("book", uselist = False)) 
    isbns = relationship("ISBN", secondary = books_isbns, backref = "book") 
    authors = relationship("Author", secondary = books_authors, backref = "book") 

class Sentense(Base): 
    id = Column(Integer, primary_key = True) 
    content = Column(Unicode(512)) 
    words = relationship("Word", secondary = sentenses_words, backref = "sentense") 

class Word(Base): 
    id = Column(Integer, primary_key = True) 
    content = Column(Unicode(32), index = True, unique = True) 
    soundex_id = Column(Integer, ForeignKey('Soundex.id')) 

class Soundex(Base): 
    id = Column(Integer, primary_key = True) 
    code = Column(Unicode(5), index = True, unique = True) 
    words = relationship("Word", backref = backref("soundex", uselist = False)) 

問題是與物投入的時間。使用大profiler我得到這個:

Line #  Hits   Time Per Hit % Time Line Contents 
============================================================== 
    111            @staticmethod 
    112            @profile 
    113            def getBooksWithSimilarWordsLikeInThisSentence(session, sentense): 
    114  16   51  3.2  0.0   s = set() 
    115  89  116294 1306.7  0.1   for word in sentense.words: 
    116  4200  712414 169.6  0.5    for word in word.soundex.words: 
    117  33690  13370590 396.9  8.7     for sentense in word.sentense: 
    118  29563  130437  4.4  0.1      if sentense.id != sentense.id: 
    119  18732  44930792 2398.6  29.3       s.add(sentense.book) 
    120           
    121  16   709  44.3  0.0   list_of_other_books = list(s) 
    122           
    123 
    124  18748  25865  1.4  0.0   for book in list_of_other_books: 
    125 
    126  39016  48461924 1242.1  31.6    for authors in book.authors: 
    127  20284  564884  27.8  0.4     print authors.name 
    128           
    129  33896  44392639 1309.7  29.0    for isbn in book.isbns: 
    130  15164  421289  27.8  0.3     print isbn.raw 
    131           
    132  18732  133320  7.1  0.1    books.add(book) 
    133           
    134  16   926  57.9  0.0   return list(books) 

有沒有一種方式來加載一次預訂對象相關的所有內容嗎?我嘗試過使用session.refresh()對象,但它沒有給出任何結果。

回答

2

您發佈的代碼僅處理查詢結果 - 將聲明傳遞給函數。問題是默認情況下所有關係都是懶惰的,所以它們需要更多的SQL查詢才能工作,這可能會很慢。

解決方案是加載所有想要的關係。像這樣的東西將讓你有:

# import sqlalchemy as sa 
sentense = Sentense.query.options(sa.joinedload_all(
     "words.soundex.words.sentense.book.authors" 
    ), sa.joinedload_all(
     "words.soundex.words.sentense.book.isbns" 
    )).filter(<some filters here>).first() 

注意,這可能仍然是很慢的,我不知道你的數據庫和數據的細節,但它會導致一個大的查詢一次得到發送。

另請注意,您的代碼還存在其他問題。關係的「邊」似乎是隨機的,名稱的複數化並不一致,這使得難以遵循。在分析代碼中,您會在for循環中覆蓋傳入的參數,因此sentense.id != sentense.id將始終評估False。您還可以使用內部for循環中的word從外部for循環覆蓋word

相關問題