ActiveRecord查询中“includes”和“preload”之间有什么区别?

时间:2012-08-14 05:38:49

标签: ruby-on-rails ruby activerecord

我很难找到ActiveRecord对象的includes()和preload()的比较。任何人都可以解释这种差异吗?

3 个答案:

答案 0 :(得分:54)

Rails有两种避免n + 1问题的方法。一个是创建一个基于连接的大型查询来引入您的关联,另一个涉及为每个关联创建一个单独的查询。

执行includes时,rails决定使用哪种策略。它默认为单独的查询方法(预加载),除非它认为您正在使用条件或顺序中的关联列。因为它只适用于连接方法,所以它使用它。

Rails的启发式方法有时会弄错,或者您可能有一个特定的理由选择一种方法而不是另一种方法。 preload(及其随播方法eager_load)允许您指定要让rails使用的策略。

答案 1 :(得分:1)

有关详细信息,请参阅this博客。

简而言之:

  

Preload在单独的查询中加载关联数据。

User.preload(:posts).to_a

# => SELECT "users".* FROM "users" SELECT "posts".* FROM "posts"  WHERE "posts"."user_id" IN (1)
  

包含将关联数据加载到单独的查询中   预紧力。但是它比preload 更聪明。但在某些情况下,它会结合查询。

如何包含更聪明?

我们不能在条件的地方使用帖子表。以下查询将导致错误。

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')

但我们可以使用查询的帖子表包含

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以获取数据的切换。它还应用了提供的条件。

答案 2 :(得分:-3)

正如apidoc所说“这个方法已被弃用或在最新的稳定版本上移动。此处显示的是最新的现有版本(v3.0.9)。”所以区别在于包括不弃用。