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

时间:2015-09-15 22:30:17

标签: java spring oracle performance hibernate

我在针对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<CertificateViewEnt>) query.list(); 
session.close();
return result;

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

在这里和那里看了一些文章后, Link1 [Slow performance on Hibernate + Java but fast when I use TOAD with the same native Oracle query Link2:[query hangs oracle 10g

我怀疑Hibernate使用的QueryPlan很差,并决定使用绑定参数删除所有过滤器,但也没有解决,尽管它有点好一些。在转移到其他页面(如第1页,第2,3,4页,......)之后暂停了一段时间。

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

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

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

       ...
       Order By Certificado.Id Desc ) row_
       where rownum <= ?)
  where rownum_ > ?

我也在Trace Log

中看到了这一点
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 final

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

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

1 个答案:

答案 0 :(得分:1)

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

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

巴比