Rails包含方法何时添加
Rails includes method when to add
所以我已经阅读了很多关于 rails includes
方法的内容,但我仍然对使用它的最佳情况感到困惑。
我有一个情况,我有一个 user
记录,然后这个用户与多个模型相关,例如 client
、player
、game
、team_player
、team
、server
和 server_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 确保使用尽可能少的查询数加载所有指定的关联。
假设我们有两个名为 User 和 Profile 的模型:
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
所以我已经阅读了很多关于 rails includes
方法的内容,但我仍然对使用它的最佳情况感到困惑。
我有一个情况,我有一个 user
记录,然后这个用户与多个模型相关,例如 client
、player
、game
、team_player
、team
、server
和 server_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 确保使用尽可能少的查询数加载所有指定的关联。
假设我们有两个名为 User 和 Profile 的模型:
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