最近优化单位的Oracle数据库,
AWR部分内容如下

可以看到
Execute to Parse %和Execute to Parse % 指标很低.
其中
Execute to Parse %
表示SQL语句解析后被重复执行命中率 计算公式=100*(1-Parses/Executions)
如果该值偏小,说明分析(硬分析与软分析 )的比例较大,快速分析较少,
根据实际情况,可以考虑调整session_cached_cursors参数
有些报告中这个值是负的,看上去很奇怪。事实上这表示一个问题,sql如果被age out的话就可能出现这种情况,也就是sql老化, 或 执行alter system flush shared_pool
Parse CPU to Parse Elapsd %
表示解析实际耗用时间/(解析实际耗用时间+等待资源的时间)
越高越好,在实际繁忙的系统中,该值可能因为等待资源而不会太高
这两个指标还是牵扯到了软软解析的老问题
http://blog.csdn.net/stevendbaguo/article/details/17267161
http://blog.itpub.net/29254281/viewspace-1064007/
如果JAVA使用了参数化SQL,那么每次执行SQL都是软解析.
相对于硬解析,软解析复用了执行计划,
但是软解析也会消耗资源(语法检查,语义检查,权限检查)
所以对于Oracle来说,软软解析才是最好的方式(我理解就是不解析...)
实现软软解析有两种方式,一种是JAVA应用程序缓存游标,另一种是设置Oracle的session_cached_cursors参数(默认20)
假设JAVA程序获取了一个游标,使用之后没有关闭,下次再次使用的时候,打开游标.oracle不会进行任何解析,而是直接使用执行计划获取数据。
即使关闭了该游标,如果同一连接软解析该SQL三次以上,Oracle也会将游标缓存在PGA。每个Session缓存游标的数量由session_cached_cursors决定。
从实验看软解析和软软解析
软解析
每次执行之后,关闭游标
-
import java.sql.Connection;
-
import java.sql.DriverManager;
-
import java.sql.PreparedStatement;
-
import java.sql.ResultSet;
-
import java.util.concurrent.Callable;
-
import java.util.concurrent.ExecutionException;
-
import java.util.concurrent.ExecutorService;
-
import java.util.concurrent.Executors;
-
import java.util.concurrent.Future;
-
-
public class Test implements Callable<Long> {
-
private static int COUNT = 100000;
-
-
public static void main(String[] args) throws Exception {
-
ExecutorService prepareThreadPool = Executors.newFixedThreadPool(4);
-
Future<Long> f1 = prepareThreadPool.submit(new Test());
-
Future<Long> f2 = prepareThreadPool.submit(new Test());
-
Future<Long> f3 = prepareThreadPool.submit(new Test());
-
Future<Long> f4 = prepareThreadPool.submit(new Test());
-
System.out.println("Wait");
-
Long totalTime = 0L;
-
totalTime = totalTime + f1.get();
-
totalTime = totalTime + f2.get();
-
totalTime = totalTime + f3.get();
-
totalTime = totalTime + f4.get();
-
System.out.println(totalTime);
-
prepareThreadPool.shutdown();
-
}
-
-
@Override
-
public Long call() throws Exception {
-
long start = System.currentTimeMillis();
-
Class.forName("oracle.jdbc.OracleDriver");
-
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:127.0.0.1:1521:orcl", "edmond", "edmond");
-
int index = 0;
-
while (index < COUNT) {
-
PreparedStatement cmd = conn.prepareStatement("select * from t");
-
ResultSet rs = cmd.executeQuery();
-
while (rs.next()) {
-
rs.getInt(1);
-
}
-
index++;
-
cmd.close();
-
}
-
long end = System.currentTimeMillis();
-
conn.close();
-
return end - start;
-
-
}
-
-
}
先刷新共享池
alter system flush shared_pool;
然后执行JAVA程序.结果如下
Wait
57448
使用如下SQL查看Execute to Parse %
-
set linesize 300;
-
set pagesize 3000;
-
col sql_text format a50;
-
SELECT sql_id,sql_text, s.PARSE_CALLS, loads, executions, round((1 - s.PARSE_CALLS / executions) * 100,-1)||'%' AS Execute_to_Parse
-
FROM v$sql s
-
WHERE executions>10 and PARSING_SCHEMA_NAME=upper('edmond') and rownum<10
-
ORDER BY executions desc ;
结果如下

然后修改JAVA程序,查看软软解析的情况.(缓存游标,注意红色的代码)
-
import java.sql.Connection;
-
import java.sql.DriverManager;
-
import java.sql.PreparedStatement;
-
import java.sql.ResultSet;
-
import java.util.concurrent.Callable;
-
import java.util.concurrent.ExecutionException;
-
import java.util.concurrent.ExecutorService;
-
import java.util.concurrent.Executors;
-
import java.util.concurrent.Future;
-
-
public class Test implements Callable<Long> {
-
private static int COUNT = 100000;
-
-
public static void main(String[] args) throws Exception {
-
ExecutorService prepareThreadPool = Executors.newFixedThreadPool(4);
-
Future<Long> f1 = prepareThreadPool.submit(new Test());
-
Future<Long> f2 = prepareThreadPool.submit(new Test());
-
Future<Long> f3 = prepareThreadPool.submit(new Test());
-
Future<Long> f4 = prepareThreadPool.submit(new Test());
-
System.out.println("Wait");
-
Long totalTime = 0L;
-
totalTime = totalTime + f1.get();
-
totalTime = totalTime + f2.get();
-
totalTime = totalTime + f3.get();
-
totalTime = totalTime + f4.get();
-
System.out.println(totalTime);
-
prepareThreadPool.shutdown();
-
}
-
-
@Override
-
public Long call() throws Exception {
-
long start = System.currentTimeMillis();
-
Class.forName("oracle.jdbc.OracleDriver");
-
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:127.0.0.1:1521:orcl", "edmond", "edmond");
-
int index = 0;
-
PreparedStatement cmd = conn.prepareStatement("select * from t");
-
while (index < COUNT) {
-
ResultSet rs = cmd.executeQuery();
-
while (rs.next()) {
-
rs.getInt(1);
-
}
-
index++;
-
}
-
cmd.close();
-
long end = System.currentTimeMillis();
-
conn.close();
-
return end - start;
-
-
}
-
-
}
还是先刷新共享池.
alter system flush shared_pool;
执行JAVA程序,可以看到执行速度提高了近一倍
Wait
29881
最后使用SQL查询Execute to Parse %

可以看到AWR报表中的Execute to Parse参数和软软解析是相关的.
事实上,resin中间件JNDI的配置是这样的
8
所以造成了Execute to Parse指标的不佳.
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-1320454/
,如需转载,请注明出处,否则将追究法律责任。