Метод yield_per
Метод yield_per класса Query выполняет
SQL-запрос и возвращает итератор, который
загружает объекты порциями указанного размера.
Метод принимает один параметр count - количество
строк, извлекаемых из базы данных за один раз.
Это позволяет существенно снизить потребление
памяти при обработке больших наборов данных.
Метод особенно полезен в сочетании с
итерацией по результатам запроса, когда
нет необходимости загружать все объекты
в память одновременно. Следует учитывать,
что при использовании yield_per коллекции
связей, загружаемые через joined eager loading,
могут работать некорректно.
Синтаксис
Query.yield_per(count)
Параметр count задает размер порции
загружаемых строк. Если передать значение
0 или отрицательное число, все строки
будут загружены сразу.
Пример
Давайте создадим модель Article и
продемонстрируем порционную загрузку
объектов через yield_per:
from sqlalchemy import create_engine, String, Integer
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(100))
text: Mapped[str] = mapped_column(String(500))
status: Mapped[str] = mapped_column(String(50))
num: Mapped[int] = mapped_column(Integer)
Теперь создадим несколько записей и
выполним запрос с методом yield_per:
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from models import Base, Article
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
for i in range(1, 6):
session.add(Article(
title=f'article {i}',
text=f'text {i}',
status='published',
num=i
))
session.commit()
with Session(engine) as session:
query = session.query(Article).yield_per(2)
for article in query:
print(article.title)
Результат выполнения кода:
"article 1"
"article 2"
"article 3"
"article 4"
"article 5"
Пример
Давайте сравним поведение обычного запроса
и запроса с yield_per, выведя
количество объектов, загруженных за раз:
Результат выполнения кода:
"Batch loaded: ['article 1', 'article 2', 'article 3']"
"Batch loaded: ['article 4', 'article 5', 'article 6']"
"Batch loaded: ['article 7']"
Пример
Давайте применим yield_per вместе
с фильтрацией и сортировкой для обработки
отфильтрованного набора данных:
Результат выполнения кода:
"article 2 - published"
"article 4 - published"