首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails 5中的includes(:associations).references(:associations)和eager_load(:associations)之间有什么区别吗?

Rails 5中的includes(:associations).references(:associations)和eager_load(:associations)之间有什么区别吗?
EN

Stack Overflow用户
提问于 2020-07-16 08:31:36
回答 1查看 66关注 0票数 2

似乎includes(:associations).references(:associations)eager_load(:associations)在Rails 5中执行的 SQL (左外部联接)完全相同。那么,我什么时候需要使用includes(:associations).references(:associations)语法呢?

例如,

代码语言:javascript
复制
Parent.includes(:children1, :children2).references(:children1).where('(some conditions of children1)')

可以转换为

代码语言:javascript
复制
Parent.eager_load(:children1).preload(:children2).where('(some conditions of children1)')

我认为后者(使用eager_loadpreload的查询)更简单,看起来更好。

更新

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

即使当我includes几个关联,而references只有其中一个,所有的,我包括的关联是LEFT OUTER JOIN编辑的。

例如,

代码语言:javascript
复制
Parent.includes(:c1, :c2, :c3).references(:c1).to_sql

执行LEFT OUTER JOIN的所有c1、c2、c3的SQL。我以为它只加入了c1。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-20 23:35:35

实际上,includes + references最终与eager_load相同。就像Rails中的许多东西一样,您有几种实现相同结果的方法,在这里您可以亲眼目睹这一点。如果我是在一个语句中编写它们,我总是倾向于使用eager_load,因为它更显着,而且它是一个函数调用。

我也更喜欢eager_load,因为我认为references是一种黑客。它对SQL生成器说:“嘿,我指的是这个对象,在其他情况下您不会检测到,所以将它包含在JOIN语句中”,并且通常在使用字符串作为查询的一部分传递SQL片段时使用它。

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

代码语言:javascript
复制
Article.includes(:comments).where("comments.visible = true").references(:comments)

至于为什么引用1关联会导致3被加入,我不确定。includes的代码使用启发式来决定何时使用联接更快,何时使用两个单独的查询更快,第一个查询用于检索父查询,第二个查询用于检索关联对象。我惊讶地发现通常使用两个单独的查询更快。是怎么做到的。可能因为查询必须使用1 join,算法认为使用1大连接比使用3查询更快,或者一般认为1 join比4查询更快。

我一般不会使用preload,除非我有充分的理由相信它比join更快。我只需要使用includes,然后由算法来决定。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62930672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档