#31965: MySQL fast-delete optimizations introduced in Django 3.1 don't properly
deal with aggregation and cause performance regression.
-------------------------------------+-------------------------------------
               Reporter:  Simon      |          Owner:  nobody
  Charette                           |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  3.1
  layer (models, ORM)                |
               Severity:  Release    |       Keywords:
  blocker                            |
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 [https://github.com/django/django/pull/11996#issuecomment-682349899 As
 reported on Github] the fast-delete optimization on MySQL to use the
 proprietary `DELETE FROM` syntax introduced in #23576 and the follow up
 commit to disable it on MariaDB 10.3.1+
 5b83bae031a9771d86933bcc808d4bf2e21216a2 are causing performance
 regression due it's poor query planing of `DELETE` involving subqueries.

 [https://github.com/django/django/pull/11931#issuecomment-547862119 While
 investigating the initially reported failure on MariaDB] I noticed that
 the MySQL's `SQLDeleteCompiler` implementation was also not properly
 dealing while filters against aggregation. It's normally not an issue
 because aggregation is done against against many-to-many relationships
 that involve reverse `ForeignKey` that usually have an `on_delete` that
 require in-memory fetching from `deletion.Collector` (e.g. `CASCADE`,
 `SET_NULL`) and thus disable fast-delete. However when only fast-delete
 `on_delete` handlers are involved (e.g. `DO_NOTHING` or future database
 level `on_delete` support #21961) this can be an issue that results in a
 `Invalid use of group function` crash due to an attempt at using aggregate
 functions in the `WHERE` clause.

 In order to address both issues I suggest we
 1. Always use the subquery approach when aggregation is involved
 2. Materialize the subquery at the database level when the backend doesn't
 have the `update_can_self_select` feature
 3. Favor the proprietary `DELETE FROM` syntax otherwise to work around
 MySQL poor handling of subqueries and avoid the generation of slow
 queries.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31965>
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 django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.175c897621ebc155f89ac316c04923c9%40djangoproject.com.

Reply via email to