Rails找到关联的效率

时间:2012-07-04 09:19:07

标签: ruby-on-rails performance activerecord

我有一个用户,帖子和评论的应用程序。用户has_many帖子,帖子has_many评论和评论belongs_to用户和帖子。

在我的视图模板中,我循环遍历这样的评论以获取评论者的用户名:

User.find(comment.user_id).name

如果我为每个帖子的每个评论做这个,效率有多高? 我可以想象,将用户名存储在Comments表的单独行中可能会更快,但重复数据似乎是错误的。

我是偏执狂吗?ActiveRecord正在做一些缓存魔法,还是有更好的办法做这样的事情?

4 个答案:

答案 0 :(得分:0)

Eager loading of associations

class Post < ActiveRecord::Base
  has_many :comments
  # ...
end

class Comment < ActiveRecord::Base
  belongs_to :user
end


comments = @post.comments.includes(:user)

它会预先加载用户。

SQL将如下所示:

SELECT * FROM `comments` WHERE `comments`.`post_id` = 42;
SELECT * FROM `users` WHERE `users`.`id` IN (1,2,3,4,5,6) # 1,2,3,4,5,6 - user_ids from comments

答案 1 :(得分:0)

您可以在初始查询中预加载用户。 看到您在User和Comment之间建立了关联,您可以通过关联访问用户。

假设你有一个控制器方法:

def show
  @posts = Post.limit(10).includes(:comments => :user)
end

在您浏览@comments时的视图中:

@posts.each do |post|
  # show post stuff
  post.comments.each do |comment|
    comment.user.name
  end
end

答案 2 :(得分:0)

如果您拥有以下关联,则可以从评论对象本身comment.user

访问用户
class User < ActiveRecord::Base
  has_many :posts
  has_many :comments
end

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :post
end

答案 3 :(得分:0)

如果性能对您来说是一个问题,那么使用无关系数据库就像Mongodb一样。

如果你仍然想使用ActiveRecord,你可以使用Post.comments.include(:user)的热切加载(这会加载未使用的用户信息 - 这并不是很好),或者你可以使用缓存技术。

我发现只要您控制可能发生的更改,就可以按照建议在注释表中缓存user.name。您可以通过在User模型中设置回调来完成此操作:

after_save do |user|
  Comment.where(user_id: user.id).update_all(:username, user.name)
end

这种技术有点像数据库缓存,当然,你可以缓存HTML片段。并且注释块可以缓存HTML块。