Ich beginne mit:
Code: Select all
users = User.objects.filter(organisation=organisation).filter(is_active=True)
Code: Select all
start_dateCode: Select all
for date in (start_date + datetime.timedelta(n):
for n in range((datetime.datetime.now().replace(tzinfo=pytz.UTC) - start_date).days + 1)):
Code: Select all
for date in (start_date + datetime.timedelta(n):
for n in range((datetime.datetime.now().replace(tzinfo=pytz.UTC) - start_date).days + 1)):
for user in users.filter(created_date__lte=date).iterator():
Was dazu führen kann, dass einige der eingefleischten Django-Fans die Fassung verlieren, ich mache alles oben Genannte in einer anderen Schleife!
Code: Select all
for survey in Survey.objects.all().iterator():
for date in (start_date + datetime.timedelta(n) for n in range((datetime.datetime.now().replace(tzinfo=pytz.UTC) - start_date).days + 1)):
for user in users.filter(created_date__lte=date).iterator():
Code: Select all
survey_result = SurveyResult.objects.filter(survey=survey, user=user, created_date__lte=date).order_by('-updated_date')[0]
Ich habe angefangen, über prefetch_related und das Prefetch-Objekt nachzudenken. Ich habe die Dokumentation konsultiert, kann sie aber anscheinend nicht auf meine Situation anwenden.
Tatsächlich dauert die Abfrage viel zu lange. Bei durchschnittlich 1000 Benutzern, 4 Umfragen und etwa 30 Tagen dauert die Ausführung dieser Abfrage 1 Minute.
Im Idealfall würde ich gerne 50 % davon einsparen. Wenn es besser wird, werde ich sehr glücklich sein. Ich möchte auch, dass die Belastung des DB-Servers reduziert wird, da diese Abfrage mehrmals in verschiedenen Organisationen ausgeführt werden könnte.
Ich möchte auch verbessern, wie solche schrecklichen Abfragen innerhalb von Schleifen innerhalb von Schleifen organisiert werden!
Vollständiger „komprimierter“ minimal lebensfähiger Snippet:
Code: Select all
users = User.objects.filter(organisation=organisation).filter(is_active=True)
datasets = []
for survey in Survey.objects.all():
data = []
for date in (start_date + datetime.timedelta(n) for n in
range((datetime.datetime.now().replace(tzinfo=pytz.UTC) - start_date).days + 1)):
total_score = 0
participants = 0
for user in users.filter(created_date__lte=date):
participants += 1
survey_result = \
SurveyResult.objects.filter(survey=survey, user=user, created_date__lte=date).order_by('-updated_date')[
0]
total_score += survey_result.score
# An average is calculated from the total_score and participants and append to the data array.:
# Divide catches divide by zero errors.
# Round will round to two decimal places for front end readability.
data.append(
round(
divide(total_score, participants), 2
)
)
datasets.append(data)
Also, weiter zu @dirkgrotens Antwort, ich verwende derzeit:
Code: Select all
for survey in Survey.objects.all():
results = SurveyResult.objects.filter(
user__in=users, survey=survey, created_date__range=date_range
).values(
'survey',
'created_date',
).annotate(
total_score=Sum('normalized_score'),
participants=Count('user'),
average_score=Avg('normalized_score'),
).order_by(
'created_date'
)
for result in results:
print(result)
Stehen mir noch andere Optimierungen zur Verfügung?
Mobile version