model.association.delete_all performance issue - Rails 3.2.3 #6289

njakobsen opened this Issue May 12, 2012 · 7 comments


None yet
5 participants

njakobsen commented May 12, 2012

This is a very similar issue to #3672. Instead of the problem being on the :dependent => :delete_all callback, it occurs when calling delete_all on an association. The problem is that instead of returning the count of the number of deleted objects like :delete_all does on an ActiveRecord model, calling :delete_all on an ActiveRecord association returns an array of all the deleted objects.

I am running into an issue when I try to destroy all 30,000 objects associated with my main model and Rails tries to instantiate each one. The whole point behind :delete_all is that for performance reasons it's purely a database call, and no ActiveRecord objects should be instantiated.

See for an example of the bug.


gmile commented May 12, 2012

Indeed, I've ran the code in gist and it appears to be extremely slow


njakobsen commented May 13, 2012

Maybe @jonleighton can weigh in on this as he was able to fix the other similar bug.

jonleighton added a commit that referenced this issue May 18, 2012

Perf: Don't load the association for #delete_all.
Bug #6289



jonleighton commented May 18, 2012

Fixed in master and 3-2-stable by the above commits.


njakobsen commented May 18, 2012

Excellent! I'll be able to unhack all my codes.


jonleighton commented Jun 7, 2012

I am afraid you might need to rehack your codes until Rails 4 is out: 959fb8e


njakobsen commented Jun 7, 2012

Thanks for the heads up.

I'm just trying to interpret the decision from reading the commit log for 959fb8e. My understanding is that for some reason, people used delete_all instead of destroy_all and expected callbacks to work since rails 2.3? And that this is a major change that doesn't belong in a small point release, so it's being left for Rails 4.0?

fenelon commented Nov 6, 2012

On Rails 3.2.8:

Note that "deleting from s3" is in a before_destroy callback. The delete_all spec says it doesn't trigger any callbacks.

irb(main):006:0> h = Hotel.find(40069)
irb(main):007:0> h.images.delete_all
   (0.1ms)  BEGIN
deleting from s3
  SQL (0.4ms)  DELETE FROM `hotel_images` WHERE `hotel_images`.`id` = 7388
deleting from s3
  SQL (0.3ms)  DELETE FROM `hotel_images` WHERE `hotel_images`.`id` = 7389
deleting from s3
  SQL (0.3ms)  DELETE FROM `hotel_images` WHERE `hotel_images`.`id` = 7390
deleting from s3
  SQL (0.2ms)  DELETE FROM `hotel_images` WHERE `hotel_images`.`id` = 7391
deleting from s3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment