Hibernate获取策略 - 何时使用“join”以及何时使用“select”?

时间:2009-03-05 23:22:51

标签: hibernate fetch

大多数Hibernate关联都支持“fetch”参数:

fetch="join|select"

“select”是默认值。

如何决定使用哪一种关联?

我尝试将所有内容从“选择”更改为“加入”应用程序范围 - 生成的查询数量减少了大约10倍,但性能保持完全相同(甚至变得更糟糕)。

感谢。

6 个答案:

答案 0 :(得分:41)

加入应该解决n + 1问题。如果您有10个父母,每个父母有10个孩子,则加入将需要一个查询,并且选择将需要11个(一个用于父母,一个用于每个父母的子女)。如果数据库与应用程序位于同一服务器上,或者网络速度非常快,那么这可能不是什么大问题,但如果每个数据库调用都有延迟,则可以相加。 join方法在初始查询上的效率稍差,因为您复制了每一行中的父列,但只进行了一次数据库往返。

一般来说,如果我知道我需要所有父母的孩子,我就会加入。如果我只需要几个父母的孩子,我会选择。

答案 1 :(得分:9)

选择将通过向数据库发出新查询来获取子项。 Join将通过将子项添加到父查询中来获取子项。这就是为什么你看到类似的性能,即使查询数量下降。

选择

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)

关于何时使用其中一个...不完全确定。它可能取决于数据库系统。如果一个总是比另一个好,我怀疑他们会费心给你选择!如果你看到每个人都有类似的表现,我就不用担心了。

答案 2 :(得分:2)

如果父母有很多孩子,而这些孩子又有很多孩子,那么在这种情况下,最初的孩子会加入'可能会扼杀网络。我的建议是使用' select'在这种情况下,拆分选择。

答案 3 :(得分:1)

<强>取= “加入” 如果你执行fetching =“join”,它将在一个select语句中检索所有信息。

<强>取= “选择” 如果你想要第二个select语句来获取相关的集合,那么你将使用fetch =“select”。

来源:Hibernate Fetching Strategies

答案 4 :(得分:1)

JOIN是首选,通常是出于性能原因。

使用SELECT的一个原因是,如果您是具有多对多关系的分页结果(设置偏移量和限制)。如果你使用JOIN,如果root实体包含多个多对多子节点并且那些“副本”计入你的限制(即使Hibernate在事后使用DISTINCT_ROOT_ENTITY将其折叠),它将多次出现。

答案 5 :(得分:0)

人们总是使用 fetch = JOIN 来讨论性能损失。但正如我所知,对我们来说理解我们正在获取的父/子记录的数量非常重要:

如果您只想获取单个父记录并且期望它没有多个孩子,那么我建议您使用 fetch = SELECT

如果你想获取所有父记录,包括其子记录,那么最好去 fetch = JOIN

只是添加一个注释,如果记录是懒洋洋地抓取孩子( lazy = true ),那么它就没有任何意义使用 fetch = JOIN 因为所有父记录和子记录都是一次性加载的。