Rails包含方法何时添加

Rails includes method when to add

所以我已经阅读了很多关于 rails includes 方法的内容,但我仍然对使用它的最佳情况感到困惑。

我有一个情况,我有一个 user 记录,然后这个用户与多个模型相关,例如 clientplayergameteam_playerteamserverserver_center.

我需要在视图中显示相关模型的特定属性。我只需要特定模型的大约 1-2 个属性,我不使用其他属性。

我已经添加了 delegates 例如从 player 得到 server.name 我可以使用 server_name 但在这种情况下我 include 所有我需要从中获取属性的表,或者我还需要做其他事情,因为我只需要模型中的几个属性。

我目前的查询如下:

@user_profile = User
               .includes({:client => [:player, :team_player => [:team]]}, 
                        :game, 
                        {:server_center => :server})
               .where(game_id: @master.admin.games)

Includes 确保使用尽可能少的查询数加载所有指定的关联。

假设我们有两个名为 UserProfile 的模型:

class User < ActiveRecord::Base
  has_one :profile
end

class Profile < ActiveRecord::Base
  belongs_to :user
end

如果我们遍历每个 users 并显示每个用户的名称,名称字段位于 Profile 模型中,该模型与 User 模型,我们通常每次都必须使用单独的数据库查询来检索名称。但是在使用includes方法的时候,已经预先加载了关联的人table,所以这个block只需要一个query。

不包括:

users = User.all
users.each do |user|
  puts user.profile.name # need extra database query for each time we call name
end

包含

# 1st query to get all users 2nd to get all profiles and loads to the memory
users = User.includes(:profile).all
users.each do |user|
  puts user.profile.name # no extra query needed instead it loads from memory.
end

Eager Loading用于防止N+1查询问题。基本上它执行 left outer join,这在加快请求响应或优化查询方面起着重要作用。例如:如果我们有大量用户,如果我们想遍历这些用户及其相应的个人资料。我们将访问数据库的时间不等于用户数量。但是如果我们使用 include,它会在稍后迭代用户时将所有配置文件保存到内存中,它将从该内存中获取而不是查询。

预加载 可能并不总是解决我们 N+1 查询 的最佳方法,例如:如果您正在处理一些复杂的查询最好寻找一些缓存解决方案,例如 Russian Doll 缓存 等。这两种方法仍然各有利弊,最终由您决定最佳方法。

一个有助于检测 N+1 查询的有用 gem 是 bullet