РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
528 of 711 menu

Значение lazy subquery

Значение lazy='subquery' передается в параметр lazy функции relationship и включает стратегию жадной загрузки через подзапрос. При первом обращении к связанной коллекции SQLAlchemy выполняет один дополнительный SELECT, который выбирает связанные объекты для всех родительских строк сразу. Это уменьшает число запросов по сравнению с lazy='select', но подзапрос загружает весь набор данных без учета фильтров и лимитов родительского запроса.

Синтаксис

relationship(SomeModel, lazy='subquery')

Пример

Давайте создадим две связанные модели и установим для связи значение lazy='subquery':

from sqlalchemy import create_engine, ForeignKey from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session class Base(DeclarativeBase): pass class User(Base): __tablename__ = 'users' id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] articles: Mapped[list['Article']] = relationship( back_populates='user', lazy='subquery' ) class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] user_id: Mapped[int] = mapped_column(ForeignKey('users.id')) user: Mapped['User'] = relationship(back_populates='articles') engine = create_engine('sqlite:///:memory:', echo=True) Base.metadata.create_all(engine) with Session(engine) as session: user = User(name='user') user.articles = [Article(title='article 1'), Article(title='article 2')] session.add(user) session.commit() users = session.query(User).all() for u in users: print([a.title for a in u.articles])

В логе видно, что после основного SELECT по таблице users сразу выполняется подзапрос по таблице articles для всех найденных пользователей:

SELECT users.id AS users_id, users.name AS users_name FROM users SELECT articles.user_id AS articles_user_id, articles.id AS articles_id, articles.title AS articles_title FROM articles WHERE articles.user_id IN (SELECT users.id FROM users)

Результат выполнения кода:

['article 1', 'article 2']

Пример

Значение lazy='subquery' можно переопределить на уровне отдельного запроса с помощью опции lazyload. Давайте загрузим связь лениво, несмотря на настройку в модели:

from sqlalchemy import create_engine, ForeignKey from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session from sqlalchemy.orm import lazyload class Base(DeclarativeBase): pass class User(Base): __tablename__ = 'users' id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] articles: Mapped[list['Article']] = relationship( back_populates='user', lazy='subquery' ) class Article(Base): __tablename__ = 'articles' id: Mapped[int] = mapped_column(primary_key=True) title: Mapped[str] user_id: Mapped[int] = mapped_column(ForeignKey('users.id')) user: Mapped['User'] = relationship(back_populates='articles') engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: user = User(name='user') user.articles = [Article(title='article 1')] session.add(user) session.commit() users = session.query(User).options(lazyload(User.articles)).all() for u in users: print([a.title for a in u.articles])

Результат выполнения кода:

['article 1']

Смотрите также

  • функцию relationship,
    которая настраивает связь между моделями
  • значение lazy select,
    которое включает ленивую загрузку связей
  • значение lazy selectin,
    которое включает загрузку отдельным IN-запросом
  • значение lazy joined,
    которое включает жадную загрузку через JOIN
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить