|
SQLAlchemy支持渴望加载关系,这基本上是一条JOIN语句。但是,如果模型具有两个或多个关系,则可能是非常庞大的联接。例如,1 z+ C- N0 J9 [
class Product(Base):
8 U' y5 N# O: r6 k6 I& S' k% o k: R __tablename__ = 'product'5 X. k- a3 C/ @
id = Column(Integer, primary_key=True, autoincrement=True)
2 ~) o. M# x, f name = Column(String(255), nullable=False)# p# Y0 V2 W1 s1 x
orders = relationship('Order', backref='product', cascade='all')' Z0 {$ z0 Y! H) y& Z
tags = relationship('Tag', secondary=product_tag_map). f/ }4 U- Q' a) e
class Order(Base):! [- e! Z e/ a/ x( E P4 r; j, ~
__tablename__ = 'order'
7 j! y( u# |3 G0 e: x4 @* o id = Column(Integer, primary_key=True, autoincrement=True)+ F2 c# T8 p9 y
date = Column(TIMESTAMP, default=datetime.now())
8 J1 {2 @+ w9 J3 s) N) zclass Tag(Base):
9 a$ v6 Z' t% D7 u9 Z" i* | __tablename__ = 'tag'/ a0 v7 s& u* t. T: y2 c1 f& ^
id = Column(Integer, primary_key=True, autoincrement=True)
: k# W `) n2 E0 @. n0 i tag_type = Column(String(255), nullable=False)- g6 V3 ?# A8 `% z! l& [3 x
tag_value = Column(String(255), nullable=False)
: J+ ~5 p$ ^* p0 g3 ]q = session.query(Product).join(User.addresses)\
% Y- \* |- n# J& G4 |; P6 q .options(joinedload(Product.orders))\0 Q( n7 |3 a' Z) `8 H
.options(joinedload(Product.tags)).all()# I- }- P) P- |/ g% P1 W
该查询的性能实在是太差了,因为JOIN中Order和Tag会产生一个巨大的表。但是Order和Tag在这里没有关系,因此它们不应该是JOIN。它应该是两个分开的查询。并且由于会话具有某种程度的缓存,因此我将查询更改为此。
7 E, J7 C# L$ A, u1 s0 b; ?session.query(Product).join(Product.order) \2 E# U4 |" y, z! o+ X, U/ z% H
.options(joinedload(Product.tags)).all()
: p) j$ w# u/ \8 q1 I- zq = session.query(Product).join(User.addresses) \
: l; k% F: q( F f& Q* ~ .options(joinedload(Product.cases)).all()8 H4 B/ e: Y. z: Q
这次的性能要好得多。但是,我不认为这样做是正确的。我不确定会话结束时标签缓存是否会过期。7 N* W. f, I3 n# ~8 X* i; H, B
请让我知道这种查询的适当方式。谢谢!
7 A) o/ ]' L2 o% \3 j4 v7 d5 a
1 E& w" [2 n7 q$ c! L3 n; `! m解决方案:' ]$ [; M4 C1 x( o; q1 _
9 {' g: {* E6 Y/ U8 u! E8 i( ~
8 H1 l9 o2 N# I# o7 p# m3 }( J( N' k3 d9 e% n
对于一对多或多对多关系subqueryload,出于性能原因,最好使用(通常)代替:, q/ `2 M+ b1 x6 \4 X& z* t
session.query(Product).join(User.addresses)\
3 W! b( W9 z5 Y0 n .options(subqueryload(Product.orders),\( L# o" u( V4 c' Q
subqueryload(Product.tags)).all(): j* i9 M# f2 E# e
这个问题会SELECT针对orders和分别发出查询tags。 |
|