我正在努力寻找 ActiveRecord 对象的 include() 和 preload() 的比较。谁能解释其中的区别?
问问题
15800 次
3 回答
79
Rails 有两种方法可以避免 n+1 问题。一个涉及创建一个基于大连接的查询来拉入您的关联,另一个涉及对每个关联进行单独的查询。
当你这样做时,includes
rails 决定为你使用哪种策略。它默认为单独的查询方法(预加载),除非它认为您正在使用您的条件或顺序中的关联列。因为这只适用于连接方法,所以它使用它。
Rails 的启发式方法有时会出错,或者您可能有特定原因偏爱一种方法而不是另一种方法。preload
(及其配套方法eager_load
)允许您指定您希望 Rails 使用的策略。
于 2012-08-14T07:02:29.760 回答
6
有关详细了解,请参阅此博客。
简而言之:
Preload 在单独的查询中加载关联数据。
User.preload(:posts).to_a
# => SELECT "users".* FROM "users" SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1)
包括在单独的查询中加载关联数据,就像预加载一样。但是它比.
preload
但在某些情况下,它结合了查询。
包含如何更智能?
我们不能在 where 条件下使用 post 表。以下查询将导致错误。
User.preload(:posts).where("posts.desc='ruby is awesome'")
# =>
SQLite3::SQLException: no such column: posts.desc:
SELECT "users".* FROM "users" WHERE (posts.desc='ruby is awesome')
但是我们可以在 where 查询中使用 post 表和include
User.includes(:posts).where('posts.desc = "ruby is awesome"').to_a
# =>
SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "posts"."id" AS t1_r0,
"posts"."title" AS t1_r1,
"posts"."user_id" AS t1_r2, "posts"."desc" AS t1_r3
FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
WHERE (posts.desc = "ruby is awesome")
如您所见,包括从使用两个单独的查询到创建单个 LEFT OUTER JOIN 以获取数据的切换。它还应用了提供的条件。
于 2018-03-07T06:26:45.327 回答
-6
正如 apidoc 所说,“此方法已被弃用或在最新的稳定版本上移动。最后一个现有版本(v3.0.9)显示在这里。” 所以不同之处在于包括不被弃用。
于 2012-08-14T05:58:48.583 回答