#18676: Django should do m2m deletes in a single query when possible -------------------------------------+------------------------------------- Reporter: jdunck | Owner: nobody Type: | Status: new Cleanup/optimization | Version: 1.4 Component: Database layer | Resolution: (models, ORM) | Triage Stage: Accepted Severity: Normal | Needs documentation: 0 Keywords: | Patch needs improvement: 0 Has patch: 1 | UI/UX: 0 Needs tests: 0 | Easy pickings: 0 | -------------------------------------+-------------------------------------
Comment (by akaariai): Some bugs optimizations done in the above branch. I know there is still more to do in !DeleteQuery.delete_qs() - at least the logic for primary key table alias selection isn't valid - there is no guarantee that the get_initial_alias() contains the pk field. I did some little benchmarking, the models: {{{ class Place: name = TextField class AA: place = ForeignKey(Place, null=True) }}} The tests are: create 0, 1, 10, or 100 AA and delete with AA.objects.all().delete(), and similarly 0, 1, 10 or 100 AA objects, this time deleted with AA.objects.filter(`place__name='p'`).delete(). The first test hits the single-table delete in delete_qs, the second case hits the joined delete in delete_qs. The speed results for PostgreSQL are as follows: ||test||master||fast_delete|| ||all, 0||.203827||.155007|| ||all, 1||..314117||.157289|| ||all, 10||.371872||.153490|| ||all, 100||.878677||.203811|| ||filter, 0||.476457||.545436|| ||filter, 1||.468119||.503444|| ||filter, 10||.569284||.503499|| ||filter, 100||1.356935||.693341|| So, on all but joined filter with 0 or 1 deleted object the patch is faster. There is some variance in the results, as can be seen from the .545 result for the 0 object filter case. That result is usually faster than the case with one object. The reason for the speed difference is that the delete query with an inner join is a little slow for the 0 objects case, and there is some extra overhead from query.clone() in the inner join case. The relative speeds are similar on in-memory SQLite. The above test-case is favouring the old behaviour of fetching all the objs into memory, as there isn't actually any data. For large deletes we have a clear win. For small deletes we have minor improvement in the non- joined case, and a minor loss for the joined case. For huge deletes it is easy to construct arbitrarily large differences in speed. -- Ticket URL: <https://code.djangoproject.com/ticket/18676#comment:3> 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 post to this group, send email to django-updates@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.