我有一个Dashboard视图,它需要来自整个数据库的表的小数据集。我优化了数据库查询(例如删除的子查询)。现在有大约20个查询一个接一个地执行,它们从数据库中获取不同的数据集。大多数HQL查询包含GROUP BY
和JOIN
子句。使用Spring REST接口,结果将返回到前端。
如何优化自定义查询的执行?我最初的想法是并行运行数据库查询。但是我该如何实现呢?在做了一些研究后,我找到了注释@Async
,它可以并行运行方法。但这是否适用于Hibernate方法?是否始终为JpaRepository中使用@Query
注释的每个方法创建一个新的数据库会话?运行数据库查询是否会影响总体执行时间?
另一种并行运行数据库调用的方法是将Dashboard调用拆分为几个单独的Ajax调用(每个关注点都有自己的Ajax调用)。我不想这样做,因为每次打开仪表板(或者例如更改日期范围)时,都会进行另外20次Ajax调用以获取新数据。同样的问题仍然存在:并行运行SQL查询是否会影响数据库的执行时间?
我目前尚未向数据库添加其他索引。这将是下一件事,我肯定会这样做。但是,我对并行运行查询的性能影响以及如何使用Spring以编程方式实现这一点感兴趣。
我的项目最初是由jHipster(Spring Boot,MariaDB,AngularJS等)生成的。
答案 0 :(得分:6)
首先,并行运行这些SQL不会影响数据库,只会使页面加载速度加快,因此设计应该关注这一点。
我发布这个答案假设你已经确定你不能组合这20个SQL,因为数据是无关的(没有连接,视图等)。
我建议不要使用@Async有两个原因。
原因1 - 如果您想要解雇一堆任务并忘记,或者当您知道所有任务何时完成时,异步任务就很棒。因此,您需要“等待”完成所有异步任务。你要等多久?直到最慢的查询完成?
检查此示例代码是否为Async(来自指南@ spring.io - https://spring.io/guides/gs/async-method/)
// Wait until they are all done
while (!(page1.isDone() && page2.isDone() && page3.isDone())) {
Thread.sleep(10); //10-millisecond pause between each check
}
您的服务组件是否应该等待20个异步DAO查询?
原因2 - 请记住Async只是作为一个线程产生任务。由于您将使用JPA,请记住实体管理器不是线程安全的。 DAO类将传播事务。以下是可能出现问题的示例 - http://alexgaddie.blogspot.com/2011/04/spring-3-async-with-hibernate-and.html
恕我直言,最好继续进行多次Ajax调用,因为这会使你的组件具有凝聚力。是的,您将拥有20个端点,但它们将具有更简单的DAO,更简单的SQL,易于单元测试,并且返回的数据结构将更容易由AngularJS小部件处理/解析。当UI触发所有20个Ajax调用时,仪表板将在准备好时加载各个小部件,而不是同时加载所有小部件。这将有助于您通过优化仪表板的较慢加载部分(可能是缓存,索引等)来扩展您的设计。聚合DAO调用只会使数据结构变得复杂,单元测试更加困难。
答案 1 :(得分:3)
通常,并行执行查询会快得多。如果您正在使用Spring数据并且没有配置任何特定的JPA提供程序(Hibernate)将创建一个连接池来存储与您的数据库的连接。我认为默认情况下Hibernate拥有10个连接,通过这样做,它准备并行执行10个查询。通过并行运行查询的速度要快多少取决于数据库和表/查询的结构。 我认为使用@Async并不是最好的做法。定义提供特定查询结果的20个REST端点是一种更好的方法。通过这样做,您可以为每个查询简单地创建Entity,Repository和RestEndpoint类。通过这样做,每个查询都被隔离,代码也不那么复杂。