Оптимизация подзапросов 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)
)
)```
Чтобы оптимизировать работу подзапроса в вашей функции, вы можете попробовать следующие подходы:
- Используйте метод .only() для ограничения полей, которые извлекаются из базы данных. Это может уменьшить объем данных, которые необходимо передавать между базой данных и приложением, и повысить производительность. Например:
Field.objects.only("commune__region__id", "fieldattribute__ndvi")
- Используйте метод .select_related() для предварительной выборки связанных объектов. Это может уменьшить количество необходимых запросов к базе данных и повысить производительность. Например:
Field.objects.select_related("commune__region", "fieldattribute")
Используйте метод .prefetch_related() для предварительной выборки отношений "многие ко многим" и отношения "один-ко-многим". Это также может уменьшить количество запросов к базе данных, что может повысить производительность. Например:
Field.objects.prefetch_related("fieldattribute")
Надеюсь, эти предложения помогут улучшить работу вашей функции.