SQLAlchemy渴望加载多个关系
SQLAlchemy支持渴望加载关系,它基本上是一个JOIN
语句.但是,如果模型具有两个或多个关系,则可能是非常庞大的联接.例如,
SQLAlchemy supports eager load for relationship, it is basically a JOIN
statement. However, if a model has two or more relationships, it could be a very huge join. For example,
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()
此查询的性能确实很差,因为Order
和Tag
的JOIN
会生成一个巨大的表.但是Order
和Tag
在这里没有关系,因此它们不应为JOIN
.它应该是两个分开的查询.而且由于会话具有某种程度的缓存,所以我将查询更改为此.
The performance of this query is really bad, because the JOIN
of Order
and Tag
will generate a huge table. But the Order
and Tag
has no relationship in here, so they should not be JOIN
. It should be two separated queries. And because the session has some level of caching, so I changed my query to this.
session.query(Product).join(Product.order) \
.options(joinedload(Product.tags)).all()
q = session.query(Product).join(User.addresses) \
.options(joinedload(Product.cases)).all()
这次性能要好得多.但是,我不认为这样做是正确的.我不确定会话结束时标签缓存是否会过期.
This time the performance is way much better. However, I am not convinced that this is the correct to do it. I am not sure if the caches of tags will be expired when the session ends.
请让我知道此类查询的适当方式.谢谢!
Please let me know the appropriate way for this kind of query. Thank you!
For a one-to-many or many-to-many relationship, it's (usually) better to use subqueryload
instead, for performance reasons:
session.query(Product).join(User.addresses)\
.options(subqueryload(Product.orders),\
subqueryload(Product.tags)).all()
此问题分别对orders
和tags
发出SELECT
查询.
This issues separate SELECT
queries for each of orders
and tags
.