Тёмный

Зачем нужны select_related и prefetch_related [Upper Junior] 

Павлин Шарит - ИТ вместе с Николаем Павлиным
Просмотров 471
50% 1

👉 Telegram: t.me/pavlin_share
🎥 Чтобы не пропустить ничего важного и всегда быть в курсе, подписывайтесь на мой канал и активируйте уведомления! 🔔
В этом видео я подробно расскажу и покажу на примерах, как эффективно использовать методы select_related и prefetch_related в Django для оптимизации запросов к базе данных. Мы разберем, в чем разница между этими методами, когда и как их применять, чтобы улучшить производительность вашего Django-приложения.
🚀 Что вы узнаете из этого видео:
Что такое select_related и prefetch_related
Как они работают на практике
В каких ситуациях каждый метод будет наиболее полезен
Примеры использования в реальных проектах

Опубликовано:

 

28 сен 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 7   
@point_crash
@point_crash 3 месяца назад
Спасибо, помогло улучшить мой код
@vegzuzvegzuz2866
@vegzuzvegzuz2866 3 месяца назад
Было бы интересно послушать про более сложные кейсы когда select/prefetch недостаточно. В реальных кейсах связей бывает намного больше и запросы могут иметь более длинные связи. Также важный момент - если мы в сериализаторе будет использовать фильтр, то select/prefetch не сработает. В таких случаях надо делать Prefetch(). А для оптимизации запросов которые не решаются с select/prefetch надо использовать annotate
@nikolaypavlin
@nikolaypavlin 3 месяца назад
Не совсем понял, что значит в сериалайзерах используются фильтр, могу еще понять, если вы имели ввиду в вьюхе, но фильтры не будут влиять на выполнение базового queryset. Prefetch() позволяет просто более гибко выбрать объекты для связки Annotate и релейтеды концептуально разные, но могут положительно влиять на производительность, но в лоб бы их не сравнивал
@vegzuzvegzuz2866
@vegzuzvegzuz2866 3 месяца назад
​@@nikolaypavlin имеется ввиду фильтрация предзагруженных/закешированных данных на уровне сериализатора. Допустим мы не хотим все device, а только is_active=True. В таком случае будут новые запросы к БД и эффекта от prefetch related не будет. Насчет annotate, я их не то чтобы сравниваю, а привожу пример оптимизации запросов когда select/prefetch не помогут. На твоем примере, допустим, у Device есть OneToMany с Users и мы хотим получить список всех прошивок и количество юзеров по устройствам. Для этого у нас сериализатор который помимо полей Прошивки имеет поле кастомное поле users_count. Тут кеширование данных таблиц Device/Users не поможет, а вот если во вью сделать annotate в queryset, то будет только одно обращение к БД
@vegzuzvegzuz2866
@vegzuzvegzuz2866 3 месяца назад
Пример отпимизации запроса с Prefetch queryset = self.queryset.prefetch_related( 'tags', Prefetch('product_images', queryset=Image.objects.filter(raw=1)), Prefetch('parent_product__cats', queryset=Category.objects.only('title')) ).select_related('updated_by').filter(parent_product__vendor=self.request.user.staffuser.vendor) Пример оптимизации с annotate queryset = self.queryset.select_related('parent_product').prefetch_related('product_images').annotate( rate=(Avg('parent_product__parent_product_products__productreviews__rating')), reviews_count=Count('parent_product__parent_product_products__productreviews'), has_variation=Count('parent_product__parent_product_products', distinct=True), ) в этом случае, если бы rate, reviews_count, has_variation считались в сериализаторе, то получили бы N+1
@vegzuzvegzuz2866
@vegzuzvegzuz2866 3 месяца назад
Было бы интересно услышать твое мнение насколько корректно такое решение. Потому что в сети вся тема вокруг оптимизации запросов крутится на простых примерах с select/prefetch related
@nikolaypavlin
@nikolaypavlin 3 месяца назад
Много текста, постараюсь на все ответить: 1 сообщение: да, конечно, не поможет, тут действительно нужен будет Prefetch, чтобы явно указать, какие сущности нужны, но все еще не понимаю, где в сериализаторе ты планируешь это фильтровать (может через SerializerMethodField? Если так, то и Prefetch не поможет) Да, тут не поможет, нужен Annotate, согласен 2 и 3 сообщение Как один из вариантов оптимизации, альтернативой могло быть использование подзапросов avg_rating=Annotate(Subquery()), чтобы избежать джойгов и возможных дублей. Надо смотреть Explain по запросам и выбирать оптимальное решение Глобально - если можем посчитать что-то на уровне БД, а не питона, то пытаемся это сделать. И желательно снижать количество запросов, чтобы избегать оверхедов на них
Далее
Barno
00:22
Просмотров 538 тыс.
Замени свой терминал на Warp [Any]
11:09