Hibernate参数化sql查询慢和活动的oracle会话

关于Oracle数据库的hibernate查询,我一直在苦苦挣扎几天。 这样的东西用于将记录提供给网格。

SELECT fields FROM tables and JoinedTables WHERE Field1 >= :value1 AND Field2 = :value2 AND Field3 = :value3 Order By MaintTable.Id Desc 

在Spring Java + Hibernate 4.2方法中使用这种方法。

 SQLQuery query = (SQLQuery) session.createSQLQuery(querySql) .addEntity(CertificateViewEnt.class) .setParameter("value1", firstCertificateRecordDate) .setParameter("value2", certType.toUpperCase()) .setParameter("value3", deleted? 1:0); 

每个过滤的字段都被正确编入索引并在Maintable.Id Descendent上创建一个函数索引以提高性能。

起初我以为是会话/连接池没有被正确管理,所以我改为StatelessSession并添加了这个session.close():

 query.setCacheable(false) .setTimeout(30) .setReadOnly(true); ... ... //Pagination query.setMaxResults(rows); query.setFirstResult(HelperMethod(page, rows)); result = (List) query.list(); session.close(); return result; 

它没有解决它。 查询运行好几次,但由于某些未知原因,并且使用之前已成功运行的值,挂起,在Oracle中打开会话(status = ACTIVE)并在超时时失败。 在任何SQL客户端上针对Oracle运行相同的查询,并且使用所有可能的params组合进行数十次执行,具有极高的性能,大约400ms,一次10个记录。

在这里和那里阅读了一些文章后,Link1 [ Hibernate + Java上的性能降低但是当我使用TOAD时使用相同的本机Oracle查询 Link2:[ 查询挂起oracle 10g]

我怀疑Hibernate使用的QueryPlan很差,并决定使用绑定参数删除所有filter并且也没有解决,尽管它有点好一些。 一段时间后,当他搬到其他页面时,例如Page 1,2,3,4 ……

毕竟,我怀疑Hibernate的方法生成的SQL

 query.setMaxResults(rows) query.setFirstResult(SomeHelperMethod(page, rows)); 

因为在日志中看到它们作为绑定参数传递给Oracle。

  ... Order By Certificado.Id Desc ) row_ where rownum  ? 

我也在跟踪日志中看到了这一点

 2015-09-15 14:09:53 TRACE QueryPlanCache:200 - Located native-sql query plan in cache (SELECT /*+ INDEX( 

和这个:

 2015-09-15 14:09:53 TRACE BasicBinder:84 - binding parameter [2] as [VARCHAR] - E 2015-09-15 14:09:53 DEBUG Loader:2031 - bindNamedParameters() 0 -> deleted [3] 2015-09-15 14:09:53 TRACE BasicBinder:84 - binding parameter [3] as [INTEGER] - 0 2015-09-15 14:09:53 TRACE Loader:1931 - Bound [7] parameters total /* SLOW here !!! Around 3 secs when query runs in ~0,300 secs via SQL client. And ACTIVE sessions are left running in Oracle. */ 2015-09-15 14:09:56 TRACE JdbcCoordinatorImpl:397 - Registering result set [org.apache.commons.dbcp.DelegatingResultSet@f0c620] 2015-09-15 14:09:56 TRACE Loader:943 - Processing result set 

最后,我不得不放弃所有Hibernate绑定参数并实现自定义计算分页并编写所有SQL来检索页面行,并且它正在运行并正确管理数据库会话。

所以,我的问题是:什么是hibernate正在破坏阻止查询在数据库运行时运行的场景? 绑定参数查询有任何已知问题吗?

当我有绑定参数时,我真的不喜欢编写所有SQL代码并强制对此SQL进行硬解析。

关于环境的一些注意事项:Tomcat和Oracle位于同一主机上。 所以网络连接不是问题

Hibernate版本4.2.15最终版

该表在开发数据库中有大约300k recs(生产中为1,5M),并且一次显示10,20,50个rec的页面,按主键描述排序(生成序列)

希望一些Hibernate专家可以帮助我,这样我仍然可以信任大型数据库项目上的Hibernate查询。 提前致谢。

我不知道这是否是你的问题,但Oracle在解析查询时会查看绑定变量值,然后保存查询计划以供将来执行,因此每次运行时都不必继续解析查询绑定变量集。 但每隔一段时间就会重新解析一次查询。 如果在解析期间碰巧传递了一些exception的绑定变量值,则会存储并使用错误的计划。 它是绑定变量的诅咒。 它们减少了解析,但是当再次解析查询时,可以在非典型绑定变量值上翻转计划。 提示可以提供帮助。 我们使用SQL配置文件来锁定具有易于更改计划的绑定变量的查询计划。 有时,您可以自定义何时以及如何收集优化程序统计信息,以便无论将哪些值传递到绑定变量,都可以创建良好的计划。

无论如何,它是我一直看到的东西,可能是也可能不是你的问题。

鲍比