Oracle JDBC驅動使用setDate()、setTimestamp()導致全表掃描
今天有一個專案組報說,一個業務流程在Oracle上無法執行完成,而在SQL SERVER卻非常的正常。
環境:ORACLE RAC 10.2.0.4.0 FOR AIX 64bit
於是開始查詢是什麼原因,該業務流程操作的表是一個非常大的表,億級的資料量。透過對業務流程SQL執行的監控,發現在執行對這個表做小部分資料刪除的SQL時候卡住不動了。檢視了SQL的執行計劃發現是全表掃描,沒有建索引,於是把索引建上,重新監控,問題依然。
透過select exectutions from v$sqlarea where sql_id='xxxxxxx' 發現值為0。
檢查select buffer_gets from v$sqlarea where sql_id='xxxxxxxx' 發現值一直在不停的增長。
說明這個SQL一次都沒執行過,刪除的資料只有很少的量,但是卻一直在讀資料,首先想到的是全表掃描。
於是讓開發人員看了一下程式碼,這個SQL用到了預編譯PreparedStatement,where 條件要過濾一個時間欄位,賦值的時候使用的是setDate()方法。在單獨執行該SQL我使用的是to_date()函式來設定時間,執行速度很快,於是我讓開發人員把程式碼中的SQL過濾時間的部分加入to_date()函式,使用setString()方法賦值,再監控,就變得非常正常了。
後來同事在網上g了一下,發現這是oracle jdbc驅動確實有這個問題。在Java使用預編譯在where條件中使用setDate(),setTimeStamp()方法來給時間欄位賦值都會導致在執行該SQL的時候對錶進行全表掃描。
解決方法1:我們可以透過在SQL使用to_date('?','yyyy-mm-dd hh24:mi:ss')在繫結變數的時候使用setString()方法來代替使用setDate。
解決方法2:在配置連線的地方加入以下配置屬性:
解決方法3:
try {
Class.forName("oracle.jdbc.OracleDriver");
Properties prop=new Properties();
prop.setProperty("user","sysuser");
prop.setProperty("password","sys");
prop.setProperty("oracle.jdbc.V8Compatible","true");
java.sql.Connection connection1 = DriverManager.getConnection("jdbc:oracle:thin:@192.168.8.200:1521:cdb", prop);
System.out.println(connection1);
System.out.println(connection1.getMetaData().getDriverName()+"
"+connection1.getMetaData().getDriverVersion());
ResultSet rs = connection1.createStatement().executeQuery("select date1,date2 from t_test");
rs.next();
printInfo(rs,1);
printInfo(rs,2);
}
catch (Exception exception1) {
exception1.printStackTrace();
}
解決方法4:
在系統變數中使用引數-Doracle.jdbc.V8Compatible="true",例如
java -Doracle.jdbc.V8Compatible="true" MyApp
環境:ORACLE RAC 10.2.0.4.0 FOR AIX 64bit
於是開始查詢是什麼原因,該業務流程操作的表是一個非常大的表,億級的資料量。透過對業務流程SQL執行的監控,發現在執行對這個表做小部分資料刪除的SQL時候卡住不動了。檢視了SQL的執行計劃發現是全表掃描,沒有建索引,於是把索引建上,重新監控,問題依然。
透過select exectutions from v$sqlarea where sql_id='xxxxxxx' 發現值為0。
檢查select buffer_gets from v$sqlarea where sql_id='xxxxxxxx' 發現值一直在不停的增長。
說明這個SQL一次都沒執行過,刪除的資料只有很少的量,但是卻一直在讀資料,首先想到的是全表掃描。
於是讓開發人員看了一下程式碼,這個SQL用到了預編譯PreparedStatement,where 條件要過濾一個時間欄位,賦值的時候使用的是setDate()方法。在單獨執行該SQL我使用的是to_date()函式來設定時間,執行速度很快,於是我讓開發人員把程式碼中的SQL過濾時間的部分加入to_date()函式,使用setString()方法賦值,再監控,就變得非常正常了。
後來同事在網上g了一下,發現這是oracle jdbc驅動確實有這個問題。在Java使用預編譯在where條件中使用setDate(),setTimeStamp()方法來給時間欄位賦值都會導致在執行該SQL的時候對錶進行全表掃描。
解決方法1:我們可以透過在SQL使用to_date('?','yyyy-mm-dd hh24:mi:ss')在繫結變數的時候使用setString()方法來代替使用setDate。
解決方法2:在配置連線的地方加入以下配置屬性:
解決方法3:
try {
Class.forName("oracle.jdbc.OracleDriver");
Properties prop=new Properties();
prop.setProperty("user","sysuser");
prop.setProperty("password","sys");
prop.setProperty("oracle.jdbc.V8Compatible","true");
java.sql.Connection connection1 = DriverManager.getConnection("jdbc:oracle:thin:@192.168.8.200:1521:cdb", prop);
System.out.println(connection1);
System.out.println(connection1.getMetaData().getDriverName()+"
"+connection1.getMetaData().getDriverVersion());
ResultSet rs = connection1.createStatement().executeQuery("select date1,date2 from t_test");
rs.next();
printInfo(rs,1);
printInfo(rs,2);
}
catch (Exception exception1) {
exception1.printStackTrace();
}
解決方法4:
在系統變數中使用引數-Doracle.jdbc.V8Compatible="true",例如
java -Doracle.jdbc.V8Compatible="true" MyApp
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23135684/viewspace-629761/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 隱形轉換導致全表掃描案例
- ORACLE全表掃描查詢Oracle
- oracle優化:避免全表掃描Oracle優化
- oracle 全表掃描,索引範圍掃描與塊的理解Oracle索引
- 使用索引快速全掃描(Index FFS)避免全表掃描的若干場景索引Index
- 【TUNE_ORACLE】列出NL(NESTED LOOPS)被驅動表走了全表掃描的SQL參考OracleOOPSQL
- Oracle中存取資料掃描Table及索引的方式(全表掃描,索引掃描等)Oracle索引
- 優化全表掃描優化
- delete 與全表掃描delete
- oracle是如何進行全表掃描的Oracle
- 優化Oracle with全表掃描的問題優化Oracle
- 累計的力量,delete全表掃描導致程式執行時間過長。delete
- MySQL中的全表掃描和索引樹掃描MySql索引
- 優化Oracle with全表掃描的問題(二)優化Oracle
- oracle實驗記錄(分割槽全表掃描(全區掃描) FTS 時候的成本計算)Oracle
- 24_Oracle資料庫全表掃描詳解(四)_全表掃描生產最佳化案例三則Oracle資料庫
- oracle sql tuning 8--優化全表掃描OracleSQL優化
- 查詢全表掃描語句
- 查詢全表掃描的sqlSQL
- (轉)索引掃描還是全表掃描(Index Scan Or Full Table Scan)索引Index
- 轉)索引掃描還是全表掃描(Index Scan Or Full Table Scan)索引Index
- 使用全表掃描快取大表的相關問題快取
- 23_Oracle資料庫全表掃描詳解(三)Oracle資料庫
- 22_Oracle資料庫全表掃描詳解(二)Oracle資料庫
- 21_Oracle資料庫全表掃描詳解(一)Oracle資料庫
- oracle實驗記錄 (全表掃描COST計算方法)Oracle
- 一次簡單的效能優化診斷,聚簇因子過高導致全表掃描。優化
- 抓取全表掃描的表,篩選和分析
- 索引全掃描和索引快速全掃描的區別索引
- 使用10046 event trace跟蹤全表掃描操作
- zt:東軟醫保動態庫全表掃描問題
- Greenplum儲存過程使用分割槽表將進行全表掃描儲存過程
- delete 刪除資料 全表掃描還是掃描所有塊的測試delete
- maven打包oracle jdbc驅動MavenOracleJDBC
- 一條全表掃描sql語句的分析SQL
- Oracle 11g全表掃描以Direct Path Read方式執行Oracle
- 有索引卻走全表掃描的實驗分析索引
- noworkload下全表掃描cost的計算