Oracle版本驅(qū)動(dòng)中使用Java Date產(chǎn)生問題的解答
如果你在Oracle版本驅(qū)動(dòng)中使用Java Date時(shí)產(chǎn)生一些問題的時(shí)候,你是否想了解不解之處,以下的文章主要是通過對(duì)Oracle版本驅(qū)動(dòng)中使用Java Date的問題的實(shí)際應(yīng)用的方案的介紹,來解答你在Oracle版本驅(qū)動(dòng)中使用Java Date的問題在實(shí)際操作方面的問題。
這里兩天都在對(duì)一條sql進(jìn)行調(diào)優(yōu)。該sql并不復(fù)雜,類似于
- select ... from some_view union all select ...
from some_table where datetime >= d1 and datetime< d2 and ....
底層使用
- ibatis2.1.6 + oracle 10g
今天花了些時(shí)間繼續(xù)研究這個(gè)問題,導(dǎo)致該問題的原因的確是“導(dǎo)致oracle對(duì)datetime字段進(jìn)行了隱式類型轉(zhuǎn)換,最終CBO未能使用該列的全局索 引”,不過問題不是出在ibatis上而是Oracle driver。設(shè)我們使用這樣的sql通過綁定變量(類型為java.util.date)查詢數(shù)據(jù)庫(kù),其中end_date是date類型且建立了索引。
- “select count(*) from table1 where end_date >=
:1 and end_date <= :2”
通常,面對(duì)這樣的sql,我們希望它的執(zhí)行計(jì)劃走index range scan。然而在默認(rèn)情況下oracle CBO是不會(huì)選擇走索引地,以上面這語句為例,oracle實(shí)際走的是table full scan。為什么會(huì)這樣 呢?這類問題是oracle版本在9.2以后引入了TIMESTAMP才開始出現(xiàn)的。
在 9.2之前,Oracle只有DATE,而沒有TIMESTAMP。在jdbc preparedStatement.setTimestamp時(shí),綁定變量的類型會(huì)被正確的設(shè)置為DATE。而在9.2之后,oracle開始支持 TIMESTAMP了,這兩者都能支持精度為yyyy-MM-dd hh24:mi:ss的時(shí)間(當(dāng)然TIMESTAMP能支持到納秒級(jí)別)。
但jdbc driver的api未變同樣在preparedStatement.setTimestamp時(shí),oracle driver就得選擇到底該把綁定變量的類型設(shè)置為DATE還是TIMESTAMP呢?估計(jì)是由于TIMESTAMP的精度更高,Oracle 最終默認(rèn)選擇了將綁定變量的類型設(shè)置為了TIMESTAMP。那么這個(gè)時(shí)候,如果面對(duì)實(shí)際屬性為DATE的列,那么就會(huì)導(dǎo)致 oracle隱式地進(jìn)行形如
- “TO_TIMESTAMP(date_column) = parameter_timestamp”
轉(zhuǎn)換,要 知道oracle CBO不會(huì)選擇被某函數(shù)作用的列上的索引,除非是函數(shù)索引。因此,最終也會(huì)導(dǎo)致最上面的情況使用table full scan而不是index range scan。
Oracle版本就沒有提供別的方法來正確地提供綁定變量嗎?oracle提供 了幾個(gè)方法來解決這個(gè)問題
1.升級(jí)到11g并使用新的正確的driver api。
2.將DATE列全都改成 TIMESTAMP列。
3.使用V8Compatible flag。
以上就是對(duì)Oracle版本驅(qū)動(dòng)中如何使用Java Date的相關(guān)的內(nèi)容的介紹,望你會(huì)有所收獲。
【編輯推薦】
- 檢查Oracle DICOM 對(duì)象的典型示例
- Oracle ID 自增代碼的詳細(xì)介紹
- 對(duì)Oracle Multimedia導(dǎo)出圖像的操作步驟的描述
- 在Oracle模式中定義媒體對(duì)象有哪些
- Oracle Multimedia在ORDDicom中列中存儲(chǔ)DICOM詳解