ITPub博客

首页 > 数据库 > Oracle > AWR Execute to Parse参数解析

AWR Execute to Parse参数解析

原创 Oracle 作者:壹頁書 时间:2014-11-04 19:30:51 0 删除 编辑
最近优化单位的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决定。

从实验看软解析和软软解析

软解析
每次执行之后,关闭游标
  1. import java.sql.Connection;
  2. import java.sql.DriverManager;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.util.concurrent.Callable;
  6. import java.util.concurrent.ExecutionException;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. import java.util.concurrent.Future;

  10. public class Test implements Callable<Long> {
  11.     private static int COUNT = 100000;

  12.     public static void main(String[] args) throws Exception {
  13.         ExecutorService prepareThreadPool = Executors.newFixedThreadPool(4);
  14.         Future<Long> f1 = prepareThreadPool.submit(new Test());
  15.         Future<Long> f2 = prepareThreadPool.submit(new Test());
  16.         Future<Long> f3 = prepareThreadPool.submit(new Test());
  17.         Future<Long> f4 = prepareThreadPool.submit(new Test());
  18.         System.out.println("Wait");
  19.         Long totalTime = 0L;
  20.         totalTime = totalTime + f1.get();
  21.         totalTime = totalTime + f2.get();
  22.         totalTime = totalTime + f3.get();
  23.         totalTime = totalTime + f4.get();
  24.         System.out.println(totalTime);
  25.         prepareThreadPool.shutdown();
  26.     }

  27.     @Override
  28.     public Long call() throws Exception {
  29.         long start = System.currentTimeMillis();
  30.         Class.forName("oracle.jdbc.OracleDriver");
  31.         Connection conn = DriverManager.getConnection("jdbc:oracle:thin:127.0.0.1:1521:orcl", "edmond", "edmond");
  32.         int index = 0;
  33.         while (index < COUNT) {
  34.             PreparedStatement cmd = conn.prepareStatement("select * from t");
  35.             ResultSet rs = cmd.executeQuery();
  36.             while (rs.next()) {
  37.                 rs.getInt(1);
  38.             }
  39.             index++;
  40.             cmd.close();
  41.         }
  42.         long end = System.currentTimeMillis();
  43.         conn.close();
  44.         return end - start;

  45.     }

  46. }
先刷新共享池
alter system flush shared_pool;
然后执行JAVA程序.结果如下
Wait
57448

使用如下SQL查看Execute to Parse %

  1. set linesize 300;
  2. set pagesize 3000;
  3. col sql_text format a50;
  4. SELECT sql_id,sql_text, s.PARSE_CALLS, loads, executions, round((1 - s.PARSE_CALLS / executions) * 100,-1)||'%' AS Execute_to_Parse
  5. FROM v$sql s
  6. WHERE executions>10 and PARSING_SCHEMA_NAME=upper('edmond') and rownum<10
  7. ORDER BY executions desc ;
结果如下


然后修改JAVA程序,查看软软解析的情况.(缓存游标,注意红色的代码)

  1. import java.sql.Connection;
  2. import java.sql.DriverManager;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.util.concurrent.Callable;
  6. import java.util.concurrent.ExecutionException;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. import java.util.concurrent.Future;

  10. public class Test implements Callable<Long> {
  11.     private static int COUNT = 100000;

  12.     public static void main(String[] args) throws Exception {
  13.         ExecutorService prepareThreadPool = Executors.newFixedThreadPool(4);
  14.         Future<Long> f1 = prepareThreadPool.submit(new Test());
  15.         Future<Long> f2 = prepareThreadPool.submit(new Test());
  16.         Future<Long> f3 = prepareThreadPool.submit(new Test());
  17.         Future<Long> f4 = prepareThreadPool.submit(new Test());
  18.         System.out.println("Wait");
  19.         Long totalTime = 0L;
  20.         totalTime = totalTime + f1.get();
  21.         totalTime = totalTime + f2.get();
  22.         totalTime = totalTime + f3.get();
  23.         totalTime = totalTime + f4.get();
  24.         System.out.println(totalTime);
  25.         prepareThreadPool.shutdown();
  26.     }

  27.     @Override
  28.     public Long call() throws Exception {
  29.         long start = System.currentTimeMillis();
  30.         Class.forName("oracle.jdbc.OracleDriver");
  31.         Connection conn = DriverManager.getConnection("jdbc:oracle:thin:127.0.0.1:1521:orcl", "edmond", "edmond");
  32.         int index = 0;
  33.         PreparedStatement cmd = conn.prepareStatement("select * from t");
  34.         while (index < COUNT) {
  35.             ResultSet rs = cmd.executeQuery();
  36.             while (rs.next()) {
  37.                 rs.getInt(1);
  38.             }
  39.             index++;
  40.         }
  41.         cmd.close();
  42.         long end = System.currentTimeMillis();
  43.         conn.close();
  44.         return end - start;

  45.     }

  46. }
还是先刷新共享池.
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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2013-10-19

  • 博文量
    620
  • 访问量
    6339907