似乎includes(:associations).references(:associations)和eager_load(:associations)在Rails 5中执行的 SQL (左外部联接)完全相同。那么,我什么时候需要使用includes(:associations).references(:associations)语法呢?
例如,
Parent.includes(:children1, :children2).references(:children1).where('(some conditions of children1)')可以转换为
Parent.eager_load(:children1).preload(:children2).where('(some conditions of children1)')我认为后者(使用eager_load和preload的查询)更简单,看起来更好。
更新
我在我的环境(rails 5.2.4.3)中发现了一种奇怪的行为。
即使当我includes几个关联,而references只有其中一个,所有的,我包括的关联是LEFT OUTER JOIN编辑的。
例如,
Parent.includes(:c1, :c2, :c3).references(:c1).to_sql执行LEFT OUTER JOIN的所有c1、c2、c3的SQL。我以为它只加入了c1。
发布于 2020-07-20 23:35:35
实际上,includes + references最终与eager_load相同。就像Rails中的许多东西一样,您有几种实现相同结果的方法,在这里您可以亲眼目睹这一点。如果我是在一个语句中编写它们,我总是倾向于使用eager_load,因为它更显着,而且它是一个函数调用。
我也更喜欢eager_load,因为我认为references是一种黑客。它对SQL生成器说:“嘿,我指的是这个对象,在其他情况下您不会检测到,所以将它包含在JOIN语句中”,并且通常在使用字符串作为查询的一部分传递SQL片段时使用它。
我使用includes(:associations).references(:associations)语法的唯一一次是,它是使查询工作所需的工件,而不是意图声明。导轨给出了这个很好的例子:
Article.includes(:comments).where("comments.visible = true").references(:comments)至于为什么引用1关联会导致3被加入,我不确定。includes的代码使用启发式来决定何时使用联接更快,何时使用两个单独的查询更快,第一个查询用于检索父查询,第二个查询用于检索关联对象。我惊讶地发现通常使用两个单独的查询更快。是怎么做到的。可能因为查询必须使用1 join,算法认为使用1大连接比使用3查询更快,或者一般认为1 join比4查询更快。
我一般不会使用preload,除非我有充分的理由相信它比join更快。我只需要使用includes,然后由算法来决定。
https://stackoverflow.com/questions/62930672
复制相似问题