Выбор ответа Senior SQLAlchemy 2.0 обновлено
Как не пропустить N+1 в SQLAlchemy
Вопрос
Как сделать так, чтобы случайная ленивая загрузка связи в новом коде сразу ломала тесты, а не тихо делала N+1 в проде?
Попробуйте сами
Выберите вариант, и откроется разбор.
Показать ответ и разбор
Коротко
Правильный ответ: Добавить raiseload("") или lazy="raise", чтобы ленивая загрузка падала. С raiseload любая попытка неявно подгрузить связь заканчивается ошибкой, и разработчик вынужден явно указать selectinload или joinedload.
Варианты ответа
- Включить
echo=Trueв проде и настроить алерт на рост числа SQL-запросов - Добавить
raiseload("*")илиlazy="raise", чтобы ленивая загрузка падалаправильный ответ - Увеличить пул соединений, чтобы N+1 не упирался в лимит и не падал
- Использовать
expire_on_commit=True, чтобы связи перечитывались явно
Разбор
С raiseload любая попытка неявно подгрузить связь заканчивается ошибкой, и разработчик вынужден явно указать selectinload или joinedload. В async это вдобавок превращает невнятный MissingGreenlet в понятное сообщение. echo полезен для отладки, но не ловит регрессии автоматически, а пул и истечение атрибутов к N+1 отношения не имеют.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.