#29943 closed Cleanup/optimization (fixed)
Document that admin changelist adds `pk` to ordering
Reported by: | Taha Jahangir | Owned by: | Hasan Ramezani |
---|---|---|---|
Component: | Documentation | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Consider a simple model with this definition for model and admin:
class MyModel(models.Model): class Meta: ordering = ('-created',) created = models.DateTimeField(default=now, db_index=True) message = models.CharField(max_length=20) @admin.register(MyModel) class MyModelAdmin(admin.ModelAdmin): pass
We created a model with the indexed created
field, and ordering
field set to it . It should works nicely. But if the tables go large, the listing will be slow, because the generated query is like:
SELECT "myapp_mymodel"."id", "myapp_mymodel"."created", "myapp_mymodel"."message" FROM "myapp_mymodel" ORDER BY "myapp_mymodel"."created" DESC, "myapp_mymodel"."id" DESC LIMIT 100;
And the database (in my case, postgresql) WILL NOT use the created
index and the query becomes very slow.
I treat this as a bug, because the default behavior of admin module is not sensible (and not documented), and will result in performance bug in normal setups , and it cannot be changed in a simple manner (without copying/monkey-patching of ChangeList.get_ordering
method).
A stackoverflow topic about this behavior:
https://stackoverflow.com/questions/32419190/django-admin-incorrectly-adds-order-by-into-query
The issue (and commit) when this behavior is introduced (~7 years ago)
#17198 -- Ensured that a deterministic order is used across all database backends
In reply to https://code.djangoproject.com/ticket/17198#comment:14 :
In our cases (a ~2M row table), the duration of count(*)
query is ~300ms, but viewing the 2000th page (LIMIT 100 OFFSET 200000
) is 8s!
Change History (12)
comment:1 by , 6 years ago
Description: | modified (diff) |
---|
comment:2 by , 6 years ago
Easy pickings: | unset |
---|
comment:3 by , 6 years ago
Component: | contrib.admin → Documentation |
---|---|
Summary: | Slow admin chanelist query (because of adding `pk` to ordering) → Document that admin changelist adds `pk` to ordering |
Triage Stage: | Unreviewed → Accepted |
Type: | Bug → Cleanup/optimization |
Absent another proposal, the behavior could be documented.
comment:4 by , 6 years ago
Taha, out of curiosity does adding a composite Index(fields=('-created', 'id'))
index instead of using db_index=True
helps anyhow? It shouldn't be significantly larger than the created
index db_index=True
created and provide a total ordering on your table.
comment:5 by , 6 years ago
There are two proposals for this issue:
1) Adding a variable (perhaps a property on ModelAdmin
) to easily enable/disable this behavior.
2) If we think in a larger scope, django-admin could have a huge-table mode. There are also other issues with large tables (like querying for distinct values in filters or displaying a long list of related items when filtering by foreign-key)
comment:6 by , 6 years ago
Has patch: | set |
---|---|
Owner: | changed from | to
Status: | new → assigned |
comment:7 by , 6 years ago
Patch needs improvement: | set |
---|
Ref PR: The suggestion to index both (e.g.) -created
and id
was made here and on #17198 comment:2, so should probably be mentioned in any documentation fix.
comment:8 by , 6 years ago
Patch needs improvement: | unset |
---|
the comment from the mentioned ticket added to note.
I also checked the override get_ordering(), so the behavior doesn't change.
comment:9 by , 6 years ago
Patch needs improvement: | set |
---|
Patch needs updating to reflect changes in f84ad16ba4bcf5fce6fc76593e0606573dec4697 (which was ref #17198)
Rough outline of the change needed is something like:
- If no total ordering existing,
pk
is added. - If this causes performance issues, add composite index.
Do you have a suggestion of what to do?