Python SQLAlchemy中的性能一对多关系
我试图定义与SqlAlchemy的一对多关系,在这种关系中,我的父母有很多孩子Python SQLAlchemy中的性能一对多关系,python,sqlalchemy,Python,Sqlalchemy,我试图定义与SqlAlchemy的一对多关系,在这种关系中,我的父母有很多孩子 class Parent(Base): __tablename__ = "parent" id = Column(String, primary_key = True) children = relationship("Child") class Child(Base): __tablename__ = "child" id = Column(Integer, prim
class Parent(Base):
__tablename__ = "parent"
id = Column(String, primary_key = True)
children = relationship("Child")
class Child(Base):
__tablename__ = "child"
id = Column(Integer, primary_key = True)
feed_type_id = Column(String, ForeignKey("parent.id"))
根据业务规则,父级没有太多子级(10到30之间),大多数时候我都需要访问所有子级,因此我认为relationship()检索内存中的所有子级以提高性能是个好主意(第一个问题:我说得对吗?)但有几次我需要一个特定的孩子,但我不会做类似的事情:
def search_bar_attr(some_value)
for bar in foo.bars:
if(bar.attr == some_value)
return bar
lazy=“dynamic”返回一个允许查询的列表,但我认为相对于“急切地”加载,它的速度很慢,因为动态关系总是查询数据库
第二个问题:是否有满足我所有需求的配置 您不需要使用这样的函数,甚至不需要加载内存中的所有子对象。
如果要搜索具有特定属性的子级,可以执行以下操作:
# get a session object, usually with sessionmaker() configured to bind to your engine instance
c = session.query(Child).filter_by(some_attribute="some value here").all() # returns a list of all child objects that match the filter
# or: to get a child who belongs to a certain parrent with a certain attribute:
# get the parent object (p)
c = session.query(Child).filter_by(feed_type_id=p.id).filter_by(some_attr="some attribute that belongs to children of the p parrent object")
您不需要使用这样的函数,甚至不需要加载内存中的所有子对象。
如果要搜索具有特定属性的子级,可以执行以下操作:
# get a session object, usually with sessionmaker() configured to bind to your engine instance
c = session.query(Child).filter_by(some_attribute="some value here").all() # returns a list of all child objects that match the filter
# or: to get a child who belongs to a certain parrent with a certain attribute:
# get the parent object (p)
c = session.query(Child).filter_by(feed_type_id=p.id).filter_by(some_attr="some attribute that belongs to children of the p parrent object")
通过使用,您可以构造与
lazy=“dynamic”
相同的查询
如果您需要编写大量以下内容,您甚至可以添加一个函数来简化样板文件:
def dynamicize(rel):
@property
def _getter(self):
return object_session(self).query(rel.parent).with_parent(self, rel)
return _getter
class Parent(Base):
...
children = relationship("Child")
children_dynamic = dynamicize(children)
通过使用,您可以构造与
lazy=“dynamic”
相同的查询
如果您需要编写大量以下内容,您甚至可以添加一个函数来简化样板文件:
def dynamicize(rel):
@property
def _getter(self):
return object_session(self).query(rel.parent).with_parent(self, rel)
return _getter
class Parent(Base):
...
children = relationship("Child")
children_dynamic = dynamicize(children)
没有一种策略能给你一切。但是,您可以选择默认策略,然后覆盖它。 我的建议是:
- 将lazy=“joined”添加到您的关系中,这样默认情况下,您将获得所有家长
- 如果要查询一组依赖于其父对象属性但不需要父对象的子对象,请在查询和筛选器上使用连接函数,同时引用父对象和子对象
- 如果您需要构造一个类似于lazy=“dynamic”的查询,请使用sqlalchemy.orm.defer操作符关闭lazy=“joined”急切加载和(覆盖急切加载,然后与\u parent一起构造查询。类似于使用lazy=“dynamic”得到的查询
- 将lazy=“joined”添加到您的关系中,这样默认情况下,您将获得所有家长
- 如果要查询一组依赖于其父对象属性但不需要父对象的子对象,请在查询和筛选器上使用连接函数,同时引用父对象和子对象
- 如果您需要构造一个类似于lazy=“dynamic”的查询,请使用sqlalchemy.orm.defer操作符关闭lazy=“joined”急切加载和(覆盖急切加载,然后与\u parent一起构造查询。类似于使用lazy=“dynamic”得到的查询
- 没有一种策略可以为您提供一切。但是,您可以选择一种默认策略,然后覆盖它。
我的建议是:
属性
参数,因此我认为可以将其缩短为对象会话(self).query(Child)。使用\u parent(self)
时,我在理解这一点上遇到了一些困难:are关系(“Child”)
和对象会话(self).query(Child)。使用\u parent(self,parent.children)。all()
和object\u session(self).query(Child).filter(parent=self).all()
(假设我们在关系中有backref='parent'
)等价物?@SunQingyao如果您有一个名为parent
的子对象的backref,那么filter(Child.parent==self)
在功能上等同于。\u parent(self,parent.children)
,但我认为SQL的呈现方式有一些细微的区别。前者也不太通用,因为它假设一对多的关系。根据,可以省略属性
参数,因此我认为可以将其缩短为对象会话(self).查询(Child).与父对象(self)
此外,我在理解这一点上遇到了一些困难:are关系(“子”)
和对象会话(self).query(Child).与父对象会话(self,parent.children).all()
和对象会话(self).query(Child).filter(parent=self).all()
(假设我们在关系中有backref='parent'
)等价物?@SunQingyao如果您有一个名为parent
的子对象的backref,那么.filter(Child.parent==self)
在功能上等同于