Python 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

我试图定义与SqlAlchemy的一对多关系,在这种关系中,我的父母有很多孩子

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”得到的查询


      一般来说,这很难回答。但是,您可以在查询时选择最适合运行查询的上下文的选项。当性能重要时,我发现最好使用手动构造的sql和逻辑测试查询和函数性能,然后反向工作并编写相应的sqlalchemy表达式这通常很难回答。但是,您可以在查询时选择最适合运行查询的上下文的选项。当性能重要时,我发现最好使用手动构造的sql&logic测试查询和函数性能,然后反向工作并编写相应的sqlalchemy表达式sion.两种情况下,您查询10000+行的子表我想从父表筛选,因为您只查询10到30条记录。两种情况下,您查询10000+行的子表我想从父表筛选,因为您只查询10到30条记录“动态筛选子表”是什么意思?@Overflow012澄清了我在回答中的意思;我的意思是喜欢你用lazy=“dynamic”得到什么?你说的“动态筛选子项”是什么意思?@Overflow012澄清了我在回答中的意思;我的意思是喜欢你用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)
      在功能上等同于