我正在运行Hibernate 4.1,在Hikari池之上,在Oracle 12c上运行Javassist运行时工具。JDK为1.7。
我有一个查询,它在数据库上运行得相当快,并在Hibernate中获取大约500个实体。根据JProfiler的说法,查询运行时非常小,约为11 ms,但Query.list总共运行约7秒。
我尝试过删除所有过滤器,这表明大部分时间都花在Javaassist和其他与Hibernate相关的反射调用上(比如AbstractProxyHandler等)。我读到反射开销应该是相当小的,但它似乎不是,它似乎是太多了。
能告诉我这里的瓶颈是什么吗?
发布于 2017-09-25 17:38:56
确保您要检索的对象没有子对象,这些子对象作为SELECT而不是JOIN被延迟地获取。这可能导致名为SELECT N+ 1的行为,其中Hibernate运行一个查询从各自的表中获取500个对象,然后对每个对象进行额外的查询以获取子对象。如果您有4或5个关系被作为每个记录的SELECT语句获取,并且您有500条记录,那么突然之间,您正在运行大约2000条查询以获得列表。
我建议打开Hibernate的SQL日志,看看它正在运行哪些查询。如果在获取列表时,它转储出一个非常长的SELECT查询列表,请查看映射文件以查看如何设置关系。尝试将它们调整为一个fetch=“联接”,看看这些查询是否消失,以及性能是否有所提高。
以下是一些可能相关的堆栈溢出问题,可以提供更具体的细节。
Hibernate FetchMode SELECT vs JOIN
What is N+1 SELECT query issue?
还有一些关于分析器和其他类似工具的需要注意的地方。通常,在跟踪性能问题时,某个特定的代码块会显示为花费最多时间的地方。人们通常倾向于跳过的结论是,所讨论的代码块是缓慢的。在您的例子中,您似乎是在观察Hibernate的反射代码,因为它是花费时间的地方。非常重要的是要考虑到这段代码本身可能并不是很慢,但是由于算法的复杂性,这是花费时间的地方,因为它经常被调用。我发现,在许多问题中,序列化或反射似乎很慢,而实际情况是,代码用于与外部资源通信,而该资源被调用1000 s,而它只应该被称为少数几个。进行1000 s的查询来获取您的列表将导致您的抽样结果,表明在处理这些查询的代码中花费了大量时间。注意,不要将经常由于设计/配置问题而被调用的代码误认为是缓慢的代码。问题很可能不在于hibernate对反射的使用,因为反射通常不会按秒的顺序缓慢。
https://stackoverflow.com/questions/46410689
复制相似问题