Анализ и исправление узких мест запросов к базе данных

prefetch_related('articles') загружает одну выборку, а последующий articles.filter(deleted=False) создаёт новые запросы. В результате предварительная загрузка не устраняет N+1 для используемого фильтра.

Короткий ответ

Что ответить на собеседовании

prefetch_related('articles') загружает одну выборку, а последующий articles.filter(deleted=False) создаёт новые запросы. В результате предварительная загрузка не устраняет N+1 для используемого фильтра.

Подробный разбор

Ответ с пояснениями

Условие

Необходимо выявить и подробно описать проблемы в работе кода, которые снижают производительность запросов к БД. Рассмотрим функцию, получающую всех авторов и их связанные статьи.

def fetch_authors():
    authors_qs = Author.objects.prefetch_related('articles').all()

    for author in authors_qs:
        print(f'{author.get_full_name()}:')
        for article in author.articles.filter(deleted=False):
            print(f'  {article.name}')

Ответ

prefetch_related('articles') загружает одну выборку, а последующий articles.filter(deleted=False) создаёт новые запросы. В результате предварительная загрузка не устраняет N+1 для используемого фильтра.

Загрузите сразу нужные статьи в отдельный атрибут:

from django.db.models import Prefetch

def fetch_authors():
    authors = Author.objects.prefetch_related(Prefetch(
        'articles',
        queryset=Article.objects.filter(deleted=False),
        to_attr='visible_articles',
    ))
    for author in authors:
        print(f'{author.get_full_name()}:')
        for article in author.visible_articles:
            print(f'  {article.name}')

Article — предполагаемая модель статьи. Проверьте также, не выполняет ли get_full_name() запросы. Для огромного числа авторов нужна порционная обработка, иначе prefetch может занять много памяти.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее