首页 文章

SQLAlchemy中的性能一对多关系

提问于
浏览
1

我正在尝试与SqlAlchemy定义一对多的关系,其中Parent有很多Child

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"))

根据业务规则,Parent没有多少Child(10到30之间),而且大部分时间我都需要访问所有这些,所以我认为关系()检索内存中的所有子项以提高性能是个好主意( First question: 我是对的?)但很少有时候我需要得到一个特定的孩子,但我不会做类似的事情:

def search_bar_attr(some_value)
    for bar in foo.bars:
        if(bar.attr == some_value)
            return bar

lazy =“dynamic”返回一个允许查询的列表,但我认为它对“急切”加载很慢,因为动态关系总是查询数据库 .

Second question :是否有一些配置可以满足我的所有需求?

3 回答

  • 0

    您可以使用.with_parent构造 lazy="dynamic" 所执行的相同查询 .

    class Parent(Base):
        ...
        @property
        def children_dynamic(self):
            return object_session(self).query(Child).with_parent(self, Parent.children)
    

    如果你必须编写很多这些函数,你甚至可以添加一个函数来减少样板:

    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)
    
  • 3

    你甚至不需要在内存中加载所有子对象 .
    如果要搜索具有特定属性的子项,可以执行以下操作:

    # 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")
    
  • 1

    没有一个策略会给你一切 . 但是,您可以选择默认策略,然后覆盖它 . 我的建议是:

    • 将lazy =“加入”添加到您的关系中,这样默认情况下,您将获得所有父母 .

    • 如果要查询依赖于其父项属性但不需要父对象的一组子项,请在查询上使用join函数并过滤引用父项和子项的过滤器

    • 如果您需要构造类似于lazy = "dynamic"的查询,请使用sqlalchemy.orm.defer运算符关闭lazy = "joined" eager loading和loading interface(以覆盖预先加载,然后使用with_parent构造查询 . 像你一样得到的查询lazy = "dynamic"

相关问题