硬解析,過多的硬解析在系統中產生shared pool latch和library cache liatch爭用,消耗過多的shared pool,使得系統不具有可伸縮性。
軟解析,過多的軟解析仍然可能會導致系統問題,特別是如果有少量的SQL高并發地進行軟解析,會產生library cache latch或者是share方式的mutex爭用。
軟軟解析,其實這也也屬于軟解析,與普通的軟解析不同的是,軟軟解析的SQL會在會話的cached cursor中命中。
一次解析,多次執行,這是解析次數最少的方式,也是系統最具有可擴展性的方式。
那么在JAVA開發的應用中,怎么樣才能實現上述第4種方式?如果是循環處理某種數據,這個比較容易實現。其實對于不是這種情況,Oracle也提供了很好的方式來實現這一點。下面是一個例子(例子代碼文件為TestStmtCache.java)。
import java.sql.*;
import oracle.jdbc.driver.OracleConnection;
public class TestStmtCache {
public static Connection getConnection() throws Exception {
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@localhost:1521:xj11g";
Class.forName(driver);
return DriverManager.getConnection(url, "test", "test");
}
public static void main(String args[]) {
Connection conn = null;
try {
conn = getConnection();
conn.setAutoCommit(false);
((OracleConnection)conn).setStatementCacheSize(0);
for (int i=0; i <200; i++) {
testNoCache(conn);
}
((OracleConnection)conn).setStatementCacheSize(20);
((OracleConnection)conn).setImplicitCachingEnabled(true);
for (int i=0; i <200; i++) {
testCache(conn);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void testCache(Connection conn) {
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement("select /*cache_test1 */ * from t1 where rownum<=1");
pstmt.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void testNoCache(Connection conn) {
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement("select /*nocache_test1 */ * from t1 where rownum<=1");
pstmt.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
編譯上述代碼文件TestStmtCache.java,并運行:
E:\JavaCode>set CLASSPATH=.;ojdbc14.jar
E:\JavaCode>d:\works\Java\jdk1.5.0_21\bin\javac TestStmtCache.java
E:\JavaCode>d:\works\Java\jdk1.5.0_21\jre\bin\java TestStmtCache
在數據庫中進行查詢:
SYS@xj11g> select sql_id,parse_calls,executions,sql_text from v$sqlarea where sql_text like '%cache_test%' and sql_text not like '%v$%';
SQL_ID PARSE_CALLS EXECUTIONS SQL_TEXT
------------- ----------- ----------- ------------------------------------------------------------
3nbu9qp40ptjk 200 200 select /*nocache_test1 */ * from t1 where rownum< =1
47hja0fwmmb6c 1 200 select /*cache_test1 */ * from t1 where rownum<=1
可以看到,這兩條SQL語句,都執行了200次,但是標記為”nocache_test1″的SQL沒有進行語句緩存,其parse calls為200次,即解析了200次,其中一次是硬解析。而標記為”cache_test1″的SQL語句,使用了語句緩存,但是parse calls只有1次,即只有一次硬解析,執行了200次。這里關鍵的代碼在于:
((OracleConnection)conn).setStatementCacheSize(20);
((OracleConnection)conn).setImplicitCachingEnabled(true);
上述第一行代碼設置語句緩存大小,當然20比較偏小,對于比較大型的系統來說,設到200-300比較合適,不過這會耗用一定數量的JAVA內存。這個數值表示一個連接能夠緩存多少語句。第二行代碼是設置隱式打開語句緩存,也即自動會對PreparedStatement的SQL語句進行緩存。
那么,上述的方式無疑是比較簡單的,但是這種方式有一個問題就是,緩存的利用效率可能不高,因為JAVA會將不常用的SQL語句也進行了緩存。Oracle的JDBC驅動也提供了一種手工控制的方式:
將測試代碼中的第22行替換為:
((OracleConnection)conn).setExplicitCachingEnabled(true);
原文轉自:http://blogread.cn/it/article/6685