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

问题描述:

我正在运行Hibernate 4.1,并在Hikari池顶部运行Javassist运行时检测程序,并在Oracle 12c之上运行。 JDK是1.7。Hibernate - SQL速度很快,但查询速度仍然很慢

我有一个查询,在数据库上运行得非常快,并在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”,并查看这些查询是否消失以及性能是否提高。

这里有一些可能相关的堆栈溢出问题,可能能够提供更具体的细节。

Hibernate FetchMode SELECT vs JOIN

What is N+1 SELECT query issue?

别的东西需要注意分析器和这种性质的其他工具。通常,在追踪性能问题时,特定的代码块会显示为最耗时的地方。人们倾向于跳到的共同结论是,所讨论的代码块很慢。就你而言,你似乎将Hibernate的反射代码视为时间消耗的地方。考虑到这个代码本身实际上可能并不慢,但是这是花费时间的地方,因为由于算法复杂度而被频繁地调用是非常重要的。我发现在很多问题中,序列化或反射出现会变慢,当现实是代码被用来与外部资源进行通信时,并且该资源被称为1000次的时候,它应该只被称为一小撮。让1000个查询获取您的列表将导致您的抽样显示在处理这些查询的代码中花费了大量时间。注意不要因为代码的设计/配置问题而导致经常调用的代码很慢,这个问题很可能不在于hibernate使用反射,因为反射通常不会在秒级上慢。

+0

我打开了SQL日志记录,它只有一个查询,所有相关的集合都是连接获取或未访问。我的猜测是,反射可能不会很慢,但由于反射调用的次数,它会扭曲分析器结果。尽管如此,我仍然无法找到问题的根源,甚至将我的实体简化为最低限度。它基本上是两个常规字段,几个用户类型字段,一个多对一集合,就是这样。 –