【发布时间】:2013-10-17 02:04:19
【问题描述】:
在 web 应用程序中,休眠条件对 oracle db 花费的时间太长。我启用 log4j.logger.org.hibernate.SQL=debug SQL 并在 sql 中使用相同的绑定变量运行 sql 查询,结果是实例。启用休眠日志并浏览日志。是什么导致hibernate花费太长时间摩擦查询?有什么建议么?
更新 1:
当我通过 SQLPlus 运行 hibernate 生成的相同查询时,oracle 似乎使用不同的执行计划。 来自 Hibernate 的 SQL 查询:
select count(*) as y0_ from SUMMARY_VIEW this_ where this_.ser_id like :1 and this_.TYPE=:2 and this_.TIME_LOCAL>=:3 and this_.TIME_LOCAL<=:4
在 SQLPlus 上运行 SQL 查询:
select count(*) as y0_ from SUMMARY_VIEW this_ where this_.ser_id like :ser_id and this_.TYPE=:type and this_.TIME_LOCAL>=:startdate and this_.TIME_LOCAL<=:enddate
更新 2: 进一步调查发现 startdate 和 endate 绑定变量作为 varchar2 从 sqlplus 传递,但这些作为时间戳从 app (:) 传递。由于这个执行计划不同。
select sql_text, v.sql_id, name, value_string, datatype_string from v$sql_bind_capture vbc join v$sql v using (hash_value) where v.sql_id in (?)
绑定变量类型会影响执行计划吗?如果是这样,是否有任何其他工具可以将日期变量作为绑定参数传递给查询?
更新 3: 由于数据类型不兼容导致的性能问题。看来列数据类型(DATE)和休眠数据类型(TIMESTAMP)不匹配会导致隐式数据类型转换。 Oracle 使用 INTERNAL_FUNCTION 来传输日期列以匹配传递的绑定变量休眠数据类型 TimeStamp。
类似问题:
Non-negligible execution plan difference with Oracle when using jdbc Timestamp or Date
Why is Oracle so slow when I pass a java.sql.Timestamp for a DATE column?
【问题讨论】:
-
也许需要很长时间的是对象树的映射。您是否尝试过原生查询(返回
Object[])来查看性能是否有所提高? -
prod 中出现问题。现在无法验证这一点,模型类中的字段是原始数据类型和字符串。所以我相信它不会构造对象树。
-
好吧,抱歉,如果没有更多信息,我们无法为您提供帮助。继续并分析您的代码/环境。当您有更多信息时,如果您仍然需要帮助,请回来更新问题,我一定会看看(可能是几件事:您可能正在耗尽您的连接池/使用错误的事务范围,这可能会使您的查询等待/锁定/有环境问题/等等等等,没有办法通过猜测来帮助)。
-
当您在 SQLPlus 中“使用相同的绑定变量”时,您是否真的在 SQLPlus 中使用了绑定变量(例如 :b1、:b2),或者您是否将值填写到 SQL 语句中你可以在 SQLPlus 中吗?
-
同一个查询在不同会话中的运行可能不同的原因有很多。首先,您应该可以使用
select * from gv$sql;和select * from table(dbms_xplan.display_cursor(sql_id => '[sql id]', cursor_child_no => '[cursor child no]'));之类的方式找到查询及其计划。如果只有一个子游标,则数据库正在执行相同的查询,这是客户端问题。如果有计划差异,那么您可以查看不同的会话设置,例如 NLS 参数,或者可能为绑定变量使用了不同的值?
标签: java sql oracle hibernate sql-execution-plan