Sqlalchemy急切加载父连接表继承中的所有属性

时间:2014-07-23 11:19:01

标签: sqlalchemy

我有以下问题:

我有一个连接表继承的类的层次结构:

class AdGroupModel(Base, AdwordsRequestMixin):
    __tablename__ = 'ad_groups'

    db_id = Column(BigInteger, primary_key=True)
    created_at = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now())

    # ----RELATIONS-----
    # campaign MANY-to-ONE
    campaign_db_id = Column(BigInteger,
                            ForeignKey('campaigns.db_id', ondelete='CASCADE'),
                            nullable = True,
                            )
    # # ads ONE-to-MANY
    ads = relationship("AdModel",
                       backref="ad_group",
                       lazy="subquery",
                       passive_deletes=True,
                       single_parent=True,
                       cascade="all, delete, delete-orphan")
    # # # keywords ONE-to-MANY
    criteria = relationship("AdGroupCriterionModel",
                            backref="ad_group",
                            lazy="subquery",
                            passive_deletes=True,
                            single_parent=True,
                            cascade="all, delete, delete-orphan")


    # Joined Table Inheritance
    type = Column(Unicode(50))
    __mapper_args__ = {
        'polymorphic_identity': 'ad_group',
        'polymorphic_on': type
    }





class AdGroupCriterionModel(Base, AdGroupDependenceMixin):
    __tablename__ = 'ad_group_criterion'

    db_id = Column(BigInteger, primary_key=True)

    destination_url = Column(Unicode, nullable=True)
    status = Column(Enum("PAUSED", "ACTIVE", "DELETED",
                         name='criterion_status'), default="ACTIVE")



    # ----RELATIONS---
    # ad_group ONE-to-MANY
    ad_group_db_id = Column(BigInteger, ForeignKey('ad_groups.db_id',
                                                   ondelete='CASCADE'), nullable=True)

    # Joined Table Inheritance
    criterion_sub_type = Column(Unicode(50))
    __mapper_args__ = {
        'polymorphic_on': criterion_sub_type
    }



class AdGroupKeywordModel(AdGroupCriterionModel):
    __tablename__ = 'ad_group_keyword'
    __mapper_args__ = {'polymorphic_identity': 'Keyword'}
    db_id = Column(Integer, ForeignKey('ad_group_criterion.db_id'), primary_key=True)

    text = Column(Unicode, nullable=False)


class AdGroupDependenceMixin(object):
    _aggad_id = Column(BigInteger, nullable=True)
    _agname = Column(Unicode, nullable=True)

    @hybrid_property
    def ad_group_GAD_id(self):
        if self.ad_group is None:
            res = self._aggad_id
        else:
            res = self.ad_group.GAD_id
        return res

    @ad_group_GAD_id.setter
    def ad_group_GAD_id(self, value):
        self._aggad_id = value
        if value is not None:
            self.ad_group = None

    @ad_group_GAD_id.expression
    def ad_group_GAD_id(cls):
        what = case([( cls._aggad_id != None,  cls._aggad_id)], else_=AdGroupModel.GAD_id)
        return what.label('adgroupgadid_expression')

    @hybrid_property
    def ad_group_name(self):
        if self.ad_group is None:
            return self._agname
        else:
            return self.ad_group.name

    @ad_group_name.setter
    def ad_group_name(self, value):
        self._agname = value
        if value is not None:
            self.campaign = None

    @ad_group_name.expression
    def ad_group_name(cls):
        what = case([( cls._agname != None,  cls._agname)], else_=AdGroupModel.name)
        return what.label('adgroupname_expression')




And I load the Keywords objects from the database with the following query:

    all_objects1 = self.database.session.query(AdGroupKeywordModel).join(AdGroupModel)\
        .options(subqueryload('ad_group'))\
        .filter(AdGroupModel.GAD_id!=None)\
        .limit(self.options.limit).all()

返回AdGroupKeywordModel类型的obejcts。

不幸的是,每当我尝试访问父表(AdGroupKeywordModel)中AdGroupCriterionModel的属性时,都会发出此类型的查询:

sqlalchemy.engine.base.Engine 
    SELECT ad_group_criterion.destination_url AS ad_group_criterion_destination_url, ad_group_criterion.status AS ad_group_criterion_status, ad_group_criterion.ad_group_db_id AS ad_group_criterion_ad_group_db_id, ad_group_criterion.criterion_sub_type AS ad_group_criterion_criterion_sub_type, ad_group_keyword.text AS ad_group_keyword_text
    FROM ad_group_criterion JOIN ad_group_keyword ON ad_group_criterion.db_id = ad_group_keyword.db_id 

这极大地影响了性能。

我想要的是,类AdGroupKeywordModel的所有属性都与父级(以及在关系中定义的其他类)相关,这些属性将与初始查询一起加载并被缓存以供进一步使用。因此,当我访问它们时,我不会从进一步的sqlstatements中获得任何开销。

似乎只为关系定义了急切加载,而不是为层次结构定义。是否有可能在sqlalchemy中对层次结构有这种行为?

由于

1 个答案:

答案 0 :(得分:1)

我看到的是:只有AdGroupModellazy=定义(定义关系的急切加载的关键字)有关系,而查询只有subqueryload('ad_group')

ad_groupAdGroupModelAdGroupKeywordModel联系的唯一一点是AdGroupModel.criteria,其中包含AdGroupCriterionModel.ad_group。我不熟悉subqueryload语法,但如果我想加载AdGroupCriterionModel.ad_group,我会像这样定义criteria

criteria = relationship(
    "AdGroupCriterionModel", backref=backref("ad_group", lazy="subquery"),
    lazy="subquery", passive_deletes=True, single_parent=True,
    cascade="all, delete, delete-orphan")

关键是为lazy定义正确的backref