spring 引导存储库 findAll() 太慢
spring boot repository findAll() too slow
当我获取 table 用于报告目的时,我的新 spring 启动应用程序出现奇怪的缓慢。
这是一个简单的 table,没有引用其他 table,它有 5 列。行数为 50k。
所以,我使用简单的 findAll() 方法,它在 JpaRepository 中可用。
当“目标”结果为实体时,findAll() 执行需要 5 分钟。
当我设置 DTO class 投影或界面投影时,执行需要 1-2 分钟。
我认为这对于该数据量来说仍然太多了。
此外,hibernate 统计信息提供的执行时间为 0.5 秒。剩下的 1-2 分钟获取 DTO 类型的数据需要什么?
当然 serialization/deserialization 过程很麻烦,需要太多内存。您可以为此做很多事情:
- 增加应用程序的内存参数。请参阅 JVM 内存选项。
- 使用比默认 JDK 系统更能处理序列化 faster/better 的 java 库。 Jackson还不错
- 建立一个缓存系统来存储对象并更快地检索它们。您可以使用 Spring
@Cacheable
注释,@see https://www.baeldung.com/spring-cache-tutorial, or you can use Google guava 库来获得一个非常好的缓存系统。
- 优化您的数据模型以获得更快的速度 request/responses。请参阅使用 Fetch.EAGER / Fetch.LAZY diffs 加载对象以及如何为您的应用程序优化方法。
- 使用 Pagination John Thompson 解释得很好。这将是检索一小组结果并让用户在其中从 10 到 10 或 50 到 50 导航的更快方法。
- 使用 Redis 或 MongoDB 等 NoSQL 数据库为您的前端获取 JSON 个对象:https://www.mongodb.com/compatibility/spring-boot
使用分页示例,您可以在 spring 启动应用程序中快速显示数据集:
public interface ProductRepository extends PagingAndSortingRepository<Product, Integer> {
List<Product> findAllByPrice(double price, Pageable pageable);
}
来自 https://www.baeldung.com/spring-data-jpa-pagination-sorting 的起点代码,您可以按照说明使其运行良好,这无疑是让事情运行良好的最佳方式。
@Benda 给出了很好的指示,附加 jvisualvm 并使用 CPU 分析来查看时间花在哪里会很有帮助。由于行数很大,驱动程序通常会进行多次往返以获取大量数据以避免内存不足的情况,并且当它们被休眠加载时 - 它会累积在第一级缓存中。我曾经遇到过事务未标记为只读的情况,因此最后 Hibernate 试图进行脏检查以查看是否发生了某些变化。
另外,我建议您集成 Javamelody。它是免费的、开源的,并且使用 Spring Boot 非常容易设置(只需在构建中包含一个依赖项)。它可以告诉您在每个用例中花费的时间以及服务级别详细信息和 SQL 时间 - 所有这些都带有一个很好的可视化仪表板。
最后这个问题的解决方案是从 JPA 存储库更改为 JdbcTemplate。
我构建了一个查询,并且使用数据映射器参数,我可以将我的列表转换为 Java 中的 DTO 类型。
经过多次 JPA 查询试验后,速度令人难以置信。使用 JPA 时为 5 分钟,使用 JdbcTemplate.query() 时变为 2 秒。
毕竟我想知道从 Spring 4.3 到 Spring Boot 2.5.5
有什么变化
当我获取 table 用于报告目的时,我的新 spring 启动应用程序出现奇怪的缓慢。
这是一个简单的 table,没有引用其他 table,它有 5 列。行数为 50k。 所以,我使用简单的 findAll() 方法,它在 JpaRepository 中可用。
当“目标”结果为实体时,findAll() 执行需要 5 分钟。 当我设置 DTO class 投影或界面投影时,执行需要 1-2 分钟。
我认为这对于该数据量来说仍然太多了。
此外,hibernate 统计信息提供的执行时间为 0.5 秒。剩下的 1-2 分钟获取 DTO 类型的数据需要什么?
当然 serialization/deserialization 过程很麻烦,需要太多内存。您可以为此做很多事情:
- 增加应用程序的内存参数。请参阅 JVM 内存选项。
- 使用比默认 JDK 系统更能处理序列化 faster/better 的 java 库。 Jackson还不错
- 建立一个缓存系统来存储对象并更快地检索它们。您可以使用 Spring
@Cacheable
注释,@see https://www.baeldung.com/spring-cache-tutorial, or you can use Google guava 库来获得一个非常好的缓存系统。 - 优化您的数据模型以获得更快的速度 request/responses。请参阅使用 Fetch.EAGER / Fetch.LAZY diffs 加载对象以及如何为您的应用程序优化方法。
- 使用 Pagination John Thompson 解释得很好。这将是检索一小组结果并让用户在其中从 10 到 10 或 50 到 50 导航的更快方法。
- 使用 Redis 或 MongoDB 等 NoSQL 数据库为您的前端获取 JSON 个对象:https://www.mongodb.com/compatibility/spring-boot
使用分页示例,您可以在 spring 启动应用程序中快速显示数据集:
public interface ProductRepository extends PagingAndSortingRepository<Product, Integer> {
List<Product> findAllByPrice(double price, Pageable pageable);
}
来自 https://www.baeldung.com/spring-data-jpa-pagination-sorting 的起点代码,您可以按照说明使其运行良好,这无疑是让事情运行良好的最佳方式。
@Benda 给出了很好的指示,附加 jvisualvm 并使用 CPU 分析来查看时间花在哪里会很有帮助。由于行数很大,驱动程序通常会进行多次往返以获取大量数据以避免内存不足的情况,并且当它们被休眠加载时 - 它会累积在第一级缓存中。我曾经遇到过事务未标记为只读的情况,因此最后 Hibernate 试图进行脏检查以查看是否发生了某些变化。 另外,我建议您集成 Javamelody。它是免费的、开源的,并且使用 Spring Boot 非常容易设置(只需在构建中包含一个依赖项)。它可以告诉您在每个用例中花费的时间以及服务级别详细信息和 SQL 时间 - 所有这些都带有一个很好的可视化仪表板。
最后这个问题的解决方案是从 JPA 存储库更改为 JdbcTemplate。
我构建了一个查询,并且使用数据映射器参数,我可以将我的列表转换为 Java 中的 DTO 类型。 经过多次 JPA 查询试验后,速度令人难以置信。使用 JPA 时为 5 分钟,使用 JdbcTemplate.query() 时变为 2 秒。
毕竟我想知道从 Spring 4.3 到 Spring Boot 2.5.5
有什么变化