Java 设置setMaxResults时,JPA查询速度非常慢

Java 设置setMaxResults时,JPA查询速度非常慢,java,sql,oracle,hibernate,jpa,Java,Sql,Oracle,Hibernate,Jpa,在一个特定的项目中,我面临一个不同配置的类型化查询问题 在TypedQuery上设置大于查询返回的实际结果数的maxResults值时,getResultList需要很长时间才能执行,有时长达350秒才能检索到由6列组成的10行 相比之下,不带setMaxResults的同一查询执行大约需要15秒。同一个查询中的WHERE参数更改为检索更多的结果,速度也非常快 我正在使用资源本地数据源在Junit测试类中测试所有这些,但Weblogic 10.3.6上的JTA数据源以及Jboss EAP 6.1

在一个特定的项目中,我面临一个不同配置的类型化查询问题

在TypedQuery上设置大于查询返回的实际结果数的maxResults值时,getResultList需要很长时间才能执行,有时长达350秒才能检索到由6列组成的10行

相比之下,不带setMaxResults的同一查询执行大约需要15秒。同一个查询中的WHERE参数更改为检索更多的结果,速度也非常快

我正在使用资源本地数据源在Junit测试类中测试所有这些,但Weblogic 10.3.6上的JTA数据源以及Jboss EAP 6.1上也会发生同样的情况,但我认为这与此无关

我尝试在persistence.xml中使用hibernate.jdbc.fetch_size和hibernate.jdbc.wrap_result_集,但很难估计是否有改进:一旦查询成功并因此被Oracle缓存,无论我如何调整这些值,执行起来都很快,因为我没有清除Oracle语句缓存的特权

我注意到,如果从查询中删除orderby,执行时间将下降到50-60秒,这仍然太长,但仍然不足350秒。列是索引的,尽管它是主键,因此我不明白为什么它会对性能产生如此大的影响

我正在使用CriteriaAPI构建查询,但我也尝试使用HQL或本机SQL。我使用只检索所需字段,然后将结果分配给具有适当构造函数的类select new

以下是由Hibernate翻译的查询:

SELECT * FROM
  (SELECT message0_.MESG_ID  AS col_0_0_,
    message0_.CREATION_DATE  AS col_1_0_,
    messagetyp1_.MSGT_ID     AS col_2_0_,
    message0_.MESSAGE_NAME   AS col_3_0_,
    interview2_.INVW_ID      AS col_4_0_,
    interview2_.IVWT_ID      AS col_5_0_,
    party3_.LICENSE_USERNAME AS col_6_0_
  FROM  message0_
  LEFT OUTER JOIN S399_MESSAGE_TYPES messagetyp1_
  ON message0_.MSGT_ID=messagetyp1_.MSGT_ID
  LEFT OUTER JOIN S399_INTERVIEWS interview2_
  ON message0_.INVW_ID=interview2_.INVW_ID
  LEFT OUTER JOIN S399_PARTIES party3_
  ON message0_.PRTY_ID          =party3_.PRTY_ID
  WHERE message0_.CREATION_DATE>=?
  AND (interview2_.IS_POLLING  IS NULL
  OR interview2_.IS_POLLING     =0)
  ORDER BY message0_.MESG_ID DESC
  )
WHERE rownum <= ?
当我在SQLDeveloper中运行这个程序时,它应该是最快的,一般不到一秒钟

当我调试Hibernate的代码时,我可以看到ps.executeQuery上的org.Hibernate.jdbc.AbstractBatcher.getResultSetPreparedStatement异常缓慢。它应该把我引向JDBC驱动程序问题还是数据库问题

提前感谢您对这种情况的任何建议或想法

配置:

爪哇6 Hibernate 3.6.10 JPA 2.0试图升级到Hibernate 4和JPA 2.1,没有变化 Oracle数据库11g 11.1.0.7.0 Oracle jdbc驱动程序11.2.0.3已在11.1.0.7.0和11.2.0.4中试用,没有任何更改。 hibernate.方言:Oracle10g方言。 可能重复:

您可以尝试添加/*+第一行*/hint。如果没有帮助的话,你必须找出Hibernate实际执行的是什么

更新:您的查询需要查看多少MB数据?15秒的响应时间是否合理?你能提供一个关于这个问题的解释方案吗

查看查询,似乎应该在message0.CREATION\u日期上有一个索引。您可以尝试在where子句中提供一个上限。就像汤姆·凯茨经常说的。。。想想看!如果您在过去和现在的某个日期之间查询数据,并且没有传递上限SYSTIMESTAMP,那么您基本上希望数据库知道在日期列上使用该索引仍然是值得的。Oracle会做绑定参数窥视之类的事情——它甚至会查看您提供的边界的实际值,如果它认为这样成本更低,它可能会决定使用不同的查询计划


您知道ORDERBY是在where子句之后计算的吗?这意味着,您不会根据order by获得前n条记录,而是n条随机记录,然后对其进行排序……

我希望尽量避免使用提示,因为Hibernate不支持这些提示。此外,在本例中,当您说ORDERBY是在where子句之后计算的时候,我认为您是错的,因为我的查询使用了一个子查询select*from。。。其中rownum在内部查询中放置orderby很重要。我想知道,因为你原来的问题没有显示出来。