java - Hibernate - SQL 很快,但查询仍然很慢

标签 java performance hibernate

我正在运行 Hibernate 4.1,并在 Oracle 12c 之上的 Hikari 池之上运行 Javassist 运行时检测。 JDK 是 1.7。

我有一个查询在数据库上运行得非常快,并在 Hibernate 中获取大约 500 个实体。根据 JProfiler 的说法,查询运行时间非常短,大​​约 11 毫秒,但 Query.list 总共运行大约 7 秒。

我尝试删除所有过滤器,它表明大部分时间都花在 Javaassist 和其他 Hibernate 相关的反射调用上(例如 AbstractProxyHandler 等)。我读到反射开销应该很小,但似乎不是,而且看起来太多了。

您能告诉一下这里的瓶颈是什么吗?

最佳答案

确保您正在检索的对象不具有作为 SELECT 延迟获取而不是作为 JOIN 急切获取的子对象。这可能会导致称为 SELECT N + 1 的行为,其中 Hibernate 最终运行一个查询以从各自的表中获取 500 个对象,然后对每个对象执行一个附加查询以获取子对象。如果您有 4 或 5 个关系作为每条记录的 SELECT 语句来获取,并且您有 500 条记录,那么您会突然运行大约 2000 个查询来获取列表。

我建议打开 Hibernate 的 SQL 日志记录以查看它正在运行哪些查询。如果在您获取列表时它转储出一个非常长的 SELECT 查询列表,请查看您的映射文件以了解您的关系是如何设置的。尝试将它们调整为 fetch="join"并查看这些查询是否消失以及性能是否有所提高。

以下是一些可能相关的 Stack Overflow 问题,可能能够提供更具体的详细信息。

Hibernate FetchMode SELECT vs JOIN

What is N+1 SELECT query issue?

关于分析器和其他类似工具的其他注意事项。通常,在跟踪性能问题时,特定的代码块会显示为花费最多时间的地方。人们往往会得出的常见结论是,所讨论的代码块速度很慢。就您而言,您似乎将 Hibernate 的反射代码视为花费时间的地方。重要的是要考虑到,这段代码本身实际上可能并不慢,但它是花费时间的地方,因为由于算法复杂,它被频繁调用。我发现在许多问题中,序列化或反射似乎很慢,而实际情况是代码用于与外部资源通信,并且该资源被调用了数千次,而实际上只应该调用少数几次。进行数千次查询来获取列表将导致您的采样显示大量时间花费在处理这些查询的代码上。请小心,不要将因设计/配置问题而经常调用的代码误认为是速度慢的代码。问题很可能不在于 hibernate 对反射的使用,因为反射通常不会慢到秒级。

关于java - Hibernate - SQL 很快,但查询仍然很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46410689/

相关文章:

java - 解释 JUnit 测试结果?

java - Selenium - Web 驱动程序等待

java - 如何将 getAssets().open(filename) 与 FileWriter 一起使用?

JavaFX 需要多个 ImageView 节点而不是对一个节点的引用?

c - glibc和相同代码的性能差异

mysql - "Packet for query is too large"在带有 mysql 的 java web 应用程序中

hibernate - 线程自旋等待时间以传递错误

android - 获取音频时出现性能问题

更新重复行的 MySql 查询非常慢。建议需要加快

hibernate - Tomcat 错误 [严重 : Error listenerStart] on accessing web application with Spring/Log4j/Hibernate/Ant?