2014-01-30 5 views
2

У меня есть модель данных, которая аналогична следующее:SQLAlchemy материализованные отношения

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 

Теперь я взвешиваю варианты того, как реконструировать каникулы, travel_agency и объекты авиакомпаний с этого вида. Один из вариантов - использовать ядро ​​sqlalchemy для запроса таблицы vacation_materialized, затем проанализировать строки и построить объекты «вручную». Есть ли какие-либо функции ORM, которые я должен изучать, что может привести к более «изящному» решению?

ответ

1

Вы должны быть в состоянии сделать карту класса против материализованного представления, а затем обеспечить только для чтения Relationship свойства:

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().

Здесь mvac_2_location создает sqlalchemy.sql.expression.BinaryExpression; Мне нравится объявлять их отдельно перед использованием, потому что они, как правило, занимают большую часть строки самостоятельно и делают последовательности аргументов нечитаемыми, если они объявлены там, где они используются. Это также делает их многоразовыми и импортируемыми в подмодули, что может быть удобно.

Чтобы построить mvac_2_location, мне нужны фактические объекты таблицы, и они мне нужны до завершения объявления класса MaterializedVacation, поэтому я объявляю их старомодным пред-декларативным способом, а затем привязывая классы к таблицам, используя декларативный аргумент __table__ вместо более распространенных __tablename__. Возможно, есть лучший способ сделать это, но я не уверен.

+0

Благодарим вас за отзыв, но я не думаю, что это зависит от того, что я собираюсь сделать. У меня «кэшировано» мое соединение во вторичной таблице. Я хотел бы иметь возможность запрашивать альтернативное сопоставление с этой вторичной таблицей, которая улучшала бы производительность за счет минимизации объединений. Вам, похоже, по-прежнему требуется соединение с основными таблицами. Я считаю, что решение включает CompositeProperty, а не RelationshipProperty. Моя попытка этого решения описана [в этом вопросе] (http://stackoverflow.com/questions/22342525/sqlalchemy-compositeproperty-for-a-mapped-type). Это разумная вещь, которую нужно делать? – natb1

Смежные вопросы