#32711: MySQL performance regression in
forms.models.apply_limit_choices_to_to_formfield
----------------------------------------------+------------------------
Reporter: Thomas Achtemichuk | Owner: nobody
Type: Uncategorized | Status: new
Component: Forms | Version: 3.2
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
----------------------------------------------+------------------------
[https://github.com/django/django/commit/556fa4bbba5ba86bc1646a86fb11ab55405d4aa4
This commit] related to #11707 in Django 3.2 introduced changes to
apply_limit_choices_to_to_formfield. The query generated, for example,
with this field on a model:
{{{
editor = models.ForeignKey(
settings.AUTH_USER_MODEL,
null=True,
blank=True,
limit_choices_to={
'is_staff': True,
'groups__name': 'Editor',
},
on_delete=models.SET_NULL)
}}}
results in the following query which takes ~25s to return on a
`db.r5.xlarge` RDS instance running MySQL 5.7:
{{{
SELECT
`auth_user`.`id`,
`auth_user`.`password`,
`auth_user`.`last_login`,
`auth_user`.`is_superuser`,
`auth_user`.`username`,
`auth_user`.`first_name`,
`auth_user`.`last_name`,
`auth_user`.`email`,
`auth_user`.`is_staff`,
`auth_user`.`is_active`,
`auth_user`.`date_joined`
FROM
`auth_user`
WHERE EXISTS(
SELECT
(1) AS `a`
FROM
`auth_user` U0
INNER JOIN
`auth_user_groups` U1 ON (U0.`id` = U1.`user_id`)
INNER JOIN
`auth_group` U2 ON (U1.`group_id` = U2.`id`)
WHERE (
U2.`name` = 'Editor'
AND U0.`is_staff`
AND U0.`id` = `auth_user`.`id`
)
LIMIT 1
)
ORDER BY `auth_user`.`date_joined` DESC;
...
21 rows in set (26.18 sec)
}}}
Counts for the involved tables:
{{{
mysql> SELECT COUNT(*) FROM auth_user;
+----------+
| COUNT(*) |
+----------+
| 3360439 |
+----------+
mysql> SELECT COUNT(*) FROM auth_group;
+----------+
| COUNT(*) |
+----------+
| 14 |
+----------+
mysql> SELECT COUNT(*) FROM auth_user_groups;
+----------+
| COUNT(*) |
+----------+
| 460 |
+----------+
}}}
And the `EXPLAIN`:
{{{
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: auth_user
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3201287
filtered: 100.00
Extra: Using where; Using filesort
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: U2
partitions: NULL
type: const
possible_keys: PRIMARY,name
key: name
key_len: 452
ref: const
rows: 1
filtered: 100.00
Extra: Using index
*************************** 3. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: U1
partitions: NULL
type: eq_ref
possible_keys: user_id,auth_user_groups_403f60f,auth_user_groups_425ae3c4
key: user_id
key_len: 8
ref: bso.auth_user.id,const
rows: 1
filtered: 100.00
Extra: Using index
*************************** 4. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: U0
partitions: NULL
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: bso.auth_user.id
rows: 1
filtered: 90.00
Extra: Using where
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/32711>
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/050.9ee563d2b90e41d8f6e96b8fc77aec98%40djangoproject.com.