org.hibernate.Query #list是随机慢的

时间:2014-01-31 09:15:57

标签: sql-server hibernate

调用org.hibernate.Query#list的方法存在性能问题。方法调用的持续时间随着时间的推移而变化:它通常持续大约一秒钟,但有些天,可能是半天,大约需要20秒。

如何解决此问题?如何确定此问题的原因?

分析此问题的更多元素:

  • 在生产环境中已发现性能问题,但所述问题出现在测试环境中。
  • 该问题至少已持续数周,但其起源日期尚不清楚。
  • 基础查询是MS SQL Server(2008 R2)中的视图(选择):
    • 此测试环境中的数据库读取/写入仅来自少数用户:数据库服务器不应过度解决,数据只会随着时间的推移而缓慢变化。
    • 直接从MS SQL Server客户端执行确切查询始终只需不到一秒钟。
    • 复制数据库(使用MS SQL Server客户端备份数据库并将此备份还原为新数据库)不允许重现问题:方法调用导致复制快速。
  • 该应用程序使用Hibernate(4.2.X)和Java 6。
    • 从Hibernate 3.5升级到4.2并没有改变任何问题。
    • 方法调用始终使用相同的参数:有一个执行操作的测试方法。
    • 分析方法调用(使用hprof)表明,当它很长时,大部分时间都花在“Object.wait”和“ref.ReferenceQueue.remove”上。
    • 在方法调用期间使用log4jdbc记录基础查询持续时间会显示以下结果:
      • 查询< 1s =>方法〜1s
      • query~3s =>方法〜20s
  • 查询生成POJO,如this issue中最常投票的答案中所述。
  • 我没有尝试过使用具有所有属性的构造函数,如this other similar issue中最高投票的答案中所述,因为我不明白会产生什么样的影响。

2 个答案:

答案 0 :(得分:0)

使用Hibernate查询显然随机缓慢的一个可能原因是刷新会话。如果同一事务中的某些语句(插入,更新,删除)未刷新,则Query的list方法可能会执行autoflush(取决于当前的刷新模式)。如果是这种情况,性能问题可能甚至不会由调用list()的查询引起。

答案 1 :(得分:0)

似乎问题在于MS SQL Server和程序计划的更新:在DBCC FREEPROCCACHE之后,DBCC DROPCLEANBUFFERS的查询和方法时间是一致的。

该问题的解决方案可能是升级MS SQL Server:升级到MS SQL Server 2008 R2 SP2导致问题不再出现。

查询的持续时间与方法的持续时间之间的差异似乎是与返回的对象相关的指数因子:大部分时间花费在结果集的套接字读取上。