SQLAlchemy支持关系的急切加载,它基本上是JOIN
语句。但是,如果模型具有两个或更多关系,则它可能是一个非常大的连接。例如,
class Product(Base):
__tablename__ = 'product'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(255), nullable=False)
orders = relationship('Order', backref='product', cascade='all')
tags = relationship('Tag', secondary=product_tag_map)
class Order(Base):
__tablename__ = 'order'
id = Column(Integer, primary_key=True, autoincrement=True)
date = Column(TIMESTAMP, default=datetime.now())
class Tag(Base):
__tablename__ = 'tag'
id = Column(Integer, primary_key=True, autoincrement=True)
tag_type = Column(String(255), nullable=False)
tag_value = Column(String(255), nullable=False)
q = session.query(Product).join(User.addresses)\
.options(joinedload(Product.orders))\
.options(joinedload(Product.tags)).all()
此查询的效果非常糟糕,因为JOIN
和Order
的{{1}}会生成一个巨大的表格。但是Tag
和Order
在这里没有任何关系,所以它们不应该是Tag
。它应该是两个独立的查询。并且因为会话具有一定程度的缓存,所以我将查询更改为此。
JOIN
这次表现要好得多。但是,我不相信这是正确的。我不确定会话结束时标签的缓存是否会过期。
请告诉我这种查询的适当方式。谢谢!
答案 0 :(得分:11)
对于一对多或多对多的关系,出于性能原因,它(通常)会更好地使用subqueryload
:
session.query(Product).join(User.addresses)\
.options(subqueryload(Product.orders),\
subqueryload(Product.tags)).all()
这会针对SELECT
和orders
中的每一个发出tags
个查询。