49

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

fetch="join|select"

“选择”是默认值。

如何决定将哪个用于哪个关联?

我尝试将所有应用程序范围从“选择”更改为“加入”——生成的查询数量可能减少了 10 倍,但性能保持不变(甚至变得更糟)。

谢谢。

4

6 回答 6

42

加入应该解决n+1问题。如果您有 10 个父母,每个父母有 10 个孩子,则 join 将需要一个查询,而 select 将需要 11 个(父母一个,每个父母的孩子一个)。如果数据库与应用程序在同一台服务器上,或者网络非常快,这可能没什么大不了的,但如果每次数据库调用都有延迟,它就会累加。join 方法在初始查询上的效率稍低,因为您在每一行中复制父列,但您只对数据库进行一次往返。

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

于 2009-03-06T05:14:43.257 回答
9

Select 将通过向数据库发出新查询来获取子项。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)

至于何时使用一个而不是另一个......不完全确定。它可能取决于数据库系统。如果一个总是比另一个更好,我怀疑他们会费心给你选择!如果你看到每个都有相似的性能,我不会担心。

于 2009-03-06T00:18:06.450 回答
2

如果父母有很多孩子,而这些孩子又有很多其他孩子,那么在这种情况下,最初的“加入”可能会阻塞网络。我的建议是在这种情况下使用“选择”来拆分选择。

于 2015-04-24T20:34:57.563 回答
1

fetching="join" 如果您执行 fetching="join",它将在单个 select 语句中检索所有信息。

fetching="select" 如果你想使用第二个 select 语句来获取关联的集合,那么你将使用 fetch="select"。

来源:休眠获取策略

于 2013-10-08T08:50:10.573 回答
1

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

使用 SELECT 的一个原因是,如果您要对具有多对多关系的结果(设置偏移量和限制)进行分页。如果您使用 JOIN,如果根实体包含多个多对多子实体,并且这些“副本”会超出您的限制(即使 Hibernate 在使用 DISTINCT_ROOT_ENTITY 事实后将它们折叠),它将出现多次。

于 2016-06-29T15:34:37.940 回答
0

人们总是谈论使用fetch=JOIN对性能的影响。但我认为,了解我们正在获取的父/子记录的数量对我们来说很重要:

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

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

只是要补充一点,如果记录是懒惰地获取子项(lazy=true),那么使用fetch=JOIN没有任何意义,因为所有父项和子项记录都是一次性加载的。

于 2015-04-14T18:29:29.540 回答