Rails 4 Eager Load has_many单个对象的关联

ste*_*cdn 2 many-to-many ruby-on-rails has-many eager-loading ruby-on-rails-4.1

在获取带有相关记录的对象数组时,我得到了使用预加载以避免N + 1的好处,但是在获取单个记录时使用预加载很重要吗?

就我而言

user has_many :addresses
user has_many :skills
user has_many :devices
user has_many :authentications
Run Code Online (Sandbox Code Playgroud)

在表演动作中,我尝试使用机架迷你分析器查看是否渴望使用急切加载

User.includes(:skills, :addresses, :devices, :authentications).find(params[:id])
Run Code Online (Sandbox Code Playgroud)

但我似乎有相同数量的sql请求。

是否有针对此类情况使用紧急加载的建议?

mes*_*jah 7

获取单个记录时使用急切加载是否重要?

对于协会深一层,没有。

如果您有嵌套的关联,则可以。

# 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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,最好急于加载 skills: :category

User.includes(skills: :category).find(id)
Run Code Online (Sandbox Code Playgroud)

编辑

Rails提供了两种避免N + 1查询的方式,称为preloading和eager_loading。

预加载为每个集合激发单独的SQL查询。

急切的加载尝试构造一个大规模的左联接SELECT,以在1个查询中检索所有集合。

简短的版本是includes让Rails选择要使用的版本。但是您可以强制使用另一种方法。

User.eager_load(:skills, :addresses, :devices, :authentications).find(params[:id])
Run Code Online (Sandbox Code Playgroud)

应该在1个查询中检索所有记录。

进一步阅读


Mat*_*son 4

尝试使用Bullet gem来检测未使用或丢失的急切加载。它旨在告诉您是否存在浪费的include语句或效率低下的 N+1 查询,哪些地方includes会有所帮助。

如果出现问题,可以将其配置为输出到 Rails 记录器以通知您。或者您可以让它在浏览器中向您显示需要优化的页面的通知。