我有两个对象之间的多对多关系:报价和书籍。引用可以属于多本书,但通常只有一两本。另一方面,一本书通常有多个引用归于它。我有一个针对引号的SQL查询,我想将所有具有至少一个引号的书籍变成单个查询:
我已完成以下操作,将查询从报价更改为所有图书的相应查询:
def get_books(session, quotes):
quote_id_query = quotes.from_self(Quote.quote_id)
book_query = (session.query(Book)
.join(Book.quotes)
.filter(Book.book_id.in_(quote_id_query))
.distinct())
return book_query
这样可行但是对于某些引号查询来说这是慢的方法。如果引号为空,则相应的书籍查询很快,但如果相应的报价查询非空,那么它可能需要超过10秒(约为报价查询所需的1000倍,甚至比N + 1查询慢)。我正在使用Postgres的最新版本。我的辅助表上有索引,我尝试解析问题已经达到了十几个级别的计划。任何人都可以帮助我减少这些查询到理智的时间吗?
编辑:以下是当前的模型定义:
class Quote(BaseModel):
quote_id = Column(Integer, primary_key=True, nullable=False)
full_text = Column(String, nullable=False, unique=True)
uses = Column(Integer, nullable=False)
popularity = Column(Integer, nullable=False)
books = relationship('Book', secondary='quotebook', back_populates='quotes')
class Book(BaseModel):
book_id = Column(Integer, primary_key=True, nullable=False)
author = Column(String, nullable=False, index=True)
title = Column(String, nullable=False, index=True)
genre = Column(String, nullable=False, index=True)
cost = Column(Integer, nullable=False)
quotes = relationship('Quote', secondary='quotebook', back_populates='books', lazy='joined')
class QuoteBook(BaseModel):
__tablename__ = 'quotebook'
id = Column(Integer, primary_key=True)
book_id = Column(Integer, ForeignKey('book.book_id'), index=True)
quote_id = Column(Integer, ForeignKey('quote.quote_id'), index=True)
答案 0 :(得分:0)
您应该记录,查看和发布为审查而生成的SQL语句(将sqlalchemy.engine记录器设置为INFO),但您的连接(Book.quotes)应该已经执行了内部连接条件,因此您的过滤器(Book.book_id.in_) (quote_id_query))是无关的,应该删除。
根据表的大小和定义,如果连接很昂贵,您还可以考虑使用过滤器测试exists子句的性能(Book.quotes。http://docs.sqlalchemy.org/en/latest/orm/internals.html?highlight=has#sqlalchemy.orm.properties.RelationshipProperty.Comparator.has(quoteid> 0)