РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
⊗pydjPmMRSR 151 of 187 menu

Жадная загрузка select_related в Django

Пусть у нас есть категории и посты, связанные через ForeignKey:

categories

  • id
  • name

posts

  • id
  • title
  • category_id

Связанные объекты в Django по умолчанию загружаются лениво. Это значит, что SQL-запрос к категории выполняется в момент обращения к post.category.

Давайте получим все посты и в цикле выведем название категории:

from main.models import Post posts = Post.objects.all() for post in posts: print(post.title, post.category.name)

На каждый пост Django сделает отдельный запрос к таблице категорий. Если постов 100, получится 101 запрос: один на список постов и еще 100 на категории. Это называют проблемой N+1.

Для решения используют метод select_related. Он заранее подгружает связанный объект через JOIN. Метод подходит для ForeignKey и OneToOneField:

posts = Post.objects.select_related('category') for post in posts: print(post.title, post.category.name)

Теперь Django сделает один запрос с JOIN, а в цикле лишних обращений к базе не будет.

То же работает для связи один к одному. Пусть посты связаны с миниатюрами:

posts

  • id
  • title

thumbnails

  • id
  • path
  • alt
  • post_id

Подгрузим миниатюры заранее:

posts = Post.objects.select_related('thumbnail') for post in posts: print(post.title, post.thumbnail.path)

Получите все города вместе со странами через select_related.

Получите всех работников вместе с контактами через select_related.

Расскажите, в чем проблема N+1 и как select_related ее решает.

Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить