草庐IT

java - Hibernate 参数化 sql 查询缓慢且活跃的 oracle session

coder 2024-03-08 原文

几天来,我一直在为针对 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 上创建函数索引以提高性能。

一开始以为是session/connection pool没有被正确管理,所以改成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;

没有解决。 查询运行几次正常,但由于某些未知原因,并且使用之前已成功运行的值,挂起,使 session 在 Oracle 中打开(状态= Activity )并因超时而失败。 在任何 SQL 客户端上针对 Oracle 运行相同的查询,并使用所有可能的参数组合执行数十次,以极高的性能执行,大约 400 毫秒,一次处理 10 条记录。

在阅读了一些文章之后, Link1 [ Slow performance on Hibernate + Java but fast when I use TOAD with the same native Oracle query 链接2:[query hangs oracle 10g

我怀疑 Hibernate 使用的 QueryPlan 很糟糕,因此决定删除所有使用绑定(bind)参数的过滤器,但也没有解决,尽管它稍微好一点。移动到第 1、2、3、4 页等其他页面时挂了一会儿,......

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

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

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

       ...
       Order By Certificado.Id Desc ) row_
       where rownum <= ?)
  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 绑定(bind)参数并实现自定义计算分页并编写所有 SQL 来检索页面行并且它正在运行并正确管理数据库 session 。

那么,我的问题是: hibernate 在阻止查询在针对数据库运行时运行的场景中做了什么? 绑定(bind)参数查询是否存在任何已知问题?

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

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

Hibernate 4.2.15 最终版

该表在开发数据库中有大约 30 万条记录(生产中有 1.5 万条记录),一次显示 10、20、50 条记录的页面,按主键降序排序(生成的序列)

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

最佳答案

我不知道这是否是您的问题,但 Oracle 在解析查询时会查看绑定(bind)变量值,然后保存查询计划以供将来执行,因此它不必在每次运行时都继续解析查询使用一组新的绑定(bind)变量。但是每隔一段时间就会重新解析查询。如果在解析过程中碰巧传递了一些不寻常的绑定(bind)变量值,则会存储和使用错误的计划。这是一种绑定(bind)变量的诅咒。它们减少了解析,但可以在再次解析查询时根据非典型的绑定(bind)变量值翻转计划。提示可以提供帮助。我们使用 SQL 配置文件来锁定带有绑定(bind)变量的查询计划,这些变量往往会改变计划。有时您可以自定义收集优化器统计信息的时间和方式,以便无论将什么值传递到绑定(bind)变量都可以创建一个好的计划。

无论如何,这是我一直看到的事情,可能是也可能不是你的问题。

鲍比

关于java - Hibernate 参数化 sql 查询缓慢且活跃的 oracle session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32596761/

有关java - Hibernate 参数化 sql 查询缓慢且活跃的 oracle session的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  4. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  7. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  8. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

随机推荐