【问题标题】:Including associations optimization in Rails在 Rails 中包括关联优化
【发布时间】:2010-04-14 18:43:07
【问题描述】:

我正在寻求有关按需加载关联的 Ruby 优化方面的帮助。

这是一个简化的例子。我有 3 个模型:PostCommentUser。引用是:Post 有很多 cmets,Comment 引用了 User (:author)。现在,当我转到帖子页面时,我希望看到帖子正文 + 所有 cmets(以及他们各自的作者姓名)。这需要以下 2 个查询:

select * from Post -- to get post data (1 row)
select * from Comment inner join User -- to get comment + usernames (N rows)

在我的代码中:

Post.find(params[:id], :include => { :comments => [:author] }

但它没有按预期工作:正如我在后端看到的,仍然有 N+1 个命中(虽然其中一些被缓存了)。我该如何优化它?

UPD 经过一番调查,看起来代码是正确的,但如果我在 Comment 模型中命名了 belongs_to,它就不能按预期工作。一旦我从 :author 更改为 :user ,它就按预期工作了。

【问题讨论】:

    标签: ruby-on-rails optimization activerecord associations


    【解决方案1】:

    在我的项目中,我与您的 PostCommentUser 模型有类似的关系。我只看到三个实际的 sql 查询。

    Post.find(1, :include => { :comments => [:author] })
    

    从调试日志中它显示了这三个查询

    SELECT * FROM `posts` WHERE (`posts`.`id` = 1)
    SELECT `comments`.* FROM `comments` WHERE (`comments`.`post_id` = 1)
    SELECT * FROM `authors` WHERE (`authors`.`id` IN (4,8,15,16,23,42)) 
    

    【讨论】:

    • 我更新了,它改变了拉用户(作者)的方式,具体取决于我在 belongs_to 中的内容。
    • 您是否调查过如何通过创建日期描述来订购 cmets?
    • 所以你的意思是这个?:Post.find(1, :include => {:cmets => :author}, :order => 'cmets.created_at desc')
    • 不完全是:它将此查询转换为内部联接而不是附加查询,并且不包括 cmets 的作者。
    【解决方案2】:

    如果您对 2/3 查询感到满意,可以尝试:

    @post = Post.find params[:id]
    @comments = Comments.find_by_post_id(params[:id], :include => [:author])
    

    @comments = @post.comments(:include => [:author])
    

    编辑:您是否尝试过:

    Post.find(params[:id], :include => { :cmets => :author }

    【讨论】:

    • 我在最后一个变体中做得对,但仍然看到它单独加载作者(按 cmets 的数量多次访问数据库)。
    • guides.rubyonrails.org/…,看起来你可以嵌套包含
    • @Corey - 是的,正如您在我的问题中看到的那样,我一直在关注这篇文章,但这并没有按预期工作。
    • @vlad - 你是否调查过如何通过创建日期描述来订购 cmets?
    • @post.cmets(:include => [:author], :order => 'created_at DESC')
    猜你喜欢
    • 2012-03-05
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多