0

これは私のデータベースの単純化されたプロジェクトです。

ここに画像の説明を入力

私のモデルは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))

問題は、オブジェクトのロード時間にあります。優れたプロファイラーを使用すると、次のようになりました。

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)

book オブジェクトに関連するすべてのコンテンツを一度にロードする方法はありますか? session.refresh() オブジェクトを使用しようとしましたが、結果が得られません。

4

1 に答える 1

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()

これでもかなり遅い可能性があることに注意してください。データベースとデータの詳細はわかりませんが、1 つの大きなクエリが一度に送信されることになります。

また、コードには他にも問題があることに注意してください。関係の「側面」はランダムに見え、名前の複数形は一貫していないため、追跡が困難です。プロファイルされたコードでは、 for ループ中に渡されたセンテンスを上書きするため、sentense.id != sentense.idは常に評価されFalseます。wordまた、外側の for ループの を内側の for ループの で上書きwordします。

于 2013-06-30T03:55:47.400 に答える