同事在配置报表时,有一张报表查询总是超时,而该段sql放到pl/sql中执行完全没问题,秒出级别的,好吧,自己不知道哪里挖的坑,还是需要自己填的。后来思考了集中可能出现的问题,一一排查:
select A_COLUMN,B_COLUMN,C_COLUMN,TIME_STAMP from TABLEA where TIME_STAMP in (?)
1.强制指定该字段的索引执行,将报表查询sql改为:
select A_COLUMN,B_COLUMN,C_COLUMN,
/*+index(A IDX_DFRS_INTERFACE_5M_001)*/
TIME_STAMP from TABLEA A where TIME_STAMP in (?)
执行仍超时!
2.将条件写死执行:
select A_COLUMN,B_COLUMN,C_COLUMN,TIME_STAMP from TABLEA where TIME_STAMP in (to_date('201705171500','yyyyMMddhh24mi'))
执行成功!
走到这里可以基本推想是Java自动注入后导致索引失效。但是为什么会失效?用其他几千条的表测试是OK的,这个表有3亿+ 近4亿的数据量就不行了。
后来查看代码发现 Date条件是new java.util.Date();那我换成new java.sql.Date() 试了一下,OK了~再换成new java.sql.Time() 也是OK的,那就是这个原因了!
之前只是知道两个Date的应用场景不一样,但是不知道具体会有什么差异,这个小bug让我也学习到了。至于说具体的差别在哪里,翻看源码发现了以下几点:
a). java.sql.Date 继承了 java.util.Date
b). java.sql.Date 注释中描述了这个子类:
A thin wrapper around a millisecond value that allows JDBC to identify this as an SQL DATE value.
一个允许JDBC去将这个类识别为一个SQL DATE 的关于毫秒值的简单封装。
-------补充-------
既然类本身没有什么特别的地方,那一定是其他地方作了区分,然后看了Oracle驱动包发现,里面会对每种类型进行区分,而对时间的处理正是识别为java.sql.Date|Time.