【问题标题】:In Hibernate, how to avoid the N+1 query problem and large results sets due to multiple joins在Hibernate中,如何避免N+1查询问题和多连接导致的大结果集
【发布时间】:2022-01-19 19:05:15
【问题描述】:

我正在使用 Spring Boot 和 Hibernate。

一些复杂的逻辑,由业务决定,需要使用各种嵌套字段,这些字段遍历各种DB关系(同样有一些是NxN、Nx1、1xN、1x1)。

遇到了N+1的问题,一开始是用HQL解决的,但是有些查询需要多次join,结果集变得无法管理。

我开始研究一个自定义实用程序,该实用程序收集需要获取的事物的 id,一次获取所有内容,然后使用 setter 填充起始对象上的字段。此实用程序适用于多对一关系,但对于多对多关系仍然效率低下,因为当我收集 id 时它会退回到 N+1 问题(因为它通过 getter 对每个对象查询连接表一次)。

我该如何解决这个问题?这个问题真的还没有解决吗?我是否遗漏了一些自动解决此问题的明显设置?

编辑: 我做了一个带有一些评论的玩具示例:https://github.com/marcotama/n-1-queries-example

【问题讨论】:

  • 你应该阅读“Spring boot persistence Best Practice (Anghel Leonard)”。这本书包含了关于休眠调优的非常好的推荐。我知道了很多陷阱。
  • 您能否发布一个您尝试执行的 SQL 查询示例?这样就更容易提出解决方案(就像fixing MultipleBagFetchException)。
  • @StefanGolubović 我添加了一个例子

标签: java spring performance hibernate jpa


【解决方案1】:

我遇到过同样的情况,我有 3 种方法来解决它;

  1. 增加依赖属性的 fetchsize 以便批量执行查询
  2. 为此目的编写自定义查询
  3. 定义实体图关系并根据属性映射

我个人更喜欢第 3 个选项,因为这样做很方便,并且使用 Spring Data JPA 更简洁。

您可以参考以下答案中的 cmets 示例:

【讨论】:

  • 实体图仍然会创建一个大的连接查询,对吗?
  • @marcotama 是的,在运行时它会创建一个大查询
【解决方案2】:

自行编写获取逻辑。 例如,您的作者有书,author_devices 您可以加入获取作者与书籍。你可以使用存储库“where author_id IN (authorsList.stream().map(author.getId())”单独获取 author_devices。比你应该分离作者并迭代 author_devices 并将其分配给适当的作者设备列表。我认为它只是对于需要加入-获取超过 1 个关系的情况的适当解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多