【问题标题】:sqlalchemy materialized relationshipssqlalchemy物化关系
【发布时间】:2014-01-31 10:21:32
【问题描述】:

我有一个类似于以下的数据模型:

Location 1-----*<> Vacation <>*------1 TravelAgency
                     <>
                     |*
                     |
                     |1
                  Airline

在sqlalchemy中以正常方式实现:

class Vacation(Base):
    __tablename__ = 'vacation'
    id = Column(Integer, primary_key=True)
    location_id = Column(Integer, ForeignKey('location.id')
    location = relationship("Location")
    travel_agency_id = Column(Integer, ForeignKey('travel_agency.id')
    travel_agency = relationship("TravelAgency")
    airline_id = Column(Integer, ForeignKey('airline.id')
    airline = relationship("Airline")

class Location(Base):
    __tablename__ = 'location'
    id = Column(Integer, primary_key=True)
    data = Column(Integer)

class TravelAgency(Base):
    __tablename__ = 'travel_agency'
    id = Column(Integer, primary_key=True)
    data = Column(Integer)

class Airline(Base):
    __tablename__ = 'airline'
    id = Column(Integer, primary_key=True)
    data = Column(Integer)

由于需要多个连接,在包含数亿个对象的数据库中分析假期太慢了。在用尽了使用数据库配置选项加速连接操作的选项之后,我现在尝试使用数据库触发器来维护与其聚合连接的假期的物化视图。

SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'vacation_materialized';

 column_name  
--------------
id
location_id
location$data
travel_agency_id
travel_agency$data
airline_id
airline$data

现在我正在权衡如何从这个视图重建假期、旅行社和航空公司对象。一种选择是使用 sqlalchemy 核心查询 Vacation_materialized 表,然后解析行并“手动”构造对象。是否有任何我应该研究的 ORM 功能可能会产生更“优雅”的解决方案?

【问题讨论】:

    标签: sql sqlalchemy materialized-views


    【解决方案1】:

    您应该能够针对物化视图映射一个类,然后提供只读关系属性:

    materialized_vacations = Table('materialized_vacations', metadata, autoload=True)
    locations = Table('locations', metadata, autoload=True)
    
    mvac_2_location = materialized_vacations.c.location_id==locations.c.location_id
    
    class Location(Base):
        __table__ = locations
    
    class MaterializedVacation(Base):
        __table__ = materialized_vacations
        location = relationship("Location", primaryjoin=mvac_2_location, viewonly=True)
        ...
    

    我在这里假设您想要将任何外键放入您的物化视图中。相反,我使用 relationship()primaryjoin 关键字参数显式指定连接条件。

    这里mvac_2_location 创建一个sqlalchemy.sql.expression.BinaryExpression;我喜欢在使用之前单独声明它们,因为它们往往会占据一行的大部分内容,并且如果在使用它们的地方声明它们,它们会使参数序列不可读。它还使它们可重用并可导入到子模块中,这很方便。

    要构造mvac_2_location,我需要实际的表对象,并且在完成类MaterializedVacation 的声明之前需要它们,所以我将它们声明为老式的预声明方式,然后将类绑定到使用声明性参数__table__ 代替更常见的__tablename__ 的表。可能有更好的方法来做到这一点,但我不确定。

    【讨论】:

    • 感谢您的反馈,但我不认为这符合我的目标。我已将我的联接“缓存”在辅助表中。我希望能够查询到该辅助表的备用映射,这将通过最小化连接来提高性能。您的解决方案似乎仍然需要加入主表。我相信解决方案涉及 CompositeProperty 而不是 RelationshipProperty。我对该解决方案的尝试描述为in this question。这是一件明智的事情吗?
    猜你喜欢
    • 2014-05-28
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 2015-04-08
    • 2013-05-22
    相关资源
    最近更新 更多