大多數休眠協會支持「提取」參數:Hibernate抓取策略 - 何時使用「加入」以及何時使用「選擇」?
fetch="join|select"
以「選擇」爲默認值。
如何決定哪一個用於哪個關聯?
我試着從「選擇」到「加入」應用程序範圍內的所有更改 - 生成的查詢數減少了大概10倍,但性能保持完全相同(甚至變得更糟)。
謝謝。
大多數休眠協會支持「提取」參數:Hibernate抓取策略 - 何時使用「加入」以及何時使用「選擇」?
fetch="join|select"
以「選擇」爲默認值。
如何決定哪一個用於哪個關聯?
我試着從「選擇」到「加入」應用程序範圍內的所有更改 - 生成的查詢數減少了大概10倍,但性能保持完全相同(甚至變得更糟)。
謝謝。
加入應該解決n + 1問題。如果你有10個父母,每個有10個孩子,加入將需要一個查詢,選擇需要11個(父母一個,每個父母的孩子一個)。如果數據庫與應用程序位於同一臺服務器上,或者網絡速度非常快,但這可能不是什麼大問題,但如果每個數據庫調用都存在延遲,則可能會加起來。連接方法在初始查詢時效率稍低一些,因爲您要複製每一行中的父列,但是隻能進行一次往返數據庫。
一般來說,如果我知道我將需要所有父母的孩子,我會加入。如果我只需要一些父母的孩子,我就用select。
嗯,我試過它的生產(我們有遠程數據庫服務器與奴隸)和行爲保持準確相同 - 比「選擇」要差一點點。爲了幫助解決n + 1問題,我們使用「default_batch_fetch_size」,因此它會批量運行select查詢,而不是逐個查詢。 – serg 2009-03-06 17:17:30
選擇將通過向數據庫發出一個新查詢來獲取子項。加入將通過將子項添加到父項查詢中來獲取子項。所以這就是爲什麼你看到類似的性能,即使查詢數量下降。
選擇:
SELECT * FROM parent WHERE id=(whatever)
SELECT * FROM child WHERE id=(parent.child.id)
加入:
SELECT *
FROM parent
LEFT OUTER JOIN child ON parent.child.id=child.id
WHERE parent.id=(whatever)
至於何時使用一個比其他...不整肯定。它可能取決於數據庫系統。如果一個總是比另一個好,我懷疑他們會麻煩給你選擇!如果你看到每個類似的表現,我都不會擔心。
fetching =「join」 如果您執行fetching =「join」,它將檢索單個select語句中的所有信息。
取=如果你想PAAS第二個SELECT語句來獲取相關的收集比在這種情況下,您將使用提取=「選擇」,「選擇」 。
人們總是在談論使用取= JOIN性能損失。但正如我認爲,瞭解我們提取的父/母記錄的數量非常重要:
如果您只想獲取單個父記錄並期望它沒有多少孩子,那麼我會建議你可以使用fetch = SELECT。
如果你想獲取所有的父記錄,包括它的孩子,那麼這將是更好的去取= JOIN
我想補充一個需要注意的是,如果記錄懶洋洋地獲取兒童(爲lazy = true),那麼使用fetch = JOIN是沒有任何意義的,因爲所有的父和子記錄都是一次性加載的。
如果父母有很多孩子,而這些孩子又有許多其他孩子,那麼在這種情況下,最初的「加入」可能會窒息網絡。我的建議是在這種情況下使用'select'來分割選擇。
爲了性能的原因,JOIN通常是優選的。
使用SELECT的一個原因是如果您是分頁結果(設置偏移量和限制),它們具有多對多的關係。如果使用JOIN,如果根實體包含多個多對多子代,並且這些「副本」計數超出限制(即使Hibernate使用DISTINCT_ROOT_ENTITY事實摺疊它們),它將出現多次。
如果您執行fetching =「select」,join將在單個select語句中檢索所有信息,除非您通過指定lazy =「false」來禁用懶惰讀取,否則Hibernate將傳遞第二個select語句以獲取關聯集合「你可以在這裏找到更多的細節http://javawebtutorial.blogspot.in/2013/09/hibernate-fetching-strategies.html – user528050 2013-10-08 08:45:10