declare   
    ---define Cursor 
    cur_policy_sql  VARCHAR2(32767) := 'select * from  (select object_id,object_name 
     from t1111 order by object_id )  
     where rownum < 10' ;
    Cursor cur_policy is  
     select * from  (select object_id,object_name 
     from t1111 order by object_id )  
     where rownum < 10 ;  
    curPolicyInfo cur_policy%rowtype;---定义游标变量  
Begin  
   Dbms_Output.put_line(cur_policy_sql);
   open cur_policy; ---open cursor  
   Loop   
     --deal with extraction data from DB  
     Fetch cur_policy into curPolicyInfo;  
     Exit when cur_policy%notfound;  
        
     Dbms_Output.put_line(curPolicyInfo.object_id); 
     Dbms_Output.put_line(cur_policy%ROWCOUNT); 
   end loop;  
   
   Exception   
     when others then  
         close cur_policy;  
         Dbms_Output.put_line(Sqlerrm);  
           
   if cur_policy%isopen then    
    --close cursor   
      close cur_policy;  
   end if;  
end;  

周末抱团去河源的乡村徒步,路上景色谈不上惊艳,但是干净的空气,远离日常工作环境带来的放松感还是挺舒服的。

一路上和朋友有一搭没一搭的扯着最近的情况,发现很多话题都只能浅尝辄止,无法深入下去,一方面是自己思考问题的点过于局限,拓展问题方面有所欠缺,另一方面,对于日常生活的很多细节,没有加以关注。可能总是关注于工作,忘记了生活。

Oracle 六种方法查看执行计划
目录:

(一)六种执行计划

(1)explain plan for
(2)set autotrace on
(3)statistics_level=all
(4)dbms_xplan.display_cursor获取
(5)事件10046 trace跟踪
(6)awrsqrpt.sql

Oracle提供了6种执行计划获取方法,各种方法侧重点不同。

第一种 :explain for

步骤一:explain for  查询sql语句

步骤二:select * from table(dbms_xplan.display());

/*
优点:无需真正执行,快捷方便;
缺点:1.没有输出相关统计信息,例如产生了多少逻辑读,多少次物理读,多少次递归调用的情况;

      2.无法判断处理了多少行;
      3.无法判断表执行了多少次

*/

第二种:set autotrace on

  步骤一:sql> set autotrace on traceonly;

  步骤二:sql>执行查询Sql语句

  步骤三:sql> set autotrace off;

/*
优点:1.可以输出运行时的相关统计信息(产生多少逻辑读、多少次递归调用、多少次物理读等);

      2.虽然要等语句执行完才能输出执行计划,但是可以有traceonly开关来控制返回结果不打屏输出;

缺点:1.必须要等SQL语句执行完,才出结果;

      2.无法看到表被访问了多少次;

*/

第三种:(3)statistics_level=all

步骤一:ALTER SESSION SET STATISTICS_LEVEL=ALL;
步骤二:执行待分析的SQL
步骤三:select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

/*
关键字解读:

1.starts:SQL执行的次数;
2.E-Rows:执行计划预计返回的行数;
3.R-Rows:执行计划实际返回的行数;
4.A-Time:每一步执行的时间(HH:MM:SS.FF),根据这一行可知SQL耗时在哪些地方;
5.Buffers:每一步实际执行的逻辑读或一致性读;
6.Reads:物理读;
7.OMem:OMem为最优执行模式所需的内存评估值, 这个数据是由优化器统计数据以及前一次执行的性能数据估算得出的;
8.1Mem:1Mem为one-pass模式所需的内存评估值,当工作区大小无法满足操作所需的大小时,需要将部分数据写入临时磁盘空间中(如果仅需要写入一次就可以完成操作,就称一次通过,One-Pass;否则为多次通过,Multi-Pass).该列数据为语句最后一次执行中,单次写磁盘所需要的内存大小,这个由优化器统计数据以及前一次执行的性能数据估算得出的
9.Used_Mem:Used-Mem则为当前操作实际执行时消耗的内存,括号里面为(发生磁盘交换的次数,1次即为One-Pass,大于1次则为Multi_Pass,如果没有使用磁盘,则显示0)

*/

/*
优点:1.可以清晰的从starts得出表被访问多少次;

      2.可以从E-Rows和A-Rows得到预测的行数和真实的行数,从而可以准确判断Oracle评估是否准确;
      3.虽然没有准确的输出运行时的相关统计信息,但是执行计划中的Buffers就是真实的逻辑读的数值;

缺点:1.必须要等执行完后才能输出结果;

      2.无法控制结果打屏输出,不像autotrace可以设置traceonly保证不输出结果;
      3.看不出递归调用,看不出物理读的数值

*/

第四种:dbms_xplan.display_cursor获取

步骤1:select * from table( dbms_xplan.display_cursor('&sql_id') );    --该方法是从共享池得到,如果SQL已被age out出share pool,则查找不到

注释:

     1.还有1种方法,select * from table( dbms_xplan.display_awr('&sql_id') );  --该方法是从awr性能视图里面获取
     2.如果有多个执行计划,可用以下方法查出:
     select * from table(dbms_xplan.display_cursor('&sql_id',0));
     select * from table(dbms_xplan.display_cursor('&s ql_id',1));

/*
优点:1.知道sql_id即可得到执行计划,与explain plan for一样无需执行;

      2.可得到真实的执行计划

缺点:1.没有输出运行的统计相关信息;

      2.无法判断处理了多少行;
      3.无法判断表被访问了多少次;

*/

第五种:事件10046 trace跟踪

/*
步骤1:alter session set events '10046 trace name context forever,level 12'; --开启追踪
步骤2:执行sql语句;
步骤3:alter session set events '10046 trace name context off'; --关闭追踪
步骤4:select tracefile from v$process where addr=(select paddr from v$session where sid=(select sid from v$mystat where rownum<=1)); --找到跟踪后产生的文件

步骤5:tkprof trc文件 生成目标文件 sys=no sort=prsela,exeela,fchela --格式化命令
*/

第六种:awrsqrpt.sql
/*
步骤1:@?/rdbms/admin/awrsqrpt.sql
步骤2:选择你要的断点(begin snap和end snap)
步骤3:输入要查看的sql_id
*/

例子:

见:使用awrsqrpt.sql查看执行计划demo

(二)如何选择
选择时一般遵循以下规则:
1.如果sql执行很长时间才出结果或返回不了结果,用方法1:explain plan for
2.跟踪某条sql最简单的方法是方法1:explain plan for,其次是方法2:set autotrace on
3.如果相关查询某个sql多个执行计划的情况,只能用方法4:dbms_xplan.display_cursor或方法6:awrsqrpt.sql
4.如果sql中含有函数,函数中有含有sql,即存在多层调用,想准确分析只能用方法5:10046追踪
5.想法看到真实的执行计划,不能用方法1:explain plan for和方法2:set autotrace on
6.想要获取表被访问的次数,只能用方法3:statistics_level = all