【问题标题】:How does Rails handle a has_many when query uses includes?当查询使用包含时,Rails 如何处理 has_many?
【发布时间】:2014-05-28 01:12:21
【问题描述】:

如果我有一个包含许多帖子的用户模型,Rails 将在以下场景中对数据库执行多少次查询?

class User
  has_many :posts

  # this is the main method in question...
  def has_posted?
    posts.any? {|p| p.posted? }
  end
end

# has an attr "posted" which is a boolean
class Post
  belongs_to :user
end


# some controller
users = User.includes(:posts).all


# in the view
<% users.each do |user| %>
  <%= 'posted!' if user.has_posted? %>
<% end %>

当我在has_posted? 方法中循环返回的帖子以防止对每个用户的帖子表进行多次查找时,我在初始查询中使用includes 的事实是否有任何魔力?

【问题讨论】:

    标签: ruby-on-rails ruby database performance


    【解决方案1】:

    当我在 has_posted 中循环返回的帖子时,我在初始查询中使用包含这一事实是否有任何魔力?防止对每个用户的帖子表进行多次查找的方法?

    是的。

    如果您不使用.includes(),您将获得所谓的 N+1 查询。 IE。必须查找第一项,然后再查找 N 项。使用.includes() 将在执行时将帖子对象急切地加载到内存中。执行时间将在您调用执行查询的点...在您使用has_posted? 方法的示例中,执行点将是posts.any?

    更新

    但是,这里有一个更好的方法来做到这一点!即使用数据库查询,而不是通过使用 ruby​​ 循环访问一组帖子。像这样:

    class User
      def has_posted?
        posts.is_posted.any?
      end
    end
    
    class Post
      scope :is_posted, -> { where(posted: true) }
    end
    

    以这种方式,您可以让数据库只选择那些将posted 设置为true 的帖子。然后.any? 会将查询转换为 COUNT 查询,瞧! (在控制台上运行它并观察每种方法生成的查询。)

    【讨论】:

    • 我对“两个示例”感到困惑,直到我意识到我在视图中输入了错误的方法名称。你能修改你的答案以匹配我的更新吗?感谢关于 N+1 的解释。
    • 天哪,我不知道 any? 是 AR 查询集的一部分。太漂亮了。
    • 在 ruby​​/rails 中,如果您觉得某些东西应该存在,那么它可能确实存在 :) -- 一定会喜欢它。
    猜你喜欢
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多