Ruby on rails RubyonRails 5中的include(:associations)、references(:associations)和eager_load(:associations)之间有什么区别吗?

Ruby on rails RubyonRails 5中的include(:associations)、references(:associations)和eager_load(:associations)之间有什么区别吗?,ruby-on-rails,activerecord,ruby-on-rails-5,Ruby On Rails,Activerecord,Ruby On Rails 5,它似乎包括(:关联)。引用(:关联)和渴望加载(:关联)执行与Rails 5中的SQL(左外连接)完全相同。那么什么时候我需要使用包含(:关联)。引用(:关联)语法 比如说, Parent.includes(:children1, :children2).references(:children1).where('(some conditions of children1)') Parent.includes(:c1, :c2, :c3).references(:c1).to_sql 可以转

它似乎
包括(:关联)。引用(:关联)
渴望加载(:关联)
执行与Rails 5中的SQL(左外连接)完全相同。那么什么时候我需要使用
包含(:关联)。引用(:关联)
语法

比如说,

Parent.includes(:children1, :children2).references(:children1).where('(some conditions of children1)')
Parent.includes(:c1, :c2, :c3).references(:c1).to_sql
可以转换为

Parent.eager_load(:children1).preload(:children2).where('(some conditions of children1)')
我认为后者(使用
eager\u load
preload
进行查询)更简单,看起来更好

更新

我在我的环境中发现了一个奇怪的行为(
rails 5.2.4.3

即使当我
包括
多个关联和
引用
仅其中一个时,我包括的所有关联都是
左外连接
ed

比如说,

Parent.includes(:children1, :children2).references(:children1).where('(some conditions of children1)')
Parent.includes(:c1, :c2, :c3).references(:c1).to_sql
执行一个SQL,该SQL将
左外部联接
s所有c1、c2、c3。
我以为它只连接c1。

事实上,
包含
+
引用
最终与
渴望加载
相同。与Rails中的许多事情一样,您有几种方法可以实现相同的结果,在这里您亲眼目睹了这一点。如果我在一条语句中编写它们,我总是更喜欢
eager\u load
,因为它更显式,而且是一个单一的函数调用

我也更喜欢<代码> EyryLoad ,因为我认为<代码>引用< /代码>是一种黑客攻击。它对SQL生成器说:“嘿,我是以一种您不会检测到的方式引用这个对象的,所以请将它包含在JOIN语句中”,通常在您使用字符串作为查询的一部分传递SQL片段时使用

我唯一一次使用
includes(:associations).references(:associations)
语法是当它是使查询工作所需的工件而不是意图声明时。这是一个很好的例子:

Article.includes(:comments)。其中(“comments.visible=true”)。引用(:comments)
至于为什么引用1个关联会导致3个被加入,我不确定。
includes的代码使用试探法来决定何时使用联接更快,何时使用两个单独的查询更快,第一个用于检索父对象,第二个用于检索关联对象。我很惊讶地发现这是怎么回事。可能是因为查询无论如何都必须使用1个连接,因此算法认为使用1个大连接比使用3个查询更快,或者通常认为1个连接比4个查询更快


我一般不会使用
preload
,除非我有充分的理由相信它比
join
更快。我只想单独使用
包含
,由算法决定。

主要区别在于
.includes
试图巧妙地使用一组复杂的启发式方法来确定是在一个查询还是两个查询中加载记录。使用
.references
是导致其委托给
.eager\u load
的条件之一,这就是其加入
:c1,:c2,:c3
的原因。如果您预先知道您将要使用关联
。eager\u load
以直接的方式完成此工作。那么何时需要使用
包含(:关联)。引用(:关联)
语法?很可能永远不会,因为它将使用
。无论如何,渴望加载
。谢谢!当我使用散列将条件传递给includes查询时,我不知道我不需要
引用。(Rails指南:“像这样使用where只能在传递散列时起作用。”)