优化特定类型的数据库查询

时间:2017-05-21 17:55:55

标签: sql postgresql sqlalchemy

我有两个对象之间的多对多关系:报价和书籍。引用可以属于多本书,但通常只有一两本。另一方面,一本书通常有多个引用归于它。我有一个针对引号的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)

1 个答案:

答案 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)