Harddjango

Чем select_related от prefetch_related?

1Постановка

Разберём, что от вас хотят в этом вопросе и как к нему подступиться на собеседовании.

2Решение

Оба решают N+1 проблему, но по-разному. select_related — для single-valued (FK, OneToOne), делает SQL JOIN. prefetch_related — для multi-valued (M2M, reverse FK), делает отдельный запрос + Python-side join.

# select_related — 1 запрос с JOIN (для FK/OneToOne)
users = User.objects.select_related('profile').all()
for u in users:
    print(u.profile.bio)   # без доп. запроса

# prefetch_related — 2 запроса (для M2M/reverse FK)
users = User.objects.prefetch_related('posts').all()
# SELECT users; затем SELECT posts WHERE user_id IN (...)
for u in users:
    print(u.posts.all())   # без доп. запроса

# Цепочки и кастомизация
User.objects.select_related('profile').prefetch_related('posts__comments')
from django.db.models import Prefetch
User.objects.prefetch_related(
    Prefetch('posts', queryset=Post.objects.filter(published=True))
)
  • select_related для 1-2 уровней (JOIN explosion на большой глубине);
  • Неверный выбор — performance killer: N+1 если забыл, JOIN explosion если на M2M.

3Как отвечать

  • Сначала уточните условия и ограничения, покажите аналитическое мышление.
  • Рассуждайте вслух — интервьюеру важен ход мысли, а не только финальный ответ.
  • Оцените сложность по времени и памяти (Big-O), если это алгоритмический вопрос.
💡

На реальном собеседовании Alffert подскажет развёрнутый ответ в реальном времени.