1818IP-服务器技术教程,云服务器评测推荐,服务器系统排错处理,环境搭建,攻击防护等

当前位置:首页 - 数据库 - 正文

君子好学,自强不息!

如果你在Oracle版本驱动中使用Java Date时产生一些问题的时候,你是否想了解不解之处,以下的文章主要是通过对Oracle版本驱动中使用Java Date的问题的实际应用的方案的介绍,来解答你在Oracle版本驱动中使用Java Date的问题在实际操作方面的问题。

这里两天都在对一条sql进行调优。该sql并不复杂,类似于

select...fromsome_viewunionallselect...
fromsome_tablewheredatetime>=d1anddatetime<d2and....

底层使用

ibatis2.1.6+oracle10g

今天花了些时间继续研究这个问题,导致该问题的原因的确是“导致oracle对datetime字段进行了隐式类型转换,最终CBO未能使用该列的全局索 引”,不过问题不是出在ibatis上而是Oracle driver。设我们使用这样的sql通过绑定变量(类型为java.util.date)查询数据库,其中end_date是date类型且建立了索引。

“selectcount(*)fromtable1whereend_date>=
:1andend_date<=:2”

通常,面对这样的sql,我们希望它的执行计划走index range scan。然而在默认情况下oracle CBO是不会选择走索引地,以上面这语句为例,oracle实际走的是table full scan。为什么会这样 呢?这类问题是oracle版本在9.2以后引入了TIMESTAMP才开始出现的。

在 9.2之前,Oracle只有DATE,而没有TIMESTAMP。在jdbc preparedStatement.setTimestamp时,绑定变量的类型会被正确的设置为DATE。而在9.2之后,oracle开始支持 TIMESTAMP了,这两者都能支持精度为yyyy-MM-dd hh24:mi:ss的时间(当然TIMESTAMP能支持到纳秒级别)。

但jdbc driver的api未变同样在preparedStatement.setTimestamp时,oracle driver就得选择到底该把绑定变量的类型设置为DATE还是TIMESTAMP呢?估计是由于TIMESTAMP的精度更高,Oracle 最终默认选择了将绑定变量的类型设置为了TIMESTAMP。那么这个时候,如果面对实际属性为DATE的列,那么就会导致 oracle隐式地进行形如

“TO_TIMESTAMP(date_column)=parameter_timestamp”

转换,要 知道oracle CBO不会选择被某函数作用的列上的索引,除非是函数索引。因此,最终也会导致最上面的情况使用table full scan而不是index range scan。

Oracle版本就没有提供别的方法来正确地提供绑定变量吗?oracle提供 了几个方法来解决这个问题

1.升级到11g并使用新的正确的driver api。

2.将DATE列全都改成 TIMESTAMP列。

3.使用V8Compatible flag。

本文来源:1818IP

本文地址:https://www.1818ip.com/post/11974.html

免责声明:本文由用户上传,如有侵权请联系删除!

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。