has_many / has_one:在某些情况下,通过生成N + 1个查询,请改用委托吗?

时间:2012-08-30 02:39:17

标签: ruby-on-rails optimization rails-activerecord

在诊断N + 1查询问题时,我注意到ActiveRecord has_one / has_many:链接在一起时通过关联忽略包含。

示例代码(我的案例与我们的模型一致):

class Post  < ActiveRecord::Base
   has_one :user
   has_one :badge, through: :user
end


class User  < ActiveRecord::Base
   has_one :badge
 end

 class Badge  < ActiveRecord::Base

 end

除了包含

之外,通过关联不会执行其他查询
post = Post.include(:user => :badge)
post.user.badge 

但是试图使用通过:

post = Post.include(:user => :badge)
post.badge

进行另一次LIMIT 1查询。这将导致循环中的N + 1。

为了解决这个问题,我想用代理来替换所有的has_one / many:through。 has_many / one:through选项是否有任何优势(对于没有条件的情况)?

2 个答案:

答案 0 :(得分:1)

我认为此代码可能对您有用。

post = Post.includes(:user => [:badge])

答案 1 :(得分:1)

问题很可能包括(:user =&gt;:badge)遵循Post.user关联,然后是User.badge关联,所以当你遵循单个Post.badge关联时,Rails会忽略包含,因为你'为不同的协会设置了它。

即使它们是相同的路径,它们也是不同的关联。

只是包括(:徽章)会更好。