Hibernate的获取策略 – 何时使用“连接”以及何时使用“select”?
大多数的Hibernate关联支持“fetch”参数:
fetch="join|select"
“select”是默认值。
如何决定哪个关联使用哪一个?
我尝试从“select”到“join”应用程序全部更改 – 生成的查询数量减less了大概10倍,但性能保持完全相同(甚至变得更糟糕)。
谢谢。
join应该是解决n + 1问题。 如果你有10个父母,每个有10个孩子,join将需要一个查询,select将需要11(父母一个,每个父母的孩子一个)。 如果数据库与应用程序位于同一台服务器上,或者networking速度非常快,但是如果每个数据库调用中存在延迟,则这可能不算什么大问题。 在初始查询中,连接方法的效率稍低一些,因为您要复制每一行中的父列,但只能往返一次数据库。
一般来说,如果我知道我将需要所有父母的孩子,我会join。 如果我只是需要less数父母的孩子,我使用select。
select将通过向他们的数据库发出一个新的查询来获取子项目。 join将通过将子项添加到父项的查询中来获取子项。 所以这就是为什么你看到类似的性能,即使查询数量下降。
select:
SELECT * FROM parent WHERE id=(whatever) SELECT * FROM child WHERE id=(parent.child.id)
join:
SELECT * FROM parent LEFT OUTER JOIN child ON parent.child.id=child.id WHERE parent.id=(whatever)
至于什么时候使用一个…不完全确定。 这可能取决于数据库系统。 如果一个总是比另一个好,我怀疑他们会麻烦给你select! 如果你看到每个类似的performance,我不会担心。
fetching =“join”如果您执行fetching =“join”,它将检索单个select语句中的所有信息。
fetching =“select”,如果你想paas第二个select语句来获取关联的集合,那么你将使用fetch =“select”。
来源: Hibernate提取策略
人们总是谈论使用fetch = JOIN的性能命中。 但是,正如我认为的,了解我们提取的父/母logging的数量对我们来说非常重要:
如果你只想获取单个父logging,并期望它没有多less孩子,那么我build议你使用fetch = SELECT 。
如果你想获取所有的父logging,包括它的孩子,那么最好去fetch = JOIN
只需要添加一个注释,如果logging是懒惰地获取子项( lazy = true ),那么使用fetch = JOIN就没有任何意义,因为所有的父子logging都是一次加载的。
如果父母有很多孩子,而这些孩子又有许多其他孩子,那么在这种情况下,最初的“join”可能会扼杀networking。 我的build议是在这种情况下使用“select”来拆分select。
由于性能原因,JOIN通常是优选的。
使用SELECT的一个原因是如果你是分页结果(设置一个偏移量和一个限制)有多对多的关系。 如果你使用JOIN,如果根实体包含多个多对多的孩子,那么这个根实体就会出现多次,而这些“副本”将会超出你的限制(即使Hibernate在事后使用DISTINCT_ROOT_ENTITY将其折叠)。