【问题标题】:Hibernate fetching strategy - when to use "join" and when to use "select"?Hibernate 获取策略 - 何时使用“加入”以及何时使用“选择”?
【发布时间】:2010-10-11 15:44:07
【问题描述】:

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

fetch="join|select"

“选择”是默认值。

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

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

谢谢。

【问题讨论】:

  • Join 将在单个 select 语句中检索所有信息,而在另一种情况下,如果您执行 fetching="select" Hibernate 将传递第二个 select 语句以获取关联的集合,除非您通过禁用延迟获取指定lazy="false" 你可以在这里找到更多细节javawebtutorial.blogspot.in/2013/09/…

标签: hibernate fetch


【解决方案1】:

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)

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 嗯,我在生产环境中尝试过(我们有带从属服务器的远程数据库服务器),行为保持不变——比“选择”稍差一点。为了帮助解决 n+1 问题,我们使用了“default_batch_fetch_size”,因此它将分批运行选择查询,而不是一个一个地运行。
    【解决方案3】:

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

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

    来源:Hibernate Fetching Strategies

    【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            猜你喜欢
            • 2012-04-19
            • 1970-01-01
            • 2020-09-29
            • 2011-09-22
            • 1970-01-01
            • 1970-01-01
            • 2023-04-11
            • 2013-05-10
            • 2011-02-22
            相关资源
            最近更新 更多