#33973: Performance regression when moving from 3.1 to 3.2
-------------------------------------+-------------------------------------
Reporter: Marc | Owner: nobody
Parizeau |
Type: | Status: new
Uncategorized |
Component: | Version: 3.2
Uncategorized | Keywords: performance
Severity: Normal | regression
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I am seing a sharp increase in execution time for some of my queries when
moving from Django 3.1 to 3.2. And the performance hit appears to be the
same for Django 4.
My backend is Postgres 14.2.
My Django project has forums for different types of content. The forum app
consists essentially of 5 tables:
1. a `Post` table that contains forum posts (essentially a text field);
2. a `Thread` table where rows point to a specific content and post;
3. a `FollowUp` table where rows point to a specific thread and post;
4. a `ThreadEntry` table where rows point to a thread, a user, and the
last seen thread post for this user;
5. a `FollowUpEntry` table where rows point to a followup, a user, and the
last seen followup post for this user.
Here is an example query that executes 2 times slower on 3.2 than on 3.1:
{{{
Content.objects.all().annotate(
has_unread_posts=Greatest(
# a content is unread if at least one condition is true
Exists(
# a thread has never been read (has no user entry)
Thread.objects.filter(
content=OuterRef('pk'),
).exclude(threadentry__user=user)
),
Exists(
# a thread entry is not up-to-date
ThreadEntry.objects.filter(
thread__content=OuterRef('pk'),
user=user,
).exclude(post=F('thread__post'))
),
Exists(
# a followup has never been read
FollowUp.objects.filter(
thread__content=OuterRef('pk')
).exclude(followupentry__user=user)
),
Exists(
# a followup entry is not up-to-date
FollowUpEntry.objects.filter(
followup__thread__content=OuterRef('pk'),
user=user,
).exclude(post=F('followup__post'))
),
)
).filter(
has_unread_posts=True,
).order_by(
'course__uid',
'-version__start',
).select_related(
'course',
'version',
)
}}}
`Course` and `Version` are other tables related to `Content`.
I want to know with this query, for each content, whether or not there is
something new in the corresponding forum for a given user. There is
something new if any one of the following condition is true:
1. there exists a thread for which the user has no thread entry (an entry
is added when the thread is first read by the user);
2. there exists a user thread entry for which the last read post is not up
to date with the current thread post (the thread owner has modified the
post since);
3. there exists a followup for which the user has no followup entry (an
entry is added when the followup is first read by the user);
4. there exists a user followup entry for which the last read post is not
up to date with the followup post (the followup owner has modified the
post since).
On my machine, just by changing the Django version using pip, and nothing
else, this query takes about 1 second of execution on Django 3.1.14, and a
little more than 2 seconds on Django 3.2.15, so about a 2x increase. Here
are the current table sizes for my forum app:
- `Thread`: ~30K
- `FollowUp`: ~46K
- `ThreadEntry`: ~1.3M
- `FollowUpEntry`: ~4.5M
- `Post`: ~103K
And there is 33 `Content` rows.
Am I the only one observing such performance regressions with Django 3.2?
On other more complex queries that contain nested subqueries, I have seen
up to **30x** execution time increases.
Did something major happen in SQL generation from 3.1 to 3.2?
Am I doing something wrong? How can this happen?
Any help on understanding what is going on with Django 3.2 would be much
appreciated.
Best regards,
--
Ticket URL: <https://code.djangoproject.com/ticket/33973>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070182f9854cef-5995e223-f96e-4bff-8050-72f4b0c63c3c-000000%40eu-central-1.amazonses.com.