Трудно сделать улучшения без измерений для сравнения. Но вот несколько мыслей.
Сначала я немного изменил порядок кода, чтобы лучше его понять.
from django.db.models import Count, Q
from django.utils import timezone as tz
from .models import Brand, ViewStat
stat_type = 'Some String'
some_brand = Brand.objects.first()
active_org_id_set = set(
some_brand.organisation_set.active().values_list('id', flat=True))
time_now = tz.now()
one_month_ago = time_now - relativedelta(months=int(1))
three_months_ago = time_now - relativedelta(months=int(3))
twelve_months_ago = time_now - relativedelta(months=int(12))
result = ViewStat.objects.select_related(None)\
.filter(stat_type__icontains=stat_type)\
.filter(
Q(
Q(brand_id=some_brand.pk)
| Q(organisation_id__in=active_org_id_set)))\
.aggregate(
one=Count('id', filter=Q(created__gte=one_month_ago),
three=Count('id', filter=Q(created__gte=three_months_ago)),
twelve=Count('id', filter=Q(created__gte=twelve_months_ago)),
all=Count('id')))
Всегда лучше использовать один вызов tz.now()
.
Похоже, что последний фильтр в агрегации (с использованием relativedelta(999)
) можно было бы опустить.
Я предпочитаю использовать отдельные переменные для хранения данных фильтра, поэтому я создал active_org_id_set
. Обратите внимание, что я собираю только PK (используя .values_list()
), а не все объекты Organisation
, поэтому потребляемая память намного меньше.
Затем я использую это active_org_id_set
и вместо этого использую organisation_id__in
из organisation__in
, так что нет необходимости объединять таблицу Organisation
с таблицей ViewStat
.
Я также фильтрую brand_id
вместо brand
, чтобы избежать присоединения таблицы Brand
к таблице ViewStat
table.
Я явно использую .select_related(None)
, чтобы свести к минимуму объединенные таблицы. Возможно, в этом вызове нет необходимости, но у меня нет доступа к вашему плану выполнения базы данных.