Rails 4 Eager Load has_many Associations for single object
Asked Answered
N

2

7

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?

Nalley answered 16/12, 2015 at 17:26 Comment(0)
P
14

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:

Photoemission answered 16/12, 2015 at 17:59 Comment(2)
But even for associations 1 level deep, shouldn't it reduce the number of sql queries (from 5 to a single one in that example)?Nalley
It sounds like you're looking for Rails' eager_load method. I will edit my answer.Photoemission
N
4

Try using the Bullet gem for detecting unused or missing eager loading. It's designed to tell you if there are wasted include statements, or inefficient N+1 queries, where includes would help.

If there's a problem, it can be configured to output to the Rails logger to let you know. Or you can have it show you a notification in the browser on pages that need optimising.

Numbing answered 16/12, 2015 at 17:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.