Proposal to merge activerecord-delay_touching into Rails


Last summer I wrote the activerecord-delay_touching gem to fix a performance problem. The gem has been used in production for six months on multiple sites. I am writing now to propose that I merge this gem into Rails.

I’d like to get feedback on this proposal before I create the PR, because it’s a non-trivial amount of work. (E.g., replace Rspec with Minitest, remove Timecop from the specs, etc.)

The problem: for key-based expiration of fragment caches in Rails, you typically use touch: true on the belongs_to statement. But when you create or update N records that all belong_to the same owning record, the cascading touches cause that record to be touched N times. All those DB round-trips turn out to be really slow. It’s similar to the traditional N+1 query problem, only for updates. This can happen even if you only make a single save call–e.g., when you use accepts_nested_attributes_for.

The solution: batch up your ActiveRecord “touch” operations into the smallest possible number of DB round-trips. This speeds things up a LOT. (I had numbers last summer from the app I was working on; I’ve since lost them. I’ll work on regenerating them.)

How: by calling delay_touching. I modeled this API on the no_touching API that was introduced in Rails 4.1:

  ActiveRecord::Base.delay_touching do

There’s more detail about what the gem does, how it works, and a couple of potential gotchas in the README:

Feedback? Shall I go ahead?

Brian Morearty

I think this is kinda related to this issue that we want to fix for rails 5.

I think you’re right, Arthur. Thanks for the pointer.