Как оптимизировать эти запросы Django для более быстрого выполнения?

У меня есть список моделей campaign_list, как показано ниже, в каждой модели есть некоторые общие поля (например, overall_score, audit_date, audit_id). Я хочу найти средний балл для каждого месяца. Я написал код ниже, и он работает, но время выполнения больше. Я хочу оптимизировать время выполнения. Время выполнения увеличивается по мере увеличения количества записей (в настоящее время у меня 200k+ записей и добавление).

# List of 40 Models 
campaign_list = [Model1, Model2, Model3, ....., ModelN]

# Method 1
campaign_score = sum([sum([j.overall_score for j in i.objects.filter(audit_date__range=[start_date, todays_date])]) for i in campaign_list])

# Method 2
campaign_score = 0
for i in campaign_list:
   score = sum([j.overall_score for j in i.objects.filter(audit_date__range=[start_date, todays_date])])
   campaign_score += score 

Если у вас действительно есть список классов моделей, нетривиально сделать все в одном запросе, но, по крайней мере, вы можете использовать Sum агрегат для суммирования по каждой модели в базе данных.

# List of 40 Models
campaign_list = [Model1, Model2, Model3, ...]

campaign_score = 0
for campaign_model in campaign_list:
    res = campaign_model.objects.filter(
        audit_date__range=[start_date, todays_date]
    ).aggregate(score=Sum("overall_score"))
    if res.get("score"):
        campaign_score += res["score"]

Я предполагаю, что у вас есть различные модели с внешним ключом модели Audit и, таким образом, есть общее поле audit_id. Поэтому мы можем объединить модели с помощью метода ORM select_related. После объединения столбцы будут разными для каждой модели, как специально overall_score. Мы можем агрегировать значение, используя F каждого столбца и получим общий балл.

Audit.objects.select_related('model2', 'model3', 'model4')
    .aggregate(
        score=F('overall_score') + F('model2__overall_score') + F('model3__overall_score') + F('model4__overall_score').get('score')
)

При использовании этого запроса выполняется только один запрос. Вы можете проверить с помощью

from django.db import connection, reset_queries
reset_queries()
Audit.objects.select_related('model2', 'model3', 'model4')
    .aggregate(
        score=F('overall_score') + F('model2__overall_score') + F('model3__overall_score') + F('model4__overall_score').get('score')
)
print(connection.queries)
reset_queries()

Как сказал @AKX, если у вас огромные данные, то вам следует использовать индекс и сэкономить время.

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