Rails Batch Processing Of Records For destroy_all
July 03, 2021
In Ruby on Rails, we use
destroy_all when we want to delete a collection of
Article.where(published: false).destroy_all # Logs # Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."published" = #? [["published", 0]] # TRANSACTION (0.1ms) begin transaction # Article Destroy (0.5ms) DELETE FROM "articles" WHERE "articles"."id" = ? [["id", 1]] # TRANSACTION (1.7ms) commit transaction # TRANSACTION (0.1ms) begin transaction # Article Destroy (0.5ms) DELETE FROM "articles" WHERE "articles"."id" = ? [["id", 2]] # TRANSACTION (1.9ms) commit transaction # Output #=> [#<Article id: 1, title: "#0 Title", published: false>, #<Article id: 2, title: "#1 Title", published: false">]
As we notice above in the logs, all the records were loaded into the memory at a time and then
DELETE transaction was initiated for each record one by one.
destroy_allalways returns the destroyed records as an array.
The initial load of all records at a time consumes memory unnecessarily which can be processed in batches.
To destroy records in batches, we can use
destroy_all methods defined in
Let's refactor above example to process it in batches:
# Ruby on Rails v6.1, v7.0 Article.where(published: false).in_batches(of: 100).destroy_all
When Ruby on Rails was getting ready for v7.0 release, there was a pull request that proposed to use
in_batches under the hood for
destroy_all method. However that pull request was reverted after initial merge since that might break many existing applications.