簡體   English   中英

Rails 5 上的 Ruby 中的 includes(:associations).references(:associations) 和 eager_load(:associations) 之間有什么區別嗎?

[英]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_loadpreload查詢)更簡單,看起來更好。

更新

我在我的環境中發現了一個奇怪的行為( 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM