TIL that since Rails 6 there have been quite new ActiveRecord
bulk methods:
insert_all
and upsert_all
. To better understand their powers, let’s quickly refresh our knowledge about INSERT
and UPSERT
SQL operations:
INSERT
is used to insert new records in a table.UPSERT
either inserts or updates a row if it already exists.
How do we perform the above operations within Rails applications usually? Well, there are create
and update
methods.
To my surprise, there are also insert
and upsert
ones 😲. According to the Rails documentation:
insert
inserts a single record into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record’s type casting and serialization.upsert
updates or inserts (upserts) a single record into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record’s type casting and serialization.
What is even more interesting, they call the insert_all
and upsert_all
methods:
# File activerecord/lib/active_record/persistence.rb, line 66 def insert(attributes, returning: nil, unique_by: nil) insert_all([ attributes ], returning: returning, unique_by: unique_by) end
# File activerecord/lib/active_record/persistence.rb, line 187 def upsert(attributes, returning: nil, unique_by: nil) upsert_all([ attributes ], returning: returning, unique_by: unique_by) end
Example usage:
Book.insert_all([ { id: 1, title: "Rework", author: "David" }, { id: 2, title: "Eloquent Ruby", author: "Russ" } ])
The methods insert and/or update all the records using a single SQL query. They also do not instantiate any models nor do trigger Active Record callbacks and validations. What does it mean for us? They are much faster, especially for bulk operations, when ActiveRecord callbacks and validations can be skipped.
insert!
and insert_all!
. They raise an exception when any row violates unique index on the table.Bonus:Â If you are interested in some basic benchmarks you can find them in the PR which added the methods.