[英]Is there any diferrence between includes(:associations).references(:associations) and eager_load(:associations) in Ruby on Rails 5?
似乎includes(:associations).references(:associations)
和eager_load(:associations)
) 在 Rails 5 中執行完全相同的SQL (LEFT OUTER JOIN)。所以我什么時候需要使用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
執行一個 SQL,其中LEFT OUTER JOIN
是 c1、c2、c3 的全部。 我以為它只加入c1。
實際上, includes
+ references
最終與eager_load
相同。 就像 Rails 中的許多事情一樣,您有幾種方法可以實現相同的結果,在這里您將親眼目睹。 如果我在單個語句中編寫它們,我總是更喜歡eager_load
,因為它更明確並且它是單個 function 調用。
我也更喜歡eager_load
,因為我認為references
是一種 hack。 它對 SQL 生成器說“嘿,我指的是這個 object 以一種您不會檢測到的方式,因此將其包含在 JOIN 語句中”並且通常在您使用字符串將 Z9778840A0101CB30C28 片段作為 Z9778840A0101B30C28 的一部分傳遞時使用查詢。
唯一一次我會使用includes(:associations).references(:associations)
語法是當它是使查詢工作所需的工件而不是意圖聲明時。 Rails 指南給出了這個很好的例子:
Article.includes(:comments).where("comments.visible = true").references(:comments)
至於為什么引用 1 個關聯會導致 3 個被 JOIN'ed,我不確定。 includes
的代碼使用啟發式方法來決定何時使用 JOIN 更快,何時使用 2 個單獨的查詢更快,第一個查詢檢索父對象,第二個檢索關聯對象。 我驚訝地發現使用 2 個單獨查詢的頻率更快。 可能是因為無論如何查詢都必須使用 1 個連接,算法認為使用 1 個大連接而不是 3 個查詢會更快,或者通常認為 1 個連接比 4 個查詢快。
我一般不會使用preload
,除非我有充分的理由相信它比join
更快。 我只會單獨使用includes
,讓算法決定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.