Рубрики
Без рубрики

Советы оптимизации Django ORM # 2 Prefetch_related

Это имеет аналогичную цель для выбора_Related, в том, что оба предназначены для остановки потока батов данных … Теги с Python, Django, SQL, базой данных.

Это имеет аналогичную цель для select_related В том, что оба предназначены для остановки запросов базы данных, вызванные доступом к связанным объектам, но стратегия совсем другая.

select_related Работает, создавая присоединение SQL и включение полей связанного объекта в выборе оператора. По этой причине select_related Получает связанные объекты в той же базе данных. Однако, чтобы избежать гораздо более крупного набора результатов, который приведет к объединению через «много» отношений, select_related ограничен однозначными отношениями – иностранным ключом и однозначным.

Prefetch_related С другой стороны, делает отдельный поиск для каждой связи и делает «присоединение» в Python. Это позволяет ему предпринимать многие-много-много и много к одному объектам, которые не могут быть выполнены с использованием select_related.

Пойдем на нашу любимую часть примеров:

В этом у нас есть таблицы пользователей и языков, каждый пользователь знает более одного языка, и мы хотим перечислять пользователей с их языками

# models.py
class Language(models.Model):
    name = models.CharField(max_length=63)
    code = models.CharField(max_length=7)


class User(models.Model):
    fullname = models.CharField(max_length=127)
    languages = models.ManyToManyField(Language, related_name="users")
# serializers.py
class LanguageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Language
        fields = ('id', 'name', 'code')


class UserSerializer(serializers.ModelSerializer):
    languages = LanguageSerializer(many=True)

    class Meta:
        model = User
        fields = ('id', 'fullname', 'languages')
# views.py
class UserListView(ListAPIView):
    serializer_class = UserSerializer
    queryset = User.objects.prefetch_related('languages')

Согласно Prefetch_related Документация:

Чтобы избежать гораздо более крупного набора результатов, который приведет к объединению на «много» отношений, Prefetch_related делает отдельный поиск для каждой связи и делает «присоединение» в Python

Так что запрос User.objects.prefetch_related («Языки») будет разделен на 2 запроса:

SELECT "user"."id", "user"."fullname" FROM "user"
SELECT "user_language"."user_id","language"."id", "language"."name",
"language"."code" 
FROM "language" INNER JOIN "user_language" 
ON ("language"."id" = "user_language"."language_id") 
WHERE "user_language"."user_id" IN (...);

И последнее, что соответствует этим запросам с Python код

Оригинал: “https://dev.to/shawara/django-orm-optimization-tips-2-prefetchrelated-57oj”