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)

有没有办法一次加载与书籍对象相关的所有内容?我试过使用 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()

请注意,这可能仍然很慢,我不知道您的数据库和数据的详细信息,但它会导致一次发送一个大型查询。

另请注意,您的代码还有其他问题。关系的“边”似乎是随机的,名字的复数并不一致,让人难以理解。在分析代码中,您在 for 循环期间覆盖传入的语句,因此sentense.id != sentense.id将始终评估False. 您还可以用内部 for 循环中的 a 覆盖word外部 forword循环。

于 2013-06-30T03:55:47.400 回答