Новое:Talanto осенью: фильтры с числами, отклик по шагам и каталог компаний

+1 183новые вакансии за сутки·93 833вакансии открыты сейчас·Новое:Talanto осенью: фильтры с числами, отклик по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 273
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: фильтры с числами, отклик по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 409 кандидатов открыты к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 230
  • Облачные технологии14 171
  • QA вакансии3 456
  • Backend вакансии2 115
  • Инженер данных1 801
  • Продакт-менеджер1 247

Разработка

  • Android1 858
  • iOS1 698
  • Fullstack вакансии996
  • AI вакансии955
  • Frontend вакансии755
  • Mobile вакансии44

По стеку

  • Go8 752
  • Java6 593
  • Node.js2 036
  • .NET1 739
  • Kotlin1 618
  • Rust1 472
  • C#717
  • PHP690
  • C++579

DevOps и инфраструктура

  • Kubernetes7 787
  • DevOps вакансии6 095
  • Linux-инфраструктура5 508
  • Terraform / IaC4 287
  • CI/CD3 272
  • Мониторинг и Observability1 792
  • SRE566
  • Кибербезопасность454

Аналитика и данные

  • Data Scientist1 138
  • Бизнес-аналитик921
  • Аналитик данных858
  • Системный аналитик154

Другие направления

  • Проджект-менеджер624
  • UI/UX дизайн149
  • Ручное тестирование14

По регионам

  • Вакансии в США44 166
  • Вакансии в Европе24 014
  • Вакансии в Канаде4 535
  • Работа в России3 867

По формату

  • Удалённые вакансии75 005
  • Релокация в США44 166
  • Гибридная работа12 485
  • Офисная работа7 090

По уровню

  • Senior вакансии42 643
  • Middle вакансии20 960
  • Junior вакансии6 708

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis38 вакансий
  • Spotify37 вакансий
  • Adyen29 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace17 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К подготовке по вакансии←К теме SQLAlchemyВсе вопросы
SQLAlchemySeniorКодинг

Как решить проблему N+1 запросов в SQLAlchemy с помощью selectinload или joinedload?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

selectinload делает отдельный SELECT IN для коллекций, joinedload добавляет JOIN для one-to-one/many-to-one. При async-сессии ленивая загрузка невозможна — всегда задавайте eager-опции явно.

Пример

from sqlalchemy import select
from sqlalchemy.orm import selectinload, joinedload
from sqlalchemy.ext.asyncio import AsyncSession

# selectinload: загружаем список заказов + их позиции
async def get_orders_with_items(session: AsyncSession):
    stmt = (
        select(Order)
        .options(selectinload(Order.items))   # отдельный SELECT IN
        .where(Order.status == "active")
    )
    result = await session.execute(stmt)
    return result.scalars().all()

# joinedload: загружаем заказы + автора (many-to-one)
async def get_orders_with_user(session: AsyncSession):
    stmt = (
        select(Order)
        .options(joinedload(Order.user))      # JOIN
        .where(Order.status == "active")
    )
    result = await session.execute(stmt)
    # scalars().unique() — важно при join, чтобы убрать дубли строк
    return result.scalars().unique().all()

# Вложенная загрузка: orders -> items -> product
async def get_deep(session: AsyncSession):
    stmt = (
        select(Order)
        .options(
            selectinload(Order.items)
            .joinedload(OrderItem.product)
        )
    )
    result = await session.execute(stmt)
    return result.scalars().all()

Проблема N+1 в SQLAlchemy

Проблема N+1 возникает, когда ORM сначала загружает список объектов (1 запрос), а затем для каждого объекта отдельно обращается к связанным данным (N запросов). При 1000 заказов это 1001 запрос вместо одного-двух.

Стратегии загрузки

SQLAlchemy 2.x предлагает несколько стратегий через функции-опции selectinload, joinedload, subqueryload и lazyload.

  • selectinload — выполняет отдельный SELECT … WHERE id IN (…) для коллекции. Не раздувает строки, безопасен для коллекций и many-to-many.
  • joinedload — добавляет LEFT OUTER JOIN к основному запросу. Хорош для загрузки единственного связанного объекта (many-to-one / one-to-one), но раздувает результат при коллекциях.
  • subqueryload — использует подзапрос; устарел, предпочитайте selectinload.
  • lazyload — поведение по умолчанию, отправляет запрос при первом обращении к атрибуту (источник N+1).

Диагностика N+1

Включите SQL-логирование и посчитайте запросы:

import logging
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)

Или используйте sqlalchemy-utils / pytest-sqlalchemy-mock и считайте вызовы через event.listen на before_cursor_execute.

Когда что выбирать

  • Коллекция (one-to-many, many-to-many) → selectinload.
  • Единственный связанный объект (many-to-one) → joinedload.
  • Большой граф с несколькими уровнями → selectinload на каждом уровне отдельно, чтобы не перемножать строки.
  • Нужен только один столбец связанного объекта → contains_eager после явного join() или просто select() с нужными столбцами.

Подводные камни

  • joinedload на коллекциях дублирует строки родителя — без .unique() получите повторы объектов в списке.
  • lazy="raise" в production — полезная защита, но сломает код, если забыть добавить опцию загрузки хоть для одного маршрута.
  • selectinload с очень большим IN-списком (10 000+ id) может замедлить PostgreSQL из-за переполнения плана; разбивайте батчами или переходите на subqueryload.
  • AsyncSession + lazyload бросает MissingGreenlet — в async-коде ленивая загрузка физически невозможна без AsyncAttrs или явного eager-options.
  • contains_eager без явного join не работает — ORM не знает, что данные уже есть в строке результата.
  • Вложенный selectinload × joinedload: порядок имеет значение — joinedload внутри selectinload работает, обратное может дать неожиданный SQL.
  • expire_on_commit=True (по умолчанию): после коммита все атрибуты помечаются устаревшими, и следующее обращение снова вызовет SELECT — даже если вы уже загрузили данные через eager.
  • Профилирование только в dev: убедитесь, что echo=True отключён в prod, иначе логирование каждого SQL-запроса само станет узким местом.

Типичные ошибки

  • Описывать n plus one loading только как термин и не показывать механизм на минимальном примере.
  • Игнорировать ошибки, пустые данные, конкурентный доступ или границы транзакции.
  • Не связывать поведение с официальным контрактом SQLAlchemy и реальной эксплуатацией.

Что проверяет интервьюер

  • Объясняет n plus one loading через последовательность действий, а не через набор ключевых слов.
  • Приводит короткий кодовый пример или production-сценарий с ожидаемым поведением.
  • Называет хотя бы один риск: производительность, безопасность, транзакции, память или сопровождение.
  • Умеет обсудить отказ, наблюдаемость и rollback без изменения публичного контракта.

Как вы знаете этот вопрос?

Проверить себя по теме SQLAlchemy →

Источники

  • https://docs.sqlalchemy.org/en/20/orm/queryguide/relationships.html
  • https://docs.sqlalchemy.org/en/20/orm/basic_relationships.html
Следующий вопрос→Как работает `Session` в SQLAlchemy и что такое паттерн Unit of Work?

Связанные темы

SQLAlchemydatabase-designimplementationtechnical-reasoning

Вакансии с этим навыком

  • Python developer

Частые вопросы на собеседовании

  • Как работает Session в SQLAlchemy и что такое паттерн Unit of Work?
  • Как делать zero-downtime миграции с Alembic и SQLAlchemy models?
  • Что такое Engine в SQLAlchemy и как работает пул соединений?
  • В чём разница между стратегиями загрузки lazy='select', lazy='joined' и lazy='selectin'?