在获取具有关联记录的对象数组时,我获得了使用急切加载来避免 N+1 的好处,但是在获取单个记录时使用急切加载是否重要?

就我而言

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

在表演 Action 中,我尝试使用机架迷你分析器查看使用预先加载是否有趣
User.includes(:skills, :addresses, :devices, :authentications).find(params[:id])

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

关于在这种情况下使用预先加载的任何建议?

最佳答案



对于一层深的关联,没有。

如果您有嵌套的关联,是的。

# 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

在这种情况下,最好预先加载 skills: :category
User.includes(skills: :category).find(id)

编辑

Rails 提供了两种方法来避免 N+1 查询,它称为 preload ing 和 eager_load ing。

Preload 为每个集合触发单独的 SQL 查询。

Eager load 尝试构建一个大量的左连接 SELECT 来检索 1 个查询中的所有集合。

简短的版本是 includes 让 Rails 选择使用哪个。但是你可以强制一种方式或另一种方式。
User.eager_load(:skills, :addresses, :devices, :authentications).find(params[:id])

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

进一步阅读 :
  • What's the difference between “includes” and “preload” in an ActiveRecord query?
  • http://blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html
  • http://blog.arkency.com/2013/12/rails4-preloading/
  • 关于ruby-on-rails - Rails 4 Eager Load has_many 单个对象的关联,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34318342/

    10-08 22:57