Оптимизация подзапросов Django ORM

У меня есть функция с некоторыми вычислениями. Подзапрос с OuterRef работает слишком долго, как я могу оптимизировать или найти другой способ получить id для average_ndmi?

def get_ranking_manager_ndvi_regions(
    year: str, month: int, pk: Optional[int] = None
) -> List[Region]:

    return (
        get_regions(pk=pk)
        .annotate(
            year=SearchVector("commune__field__fieldattribute__date__year"),
            month=SearchVector(
                Cast("commune__field__fieldattribute__date__month", CharField())
            ),
            size=Sum(F("commune__field__fieldattribute__planted_area")),
            field_count=Count("commune__field"),
        )
        .filter(year=year, month=str(month))
        .annotate(
            average_ndvi=Subquery(
                Field.objects.filter(commune__region__id=OuterRef("pk"))
                .values("commune__region__id")
                .annotate(ndvi_avg=Avg("fieldattribute__ndvi"))
                .values("ndvi_avg"),
                output_field=FloatField(),
            )
        )
        .annotate(
            standart_deviation=(
                Sum(
                    (F("commune__field__fieldattribute__ndvi") - F("average_ndvi"))
                    ** 2,
                    output_field=FloatField(),
                )
                / F("field_count")
            )
            ** (1 / 2)
        )
    )```

Чтобы оптимизировать работу подзапроса в вашей функции, вы можете попробовать следующие подходы:

  1. Используйте метод .only() для ограничения полей, которые извлекаются из базы данных. Это может уменьшить объем данных, которые необходимо передавать между базой данных и приложением, и повысить производительность. Например:

Field.objects.only("commune__region__id", "fieldattribute__ndvi")

  1. Используйте метод .select_related() для предварительной выборки связанных объектов. Это может уменьшить количество необходимых запросов к базе данных и повысить производительность. Например:

Field.objects.select_related("commune__region", "fieldattribute")

  1. Используйте метод .prefetch_related() для предварительной выборки отношений "многие ко многим" и отношения "один-ко-многим". Это также может уменьшить количество запросов к базе данных, что может повысить производительность. Например:

    Field.objects.prefetch_related("fieldattribute")
    

Надеюсь, эти предложения помогут улучшить работу вашей функции.

Вернуться на верх