Rails 4 Eager Load has_many Associations for single object

stefano_cdn picture stefano_cdn · Dec 16, 2015 · Viewed 8.5k times · Source

I get the benefits of using eager loading to avoid N+1 when fetching an array of objects with their associated records, but is it important to use eager loading when fetching a single record?

In my case

user has_many :addresses
user has_many :skills
user has_many :devices
user has_many :authentications

In the show action, I am trying to see with rack mini profiler if it is interesting to use eager loading

User.includes(:skills, :addresses, :devices, :authentications).find(params[:id])

But I seem to have the same number of sql requests..

Any advice on using eager loading for such case or not?

Answer

messanjah picture messanjah · Dec 16, 2015

is it important to use eager loading when fetching a single record?

For associations one level deep, no.

If you have nested associations, yes.

# class User
has_many :skills

# class Skill
belongs_to :category

# this code will fire N + 1 queries for skill->category
user.skills.each do |skill|
  puts skill.category
end

In this case, it is better to eager load skills: :category

User.includes(skills: :category).find(id)

Edit

Rails provide two ways to avoid N+1 queries, which it refers to as preloading and eager_loading.

Preload fires individual SQL queries for each collection.

Eager load attempts to construct one massive left-joined SELECT to retrieve all collections in 1 query.

The short version is that includes lets Rails pick which one to use. But you can force one way or the other.

User.eager_load(:skills, :addresses, :devices, :authentications).find(params[:id])

Should retrieve all records in 1 query.

Further reading: