ActiveRecord查询中“包含”和“预加载”之间的区别是什么?

我正在努力为ActiveRecord对象找到includes()和preload()的比较。 有人可以解释这个区别吗?

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

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

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

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

简而言之:

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

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

包括将关联数据加载到单独的查询中,就像预加载一样。 但它比preload 更聪明 。 但在某些情况下,它结合了查询。

怎么包括更聪明?

我们不能在where 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') 

但是我们可以使用 包含 查询的post表

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

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