Hibernate获取策略 - 何时使用“加入”何时使用“选择”?

StackOverflow https://stackoverflow.com/questions/617145

  •  03-07-2019
  •  | 
  •  

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

fetch="join|select"

with“select”是默认值。

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

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

感谢。

有帮助吗?

解决方案

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

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

其他提示

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

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

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

<强>取= QUOT;加入&QUOT; 如果你提取=&quot; join&quot;它将在一个选择语句中检索所有信息。

<强>取= QUOT;选取[ 如果你想要第二个select语句来获取相关集合,那么你将使用fetch =&quot; select&quot;。

来源: Hibernate获取策略

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

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top