同事在配置報表時,有一張報表查詢老是超時,而該段sql放到pl/sql中執行徹底沒問題,秒出級別的,好吧,本身不知道哪裏挖的坑,仍是須要本身填的。後來思考了集中可能出現的問題,一一排查:java
select A_COLUMN,B_COLUMN,C_COLUMN,TIME_STAMP from TABLEA where TIME_STAMP in (?)sql
1.強制指定該字段的索引執行,將報表查詢sql改成:app
select A_COLUMN,B_COLUMN,C_COLUMN,
/*+index(A IDX_DFRS_INTERFACE_5M_001)*/
TIME_STAMP from TABLEA A where TIME_STAMP in (?)ide
執行仍超時!學習
2.將條件寫死執行:測試
select A_COLUMN,B_COLUMN,C_COLUMN,TIME_STAMP from TABLEA where TIME_STAMP in (to_date('201705171500','yyyyMMddhh24mi'))this
執行成功!繼承
走到這裏能夠基本推想是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.