一键获取SQL的各种详细信息--脚本


此脚本转自梁敬彬老师的《收获,不止SQL优化》,感谢老师的分享


构造环境脚本,构造部分执行效率低下的SQL

create user hj identified by hj;
alter user hj default tablespace users;
grant dba to hj;

drop table hj.spoolsql_dba_objects purge;
create table hj.spoolsql_dba_objects as select * from dba_objects nologging;

drop table hj.spoolsql_dba_objects purge;
create global temporary table hj.spoolsql_dba_objects
on commit delete rows
as (select * from dba_objects where 1=2)
;

drop table hj.spoolsql_dba_users purge;
create table hj.spoolsql_dba_users as select * from dba_users nologging;

drop table hj.spoolsql_dba_segments purge;
create table hj.spoolsql_dba_segments as select * from dba_segments nologging;
begin
  for i in 1 .. 8 loop
    insert /*+ append */
    into hj.spoolsql_dba_segments
      select * from hj.spoolsql_dba_segments nologging;
    commit;
  end loop;
end;
/

create index hj.idx_spoolsql_dba_segments_name on hj.spoolsql_dba_segments(segment_name) nologging;

exec dbms_stats.gather_table_stats(ownname => 'HJ', tabname => 'spoolsql_dba_objects',cascade => true);
exec dbms_stats.gather_table_stats(ownname => 'HJ', tabname => 'spoolsql_dba_users',cascade => true);
exec dbms_stats.gather_table_stats(ownname => 'HJ', tabname => 'spoolsql_dba_segments',cascade => true);

set linesize 1000
set pagesize 3000
set trim on
set trimspool on

set autot traceonly statistics;
set timing on;

exec dbms_workload_repository.create_snapshot;

insert into hj.spoolsql_dba_objects select * from dba_objects nologging;

variable vbeginid number;
variable vendid number;

exec :vbeginid := 4900;
exec :vendid := 5000;

select t1.owner,
       t1.object_name,
       t1.subobject_name,
       t1.last_ddl_time,
       t2.user_id,
       t2.account_status,
       t3.segment_name,
       t3.partition_name,
       t3.bytes,
       t3.blocks
  from hj.spoolsql_dba_objects  t1,
       hj.spoolsql_dba_users    t2,
       hj.spoolsql_dba_segments t3
 where t1.owner = t2.username
   and t1.object_name = t3.segment_name
   and t1.object_id between :vbeginid and :vendid
;

exec :vbeginid := 1;
exec :vendid := 5000;

select t1.owner,
       t1.object_name,
       t1.subobject_name,
       t1.last_ddl_time,
       t2.user_id,
       t2.account_status,
       t3.segment_name,
       t3.partition_name,
       t3.bytes,
       t3.blocks
  from hj.spoolsql_dba_objects  t1,
       hj.spoolsql_dba_users    t2,
       hj.spoolsql_dba_segments t3
 where t1.owner = t2.username
   and t1.object_name = t3.segment_name
   and t1.object_id between :vbeginid and :vendid
;

exec :vbeginid := 1;
exec :vendid := 10000;

select t1.owner,
       t1.object_name,
       t1.subobject_name,
       t1.last_ddl_time,
       t2.user_id,
       t2.account_status,
       t3.segment_name,
       t3.partition_name,
       t3.bytes,
       t3.blocks
  from hj.spoolsql_dba_objects  t1,
       hj.spoolsql_dba_users    t2,
       hj.spoolsql_dba_segments t3
 where t1.owner = t2.username
   and t1.object_name = t3.segment_name
   and t1.object_id between :vbeginid and :vendid
;

exec :vbeginid := 4990;
exec :vendid := 5000;

select /*+ index(t3 idx_spoolsql_dba_segments_name) */
       t1.owner,
       t1.object_name,
       t1.subobject_name,
       t1.last_ddl_time,
       t2.user_id,
       t2.account_status,
       t3.segment_name,
       t3.partition_name,
       t3.bytes,
       t3.blocks
  from hj.spoolsql_dba_objects  t1,
       hj.spoolsql_dba_users    t2,
       hj.spoolsql_dba_segments t3
 where t1.owner = t2.username
   and t1.object_name = t3.segment_name
   and t1.object_id between :vbeginid and :vendid
;
exec :vbeginid := 1;
exec :vendid := 10000;

select /*+ no_index(t3) */
       t1.owner,
       t1.object_name,
       t1.subobject_name,
       t1.last_ddl_time,
       t2.user_id,
       t2.account_status,
       t3.segment_name,
       t3.partition_name,
       t3.bytes,
       t3.blocks
  from hj.spoolsql_dba_objects  t1,
       hj.spoolsql_dba_users    t2,
       hj.spoolsql_dba_segments t3
 where t1.owner = t2.username
   and t1.object_name = t3.segment_name
   and t1.object_id between :vbeginid and :vendid
;

exec dbms_workload_repository.create_snapshot;

alter index hj.idx_spoolsql_dba_segments_name unusable;

exec :vbeginid := 4900;
exec :vendid := 5000;

select t1.owner,
       t1.object_name,
       t1.subobject_name,
       t1.last_ddl_time,
       t2.user_id,
       t2.account_status,
       t3.segment_name,
       t3.partition_name,
       t3.bytes,
       t3.blocks
  from hj.spoolsql_dba_objects  t1,
       hj.spoolsql_dba_users    t2,
       hj.spoolsql_dba_segments t3
 where t1.owner = t2.username
   and t1.object_name = t3.segment_name
   and t1.object_id between :vbeginid and :vendid
;

set autot off;

variable v_dbid number;
variable v_inst_num number;
variable v_beginsnap number;
variable v_endsnap number;

begin
    with params as
     (select beginsnap, endsnap, dbid, instance_number
      from (select sum(decode(rn, 2, snap_id, 0)) beginsnap,
             sum(decode(rn, 1, snap_id, 0)) endsnap
          from (select snap_id,
                 row_number() over(order by end_interval_time desc) rn
              from dba_hist_snapshot)
           where rn < 3) t1,
         (select dbid from v$database where rownum = 1) t2,
         (select instance_number from v$instance where rownum = 1) t3)
    select dbid, instance_number, beginsnap, endsnap
	  into :v_dbid, :v_inst_num, :v_beginsnap, :v_endsnap
	  from params;
end;
/

col module format a30
col text format a30

select *
  from (select sqt.sql_id,
               to_char(nvl((round(sqt.elap / 1000000, 3)), to_number(null)),
                       '9999990.999') elapsed,
               to_char(nvl((round(sqt.cput / 1000000, 3)), to_number(null)),
                       '9999990.999') cputime,
               sqt.exec execs,
               to_char(decode(sqt.exec,
                              0,
                              to_number(null),
                              round(sqt.elap / sqt.exec / 1000000, 3)),
                       '9999990.999') "elapsed/exec",
               to_char(decode(dbt.dbtime,
                              0,
                              100,
                              100 * (sqt.elap / 10000 / dbt.dbtime)),
                       '9999990.999') "%DB time",
               nvl(sqt.module, '') module,
               decode(dbms_lob.substr(st.sql_text, 100,1),
                      null,
                      '**********************',
					  '',
					  '**********************',
                      substr(st.sql_text, 1, 50)) sqltxt
          from (select sql_id,
                       max(module) module,
                       sum(elapsed_time_delta) elap,
                       sum(cpu_time_delta) cput,
                       sum(executions_delta) exec
                  from dba_hist_sqlstat
                 where dbid = :v_dbid
                   and instance_number = :v_inst_num
                   and :v_beginsnap < snap_id
                   and snap_id <= :v_endsnap
                 group by sql_id) sqt,
               dba_hist_sqltext st,
               (SELECT nvl(sum(e.VALUE) - sum(b.value), 0) dbtime
                  FROM DBA_HIST_SYSSTAT b, DBA_HIST_SYSSTAT e
                 WHERE B.SNAP_ID = :v_beginsnap
                   AND E.SNAP_ID = :v_endsnap
                   AND B.DBID = :v_dbid
                   AND E.DBID = B.DBID
                   AND B.INSTANCE_NUMBER = :v_inst_num
                   AND E.INSTANCE_NUMBER = B.INSTANCE_NUMBER
                   and e.STAT_NAME = 'DB time'
                   and b.stat_name = 'DB time') dbt
         where st.sql_id(+) = sqt.sql_id
           and st.dbid(+) = :v_dbid
         order by nvl(sqt.elap, -1) desc, sqt.sql_id)
 where rownum < 10;

col username format a15
col event format a30
col sql_txt format a50

select c.USERNAME, a.event, a.cnt as "TIME(SECOND)", a.sql_id, substr(b.SQL_TEXT,1,50) sql_txt
  from (select rownum rn, t.*
          from (select decode(s.session_state,
                              'WAITING',
                              s.event,
                              'Cpu + Wait For Cpu') Event,
                       s.sql_id,
                       s.user_id,
                       count(*) CNT
                  from v$active_session_history s
                 where sample_time > sysdate - 15 / 1440
                 group by s.user_id,
                          decode(s.session_state,
                                 'WAITING',
                                 s.event,
                                 'Cpu + Wait For Cpu'),
                          s.sql_id
                 order by CNT desc) t
         where rownum < 20) a,
       v$sqlarea b,
       dba_users c
 where a.sql_id = b.sql_id
   and a.user_id = c.user_id
 order by CNT desc
;

exit

执行脚本,构造环境

[oracle@orasql ~]$ sqlplus / as sysdba

SQL> set echo on
SQL> @mksql.sql

性能低下的SQL信息收集脚本

set term off
set termout off
set heading on
set feedback off
set verify off
set echo off

set term on
set termout on
set heading off
set feedback off
set verify off
set echo off

SET markup html off spool ON pre off entmap off

set define ^
var sqlid varchar2(50);
var outputdir varchar2(256);
prompt "input sqlid:"
define tmp_sqlid=^SQL_ID
exec :sqlid := '^tmp_sqlid'
column outputdir_sqlid new_value outputfile
select './'||:sqlid||'.html' as outputdir_sqlid from dual;

SET markup html off spool ON pre off entmap off

set term off
set termout off
set heading off
set feedback off
set verify off
set trimspool on
set trim on
set echo off

set linesize 32767
set pagesize 999999
set serveroutput on

spool ^^outputfile
declare
  type refcursor is ref cursor;
  vCur          refcursor;
  vsqlid        varchar2(4000) := :sqlid;
  vOwnerstr     varchar2(32767) := '';
  vOwnerCnt     number(3) := 0;
  vTableStr     varchar2(32767) := '';
  vTableCnt     number(3) := 0;
  vtmpchldnum   number;
  vtmpplnval    number;
  type VARCHARTAB is table of varchar2(32767) index by BINARY_INTEGER;
  vPlanAddition VARCHARTAB;
  arr_iter BINARY_INTEGER;
  vsqltxt_c clob;
  vsqltxt_a dbms_sql.varchar2a;
  vsqltxt_lb number(1):= 0;
  vsqltxt_le number(12);
  vsqlcur number;
  vsqlmsg varchar2(4000);
begin
  ----打开服务器output
  dbms_output.enable(10000000000000);
  
  ----打印html头和样式
  dbms_output.put_line('<html><title>Reports About SQL:'||vsqlid||'</title><head>');
  dbms_output.put_line('<style>');
  
  dbms_output.put_line('th {font:bold 8pt Arial,Helvetica,Geneva,sans-serif; color:White; background:#0066CC;padding-left:4px; padding-right:4px;padding-bottom:2px}');
  dbms_output.put_line('tr   {font:10pt SimSun,SimSun,SimSun,SimSun;}');
  dbms_output.put_line('td   {border:1px solid; font:10pt SimSun,SimSun,SimSun,SimSun;}');
  dbms_output.put_line('</style>');
  dbms_output.put_line('</head><body>');

  ----获取SQL文本
  dbms_output.put_line('<b>sql_text</b><br>');
  dbms_output.put_line('<table><tr><td>');
  select sqtxt
    into vsqltxt_c
    from (select sql_text sqtxt
            from dba_hist_sqltext
           where sql_id = vsqlid
          union all
          select sql_fulltext sqtxt from v$sqlarea where sql_id = vsqlid)
   where rownum = 1;
  vsqltxt_a.delete;
  vsqltxt_le := DBMS_LOB.GETLENGTH(vsqltxt_c) / 2000 + 1;
  for i in 1 .. vsqltxt_le loop
	vsqltxt_a(i) := substr(vsqltxt_c, 1900 * (i - 1) + 1, 1900);
    dbms_output.put_line(vsqltxt_a(i));
  end loop;
  dbms_output.put_line('</td></tr></table>');
  dbms_output.put_line('<br>');
  
  ----获取执行计划--explain plan for
  dbms_output.put_line('<b>explain plan for</b><table>');
  for v in (select distinct parsing_schema_name from dba_hist_sqlstat where sql_id = vsqlid) loop
    dbms_output.put_line('<tr><td><pre>');
    begin
	  execute immediate 'alter session set current_schema='||v.parsing_schema_name;
      vsqlcur := dbms_sql.open_cursor;
      vsqltxt_a(0) := 'explain plan for ';
      dbms_sql.parse(vsqlcur, vsqltxt_a, vsqltxt_lb, vsqltxt_le, false, dbms_sql.native);
      vsqltxt_le := dbms_sql.execute(vsqlcur);
      for v_in in (select plan_table_output as planline from table(dbms_xplan.display)) loop
        dbms_output.put_line(v_in.planline);
      end loop;
      dbms_sql.close_cursor(vsqlcur);
      exception
        when others then
	  	vsqlmsg := sqlerrm;
          dbms_output.put_line(vsqlmsg);
    end;
    dbms_output.put_line('</pre></td></tr>');
  end loop;
  dbms_output.put_line('</table>');
  dbms_output.put_line('<br>');

  ----获取执行计划--V$SQLPLAN
  dbms_output.put_line('<b>Execution Plan From V$SQLPLAN</b><br>');
  for hashval in (select distinct plan_hash_value from v$sql_plan where sql_id = vsqlid) loop
    dbms_output.put_line('SQL:'||vsqlid||', PLAN_HASH_VALUE:'||hashval.plan_hash_value);
    dbms_output.put_line('<table>');
    dbms_output.put_line('<tr><th>ID</th><th>DEP</th><th width="400px">OPERITION</th><th>NAME</th><th>ROWS</th><th>BYTES</th><th>COST(%CPU)</th><th>IO_COST</th><th>TIME</th></tr>');
    vPlanAddition.delete;
    arr_iter := 0;
    for v in (select decode(trim(predicates), '', '' || ID, '*' || ID) ID,
                     DEPTH,
                     OPERATION,
                     NAME,
                     PREDICATES,
                     "ROWS",
                     BYTES,
                     "COST(%CPU)",
                     IO_COST,
                     TIME
                from (select a.plan_hash_value || ' ' plan_hash_value,
               id ID,
               depth DEPTH,
               lpad(operation, length(operation) + depth * 6, ' ') || ' ' || options OPERATION,
               decode(OBJECT_NAME,
                  null,
                  '',
                  '[' || OBJECT_TYPE || ']' || OBJECT_OWNER || '.' ||
                  OBJECT_NAME) || ' ' NAME,
               case
               when (length(access_predicates) < 3 or access_predicates is null) then
                case
                when (length(filter_predicates) < 3 or filter_predicates is null) then
                 ' '
                else
                 '[filter]' || substr(filter_predicates, 1, 3990)
                end
               else
                '[access]' || substr(access_predicates, 1, 3990)
               end PREDICATES,
               decode(cardinality, null, '', cardinality) || ' ' "ROWS",
               decode(Bytes, null, '', Bytes) || ' ' BYTES,
               decode(io_cost,
                  null,
                  decode(cost, null, '', cost),
                  decode(cost, null, '', cost) || '(' ||
                  decode(cost, 0, 0, round((cost - io_cost) / cost * 100)) || ')') || ' ' "COST(%CPU)",
               --decode(cpu_cost, null, '', cpu_cost) || ' ' CPU_COST,
               decode(io_cost, null, '', io_cost) || ' ' IO_COST,
               trim(to_char(round(nvl(time, 0) / 3600), '00')) || ':' ||
               to_char(to_date('19000101', 'yyyymmdd') + nvl(time, 0) / 3600 / 24,
                   'mi:ss') TIME
            from v$sql_plan a,
               (select plan_hash_value, max(child_number) child_number, sql_id
                from v$sql_plan
               where sql_id = vsqlid
               group by sql_id, plan_hash_value) b
           where a.sql_id = b.sql_id
             and a.plan_hash_value = b.plan_hash_value
             and a.plan_hash_value = hashval.plan_hash_value
             and a.child_number = b.child_number
           order by a.plan_hash_value, id asc
          )) loop
		arr_iter := arr_iter+1;
        vPlanAddition(arr_iter) := case when trim(v.predicates)||' ' = ' ' then '' 
            else v.id||' => '||v.predicates || '<br>' end;
        dbms_output.put_line('<tr><td>' || v.ID || '</td><td>' || v.DEPTH ||
                             '</td><td width="400px">' || v.OPERATION || 
               '</td><td>'|| v.NAME || '</td><td>' || v."ROWS" ||
                              '</td><td>' || v.BYTES || '</td><td>' || v."COST(%CPU)" ||
                               '</td><td>' || v.IO_COST || '</td><td>' || v.TIME || '</td></tr>');
    end loop;
    dbms_output.put_line('</table><br>');
    dbms_output.put_line('<p style="font:10pt SimSun,SimSun,SimSun,SimSun">');
    dbms_output.put_line('Predicate Information (identified by operation id):<br>');
    dbms_output.put_line('---------------------------------------------------------------------------<br>');
    arr_iter := 0;
    for v1 in 1..vPlanAddition.count loop
      arr_iter := arr_iter+1;
      dbms_output.put_line(vPlanAddition(arr_iter));
     end loop;
     dbms_output.put_line('<p>');
  end loop;
  dbms_output.put_line('<br>');
  
  ----SQL统计信息(SQL STATISTICS - V$SQLSTATS)
  dbms_output.put_line('<b>SQL STATISTICS- V$SQLPLAN</b>');
  dbms_output.put_line('<table><tr><th>ID</th><th>HASH</th><th>DB_TIME</th><th>MEM</th><th>VERS</th><th>EXES</th><th>DISKS</th><th>GETS</th><th>ROWS</th><th>CPU</th><th>ELAPSED</th><th>CLUSTER_WAIT</th><th>CONCURRENCE_WAIT</th></tr>');
  for v in (select mem.SQL_ID "ID",
         mem.PLAN_HASH_VALUE "HASH",
         mem_dbtime.VAL DB_TIME,
         mem.SHARABLE_MEM MEM,
         mem.VERSION_COUNT VERS,
         mem.EXECUTIONS EXES,
         mem.PARSE_CALLS PARSE_CALLS,
         mem.DISK_READS "DISKS",
         mem.BUFFER_GETS GETS,
         mem.ROWS_PROCESSED "ROWS",
         mem.CPU_TIME "CPU",
         mem.ELAPSED_TIME ELAPSED,
         mem.CLWAIT CLUSTER_WAIT,
         mem.CCWAIT CONCURRENCE_WAIT
      from (select SQL_ID,
             PLAN_HASH_VALUE,
             SHARABLE_MEM,
             VERSION_COUNT,
             FETCHES,
             END_OF_FETCH_COUNT,
             SORTS,
             EXECUTIONS,
             PX_SERVERS_EXECUTIONS PX_SERVERS_EXECS,
             LOADS,
             INVALIDATIONS,
             PARSE_CALLS,
             DISK_READS,
             BUFFER_GETS,
             ROWS_PROCESSED,
             CPU_TIME,
             ELAPSED_TIME,
             CLUSTER_WAIT_TIME     CLWAIT,
             APPLICATION_WAIT_TIME APWAIT,
             CONCURRENCY_WAIT_TIME CCWAIT,
             DIRECT_WRITES,
             PLSQL_EXEC_TIME       PLSEXEC_TIME,
             JAVA_EXEC_TIME        JAVEXEC_TIME
          from v$sqlstats
         where sql_id = vsqlid) mem,(select sum(value) val from v$sysstat where name = 'DB time') mem_dbtime
      ) loop
    dbms_output.put_line('<tr>');
  dbms_output.put_line('<td>'||v."ID"||'</td>');
  dbms_output.put_line('<td>'||v."HASH"||'</td>');
  dbms_output.put_line('<td>'||v.DB_TIME||'</td>');
  dbms_output.put_line('<td>'||v.MEM||'</td>');
  dbms_output.put_line('<td>'||v.VERS||'</td>');
  dbms_output.put_line('<td>'||v.EXES||'</td>');
  dbms_output.put_line('<td>'||v."DISKS"||'</td>');
  dbms_output.put_line('<td>'||v.GETS||'</td>');
  dbms_output.put_line('<td>'||v."ROWS"||'</td>');
  dbms_output.put_line('<td>'||v."CPU"||'</td>');
  dbms_output.put_line('<td>'||v.ELAPSED||'</td>');
  dbms_output.put_line('<td>'||v.CLUSTER_WAIT||'</td>');
  dbms_output.put_line('<td>'||v.CONCURRENCE_WAIT||'</td>');
  dbms_output.put_line('</tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----获取执行计划--AWR
  dbms_output.put_line('<b>Execution Plan From AWR</b><br><br>');
  for hashval in (select distinct plan_hash_value from dba_hist_sql_plan where sql_id = vsqlid) loop
    dbms_output.put_line('SQL:'||vsqlid||', PLAN_HASH_VALUE:'||hashval.plan_hash_value);
    dbms_output.put_line('<table>');
    dbms_output.put_line('<tr><th>ID</th><th>DEP</th><th width="400px">OPERITION</th><th>NAME</th><th>ROWS</th><th>BYTES</th><th>COST(%CPU)</th><th>IO_COST</th><th>TIME</th></tr>');
  vPlanAddition.delete;
  arr_iter := 0;
    for v in (select decode(trim(predicates), '', '' || ID, '*' || ID) ID,
                     DEPTH,
                     OPERATION,
                     NAME,
                     PREDICATES,
                     "ROWS",
                     BYTES,
                     "COST(%CPU)",
                     IO_COST,
                     TIME
                from (select a.plan_hash_value || ' ' plan_hash_value,
               id ID,
               depth DEPTH,
               lpad(operation, length(operation) + depth * 6, ' ') || ' ' || options OPERATION,
               decode(OBJECT_NAME,
                  null,
                  '',
                  '[' || OBJECT_TYPE || ']' || OBJECT_OWNER || '.' ||
                  OBJECT_NAME) || ' ' NAME,
               case
               when (length(access_predicates) < 3 or access_predicates is null) then
                case
                when (length(filter_predicates) < 3 or filter_predicates is null) then
                 ' '
                else
                 '[filter]' || substr(filter_predicates, 1, 3990)
                end
               else
                '[access]' || substr(access_predicates, 1, 3990)
               end PREDICATES,
               decode(cardinality, null, '', cardinality) || ' ' "ROWS",
               decode(Bytes, null, '', Bytes) || ' ' BYTES,
               decode(io_cost,
                  null,
                  decode(cost, null, '', cost),
                  decode(cost, null, '', cost) || '(' ||
                  decode(cost, 0, 0, round((cost - io_cost) / cost * 100)) || ')') || ' ' "COST(%CPU)",
               --decode(cpu_cost, null, '', cpu_cost) || ' ' CPU_COST,
               decode(io_cost, null, '', io_cost) || ' ' IO_COST,
               trim(to_char(round(nvl(time, 0) / 3600), '00')) || ':' ||
               to_char(to_date('19000101', 'yyyymmdd') + nvl(time, 0) / 3600 / 24,
                   'mi:ss') TIME
            from dba_hist_sql_plan a
           where a.sql_id = vsqlid
             and a.plan_hash_value = hashval.plan_hash_value
           order by a.plan_hash_value, id asc
          )) loop
    /*AWR里没有Predicate信息
    arr_iter := arr_iter+1;
        vPlanAddition(arr_iter) := case when trim(v.predicates)||' ' = ' ' then '' 
            else '        '|| v.id||' => '||v.predicates || '<br>' end;
    */
        dbms_output.put_line('<tr><td>' || v.ID || '</td><td>' || v.DEPTH ||
                             '</td><td width="400px">' || v.OPERATION || 
               '</td><td>'|| v.NAME || '</td><td>' || v."ROWS" ||
                              '</td><td>' || v.BYTES || '</td><td>' || v."COST(%CPU)" ||
                               '</td><td>' || v.IO_COST || '</td><td>' || v.TIME || '</td></tr>');
      end loop;
    dbms_output.put_line('</table><br>');
  /*AWR里没有Predicate信息
  dbms_output.put_line('<p style="font:10pt SimSun,SimSun,SimSun,SimSun">');
  dbms_output.put_line('    Predicate Information (identified by operation id):<br>');
  dbms_output.put_line('    ---------------------------------------------------------------------------<br>');
  arr_iter := 0;
  for v1 in 1..vPlanAddition.count loop
    arr_iter := arr_iter+1;
    dbms_output.put_line(vPlanAddition(arr_iter));
  end loop;
  */
  dbms_output.put_line('<p>');
  end loop;

/*
  ----SQL统计信息(SQL STATISTICS - AWR)
  dbms_output.put_line('<b>SQL STATISTICS</b>');
  dbms_output.put_line('<table><tr><th>ID</th><th>HASH</th><th>DB_TIME_TOTAL</th><th>DB_TIME_CURRENT</th><th>MEM</th><th>VERS</th><th>EXES</th><th>DISKS</th><th>GETS</th><th>ROWS</th><th>CPU</th><th>ELAPSED</th><th>CCWAIT</th></tr>');
  for v in (select mem.SQL_ID "ID",
         mem.PLAN_HASH_VALUE "HASH",
         mem_dbtime.VAL - awr_dbtime.VAL DB_TIME_TOTAL,
         mem_dbtime.VAL - (select max(value) VAL
                   from dba_hist_sysstat
                  where stat_name = 'DB time') DB_TIME_CURRENT,
         mem.SHARABLE_MEM MEM,
         mem.VERSION_COUNT VERS,
         mem.EXECUTIONS - awr.EXECUTIONS EXES,
         mem.PARSE_CALLS - awr.PARSE_CALLS PARSE_CALLS,
         mem.DISK_READS - awr.DISK_READS "DISKS",
         mem.BUFFER_GETS - awr.BUFFER_GETS GETS,
         mem.ROWS_PROCESSED - awr.ROWS_PROCESSED "ROWS",
         mem.CPU_TIME - awr.CPU_TIME "CPU",
         mem.ELAPSED_TIME - awr.ELAPSED_TIME ELAPSED,
         mem.CCWAIT - awr.CCWAIT CCWAIT
      from (select SQL_ID,
             PLAN_HASH_VALUE,
             SHARABLE_MEM,
             VERSION_COUNT,
             FETCHES,
             END_OF_FETCH_COUNT,
             SORTS,
             EXECUTIONS,
             PX_SERVERS_EXECUTIONS PX_SERVERS_EXECS,
             LOADS,
             INVALIDATIONS,
             PARSE_CALLS,
             DISK_READS,
             BUFFER_GETS,
             ROWS_PROCESSED,
             CPU_TIME,
             ELAPSED_TIME,
             --IOWAIT,
             CLUSTER_WAIT_TIME     CLWAIT,
             APPLICATION_WAIT_TIME APWAIT,
             CONCURRENCY_WAIT_TIME CCWAIT,
             DIRECT_WRITES,
             PLSQL_EXEC_TIME       PLSEXEC_TIME,
             JAVA_EXEC_TIME        JAVEXEC_TIME
          from v$sqlstats
         where sql_id = vsqlid) mem,
         (select max(SNAP_ID) SNAP_ID,
             SQL_ID,
             PLAN_HASH_VALUE,
             max(SHARABLE_MEM) SHARABLE_MEM,
             max(VERSION_COUNT) VERSION_COUNT,
             max(FETCHES_TOTAL) FETCHES,
             max(END_OF_FETCH_COUNT_TOTAL) END_OF_FETCH_COUNT,
             max(SORTS_TOTAL) SORTS,
             max(EXECUTIONS_TOTAL) EXECUTIONS,
             max(PX_SERVERS_EXECS_TOTAL) PX_SERVERS_EXECS,
             max(LOADS_TOTAL) LOADS,
             max(INVALIDATIONS_TOTAL) INVALIDATIONS,
             max(PARSE_CALLS_TOTAL) PARSE_CALLS,
             max(DISK_READS_TOTAL) DISK_READS,
             max(BUFFER_GETS_TOTAL) BUFFER_GETS,
             max(ROWS_PROCESSED_TOTAL) ROWS_PROCESSED,
             max(CPU_TIME_TOTAL) CPU_TIME,
             max(ELAPSED_TIME_TOTAL) ELAPSED_TIME,
             max(CLWAIT_TOTAL) CLWAIT,
             max(APWAIT_TOTAL) APWAIT,
             max(CCWAIT_TOTAL) CCWAIT,
             max(DIRECT_WRITES_TOTAL) DIRECT_WRITES,
             max(PLSEXEC_TIME_TOTAL) PLSEXEC_TIME,
             max(JAVEXEC_TIME_TOTAL) JAVEXEC_TIME
          from dba_hist_sqlstat
         where snap_id >
             (select min(snap_id)
              from dba_hist_snapshot
             where startup_time =
                 (select max(startup_time) from dba_hist_snapshot))
           and sql_id = vsqlid
         group by sql_id, plan_hash_value) awr,
         (select sum(value) val from v$sysstat where name = 'DB time') mem_dbtime,
         (select a.snap_id, a.value val
          from dba_hist_sysstat a
         where a.snap_id >
             (select min(snap_id)
              from dba_hist_snapshot
             where startup_time =
                 (select max(startup_time) from dba_hist_snapshot))
           and a.stat_name = 'DB time') awr_dbtime
     where awr.sql_id(+) = mem.sql_id
       and awr.plan_hash_value(+) = mem.plan_hash_value
       and awr.snap_id = awr_dbtime.snap_id
      ) loop
    dbms_output.put_line('<tr>');
  dbms_output.put_line('<td>'||v."ID"||'</td>');
  dbms_output.put_line('<td>'||v."HASH"||'</td>');
  dbms_output.put_line('<td>'||v.DB_TIME_TOTAL||'</td>');
  dbms_output.put_line('<td>'||v.DB_TIME_CURRENT||'</td>');
  dbms_output.put_line('<td>'||v.MEM||'</td>');
  dbms_output.put_line('<td>'||v.VERS||'</td>');
  dbms_output.put_line('<td>'||v.EXES||'</td>');
  dbms_output.put_line('<td>'||v."DISKS"||'</td>');
  dbms_output.put_line('<td>'||v.GETS||'</td>');
  dbms_output.put_line('<td>'||v."ROWS"||'</td>');
  dbms_output.put_line('<td>'||v."CPU"||'</td>');
  dbms_output.put_line('<td>'||v.ELAPSED||'</td>');
  dbms_output.put_line('<td>'||v.CCWAIT||'</td>');
  dbms_output.put_line('</tr>');
  end loop;
  dbms_output.put_line('</table></br>');
*/

  ----获取SQL语句所涉及的表
  vOwnerCnt := 0;
  vOwnerstr := '';
  vTableCnt := 0;
  vTablestr := '';
  for v in (select OBJECT_OWNER, object_name
              from v$sql_plan
             where sql_id = vsqlid
               and operation like '%TABLE%'
       union
      select OBJECT_OWNER, object_name from dba_hist_sql_plan
       where sql_id = vsqlid
               and operation like '%TABLE%'
	   union
	  select OBJECT_OWNER, object_name from PLAN_TABLE
	   where operation like '%TABLE%'
      ) loop
    vTablestr := vTablestr || v.OBJECT_NAME || ',';
    vTableCnt := vTableCnt + 1;
    vOwnerstr := vOwnerstr || v.OBJECT_OWNER || ',';
    vOwnerCnt := vOwnerCnt + 1;
  end loop;
  vOwnerstr := substr(vOwnerstr, 1, length(vOwnerstr) - 1);
  vTablestr := substr(vTablestr, 1, length(vTablestr) - 1);
  
  ----SQL涉及所有表的尺寸(Table Segment Size)
  dbms_output.put_line('<b>Table Segment Size</b>');
  dbms_output.put_line('<table><tr><th>owner</th><th>segment_name</th><th>MB</th>');
  for v in (select owner, segment_name, to_char(sum(bytes) / 1024 / 1024, '9999990.99') MB
              from dba_segments
             where segment_name in
                   (SELECT REGEXP_SUBSTR(vTablestr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vTableCnt)
					and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
             group by owner, segment_name
             order by owner, segment_name) loop
    dbms_output.put_line('<tr><td>' || v.OWNER || '</td><td>' ||
                         v.segment_name || '</td><td>' || v.MB ||
                         '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----SQL涉及所有表的相关信息(Table Statistics)
  dbms_output.put_line('<b>Table Statistics</b>');
  dbms_output.put_line('<table><tr>' || '<th>OWNER</th>' ||
                       '<th>table_name</th>' || '<th>num_rows</th>' ||
                       '<th>blocks</th>' || '<th>degree</th>' ||
                       '<th>last_analyzed</th>' || '<th>temporary</th>' ||
                       '<th>partitioned</th>' || '<th>pct_free</th>' ||
                       '<th>tablespace_name</th>');
  for v in (select t.OWNER,
                   t.table_name,
                   t.num_rows,
                   t.blocks,
                   t.degree,
                   t.last_analyzed,
                   t.temporary,
                   t.partitioned,
                   t.pct_free,
                   t.tablespace_name
              from dba_tables t
             where table_name in
                   (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vTableCnt)
               and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
             order by owner, table_name) loop
    dbms_output.put_line('<tr><td>' || v.OWNER || '</td><td>' ||
                         v.table_name || '</td><td>' || v.num_rows ||
                         '</td><td>' || v.blocks || '</td><td>' ||
                         v.degree || '</td><td>' || v.last_analyzed ||
                         '</td><td>' || v.temporary || '</td><td>' ||
                         v.partitioned || '</td><td>' || v.pct_free ||
                         '</td><td>' || v.tablespace_name || '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>');

  ----SQL涉及所有表的列信息(Table Column Statistics)
  dbms_output.put_line('<b>Table Column Statistics</b>');
  dbms_output.put_line('<table><tr>' || '<th>OWNER</th>' ||
                       '<th>table_name</th>' || '<th>column_name</th>' ||
                       '<th>data_type</th>' || '<th>nullable</th>' ||
                       '<th>last_analyzed</th>' || '<th>avg_col_len</th></tr>');
  for v in (select owner,
                   table_name,
                   column_name,
                   data_type,
                   nullable,
                   to_char(last_analyzed, 'mm/dd/yy hh24:mi:ss') analyzed,
                   avg_col_len
              from dba_tab_cols
             where table_name in (SELECT REGEXP_SUBSTR(vTABLESTR, '[^,]+', 1, LEVEL) AS value_str
                                    FROM DUAL
                                  CONNECT BY LEVEL <= vTABLECNT)
               and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
          order by owner, table_name, column_name) loop
    dbms_output.put_line('<tr><td>' || v.OWNER || '</td><td>' ||
                         v.table_name || '</td><td>' || v.column_name ||
                         '</td><td>' || v.data_type || '</td><td>' ||
                         v.nullable || '</td><td>' || v.analyzed ||
                         '</td><td>' || v.avg_col_len || '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>'); 

  ----SQL涉及所有表的触发器信息(Table Triggers)
  dbms_output.put_line('<b>Table Triggers</b>');
  dbms_output.put_line('<table><tr>' || '<th>table_owner</th>' ||
                       '<th>table_name</th>' || '<th>base_object_type</th>' ||
                       '<th>tiggger_owner</th>' || '<th>trigger_name</th>' ||
                       '<th>trigger_type</th>' || '<th>triggering_event</th></tr>');
  for v in (select table_owner,
                   table_name,
                   base_object_type,
                   owner tiggger_owner,
                   trigger_name,
                   trigger_type,
                   triggering_event
              from dba_triggers
             where table_name in (SELECT REGEXP_SUBSTR(vTABLESTR, '[^,]+', 1, LEVEL) AS value_str
                                    FROM DUAL
                                  CONNECT BY LEVEL <= vTABLECNT)
               and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
             order by table_owner, table_name) loop
    dbms_output.put_line('<tr><td>' || v.table_owner || '</td><td>' ||
                         v.table_name || '</td><td>' || v.base_object_type ||
                         '</td><td>' || v.tiggger_owner || '</td><td>' ||
                         v.trigger_name || '</td><td>' || v.trigger_type ||
                         '</td><td>' || v.triggering_event || '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>'); 
  
  ----SQL涉及的分区表的相关信息(Partition Statistics)
  dbms_output.put_line('<b>Partition Statistics</b>');
  dbms_output.put_line('<table><tr>' || '<th>OWNER</th>' ||
                       '<th>table_name</th>' ||
                       '<th>partitioning_type</th>' ||
                       '<th>partition_count</th>');
  for v in (select t.owner,
                   t.table_name,
                   t.partitioning_type,
                   t.partition_count
              from dba_part_tables t
             where table_name in
                   (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vtablecnt)
               and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)) loop
    dbms_output.put_line('<tr><td>' || v.OWNER || '</td><td>' ||
                         v.table_name || '</td><td>' ||
                         v.partitioning_type || '</td><td>' ||
                         v.partition_count || '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----分区表的分区列相关信息(Partition Key Statistics)
  dbms_output.put_line('<b>Partition Key Statistics</b>');
  dbms_output.put_line('<table><tr>' || '<th>owner</th>' ||
                       '<th>name</th>' || '<th>object_type</th>' ||
                       '<th>column_name</th>');
  for v in (select owner, name, object_type, column_name
              from dba_part_key_columns
             where name in (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                              FROM DUAL
                            CONNECT BY LEVEL <= vtablecnt)
               and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)) loop
    dbms_output.put_line('<tr><td>' || v.OWNER || '</td><td>' || v.name ||
                         '</td><td>' || v.object_type || '</td><td>' ||
                         v.column_name || '</td></tr>');
  end loop;
  dbms_output.put_line('</table>');
  
  ----分区表分区范围信息(Partition Range Statistics)
  dbms_output.put_line('<b>Partition Range Statistics</b>');
  dbms_output.put_line('<table><tr>' || '<th>owner</th>' ||
                       '<th>table_name</th>' || '<th>partition_name</th>' ||
                       '<th>high_value</th>' || '<th>tablespace_name</th>');
  for v in (SELECT table_owner owner,
                   table_name,
                   partition_name,
                   high_value,
                   tablespace_name
              FROM dba_tab_partitions t
             where table_name in
                   (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vtablecnt)
               and table_owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
             order by table_owner, table_name, t.partition_position) loop
    dbms_output.put_line('<tr><td>' || v.OWNER || '</td><td>' ||
                         v.table_name || '</td><td>' || v.partition_name ||
                         '</td><td>' || v.high_value || '</td><td>' ||
                         v.tablespace_name || '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----索引的大小(Index Segments)
  dbms_output.put_line('<b>Index Segments</b>');
  dbms_output.put_line('<table><tr>' || '<th>OWNER</th>' ||
                       '<th>table_name</th>' || '<th>segment_name</th>' ||
                       '<th>MB</th></tr>');
  for v in (select t1.owner,
                   t2.table_name,
                   t1.segment_name,
                   to_char(sum(t1.bytes) / 1024 / 1024, '9999990.99') MB
              from dba_segments t1, dba_indexes t2
             where t1.segment_name = t2.index_name
               and t1.segment_type like '%INDEX%'
			   and t1.owner = t2.owner
               and t2.table_name in
                   (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vtablecnt)
               and t1.owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
			   and t2.owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
             group by t1.owner, t2.table_name, t1.segment_name
             order by owner, table_name) loop
    dbms_output.put_line('<tr><td>' || v.owner || '</td><td>' ||
                         v.table_name || '</td><td>' || v.segment_name ||
                         '</td><td>' || v.MB || '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----索引相关信息(Index Statistics)
  dbms_output.put_line('<b>Index Statistics</b>');
  dbms_output.put_line('<table><tr>' || '<th>OWNER</th>' ||
                       '<th>table_name</th>' || '<th>name</th>' ||
                       '<th>rows</th>' || '<th>type</th>' ||
                       '<th>status</th>' || '<th>factor</th>' ||
                       '<th>blevel</th>' || '<th>distinct</th>' ||
                       '<th>leaf</th>' || '<th>unique</th>' ||
                       '<th>degree</th>' || '<th>analyzed</th></tr>');
  for v in (select t.owner,
                   t.table_name,
                   t.index_name        "name",
                   t.num_rows          "rows",
                   t.index_type        "type",
                   t.status,
                   t.clustering_factor factor,
                   t.blevel,
                   t.distinct_keys     "distinct",
                   t.leaf_blocks       leaf,
                   t.uniqueness        "unique",
                   t.degree,
                   to_char(t.last_analyzed, 'mm/dd/yy hh24:mi:ss') analyzed
              from dba_indexes t
             where table_name in
                   (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vtablecnt)
               and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
             order by owner, table_name) loop
    dbms_output.put_line('<tr><td>' || v.owner || '</td><td>' ||
                         v.table_name || '</td><td>' || v."name" ||
                         '</td><td>' || v."rows" || '</td><td>' ||
                         v."type" || '</td><td>' || v.status ||
                         '</td><td>' || v.factor || '</td><td>' ||
                         v.blevel || '</td><td>' || v."distinct" ||
                         '</td><td>' || v.leaf || '</td><td>' ||
                         v."unique" || '</td><td>' || v.degree ||
                         '</td><td>' || v.analyzed || '</td><tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----索引列信息,在哪些列有索引(Index columns)
  dbms_output.put_line('<b>Index columns</b>');
  dbms_output.put_line('<table><tr>' || '<th>OWNER</th>' ||
                       '<th>table_name</th>' || '<th>table_name</th>' ||
                       '<th>column_name</th>' ||
                       '<th>column_position</th>' ||
                       '<th>DESCEND</th></tr>');
  for v in (select t.index_owner owner,
                   t.table_name,
                   t.index_name,
                   t.column_name,
                   t.column_position,
                   t.DESCEND
              from dba_ind_columns t
             where table_name in
                   (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vtablecnt)
               and index_owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
             order by owner, table_name, index_name, column_position) loop
    dbms_output.put_line('<tr><td>' || v.owner || '</td><td>' ||
                         v.table_name || '</td><td>' || v.index_name ||
                         '</td><td>' || v.column_name || '</td><td>' ||
                         v.column_position || '</td><td>' || v.DESCEND ||
                         '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----分区索引的分区个数(Partition Indexes nums)
  dbms_output.put_line('<b>Partition Indexes Summary</b>');
  dbms_output.put_line('<table><tr>' || '<th>OWNER</th>' ||
                       '<th>table_name</th>' || '<th>table_name</th>' ||
                       '<th>partitioning_type</th>' ||
                       '<th>partition_count</th></tr>');
  for v in (select owner,
                   table_name,
                   index_name,
                   partitioning_type,
                   partition_count
              from dba_part_indexes
             where table_name in
                   (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vtablecnt)
               and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                      FROM DUAL
                    CONNECT BY LEVEL <= vOwnerCnt)
             order by owner, table_name, index_name) loop
    dbms_output.put_line('<tr><td>' || v.owner || '</td><td>' ||
                         v.table_name || '</td><td>' || v.index_name ||
                         '</td><td>' || v.partitioning_type || '</td><td>' ||
                         v.partition_count || '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----分区索引的详细信息(Partition Indexes details)
  dbms_output.put_line('<b>Partition Indexes Details</b>');
  dbms_output.put_line('<table><tr>' || '<th>OWNER</th>' ||
                       '<th>index_name</th>' || '<th>partition_name</th>' ||
                       '<th>status</th>' || '<th>blevel</th>' ||
                       '<th>leaf_blocks</th>' ||
                       '<th>tablespace_name</th></tr>');
  for v in (select index_owner owner,
                   index_name,
                   partition_name,
                   status,
                   blevel,
                   leaf_blocks,
                   tablespace_name
              from dba_ind_partitions
             where index_name in
                   (select index_name
                      from dba_indexes
                     where table_name in
                           (SELECT REGEXP_SUBSTR(vtablestr, '[^,]+', 1, LEVEL) AS value_str
                              FROM DUAL
                            CONNECT BY LEVEL <= vtablecnt)
					   and owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
							  FROM DUAL
							CONNECT BY LEVEL <= vOwnerCnt))
			   and index_owner in (SELECT REGEXP_SUBSTR(vOwnerstr, '[^,]+', 1, LEVEL) AS value_str
                               FROM DUAL
				   CONNECT BY LEVEL <= vOwnerCnt)
             order by owner, index_name, partition_name) loop
    dbms_output.put_line('<tr><td>' || v.owner || '</td><td>' ||
                         v.index_name || '</td><td>' || v.partition_name ||
                         '</td><td>' || v.status || '</td><td>' ||
                         '</td><td>' || v.blevel || '</td><td>' ||
                         '</td><td>' || v.leaf_blocks || '</td><td>' ||
                         '</td><td>' || v.tablespace_name || '</td></tr>');
  end loop;
  dbms_output.put_line('</table></br>');
  
  ----嵌入awrsqrpt
  dbms_output.put_line('<b>Awrsqrpt Contents</b>');
  dbms_output.put_line('<div>');
  begin
    for v in (select max(maxsnap_id) maxsnap_id,
                     max(maxsnap_id) - 1 as minsnap_id
                from (select startup_time,
                             max(a.snap_id) maxsnap_id,
                             min(a.snap_id) minsnap_id
                        from dba_hist_snapshot a, dba_hist_sqlstat b
                       where a.snap_id = b.snap_id
                         and b.sql_id = vsqlid
                       group by startup_time)
               where maxsnap_id <> minsnap_id) loop
      dbms_output.put_line('<div>');
	  begin
		for v_in in (select output
                     from table(dbms_workload_repository.awr_sql_report_html((select dbid
                                                                               from v$database
                                                                              where rownum = 1),
                                                                             (select instance_number
                                                                                from v$instance
                                                                               where rownum = 1),
                                                                             v.minsnap_id,
                                                                             v.maxsnap_id,
                                                                             vsqlid))) loop
		  dbms_output.put_line(v_in.output);
		end loop;
	  Exception
      when others then
        vsqlmsg := sqlerrm;
		dbms_output.put_line('在DBA_HIST_XXXX中找不到SQL:' || vsqlid || '的信息.');
        dbms_output.put_line(vsqlmsg);
	  end;
      dbms_output.put_line('</div>');
    end loop;
  Exception
    when others then
      vsqlmsg := sqlerrm;
      dbms_output.put_line(vsqlmsg);
  end;
  dbms_output.put_line('</div>');
  
  dbms_output.put_line('</body></html>');
  rollback;
end;
/
set termout on
spool off;
exit

执行脚本,此脚本需要SQL_ID

[oracle@orasql ~]$ sqlplus / as sysdba

SQL> @spoolsql.sql
"input sqlid:"
Enter value for sql_id: 5fy6m249h2kr5

./5fy6m249h2kr5.html
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
有人就有江湖,有江湖就有IT系统,有IT系统就有数据库,有数据库就有SQLSQL应用可一字概括:“广”。加之其简单易学,SQL实现也可一字概括:“乐”。, 然而,SQL虽然实现简单可乐,却极易引发性能问题,那时广大SQL使用人员可要“愁”就一个字,心碎无数次了。, 缘何有性能问题?原因也一字概括:“量”。当系统数据量、并发访问量上去后,不良SQL就会拖跨整个系统,我们甚至找不出哪些SQL影响了系统。即便找到也不知如何动手优化。此时的心情也可以一字概括:“懵”。, 现在《收获,不止SQL优化——抓住SQL的本质》开始带你抛除烦恼,走进优化的可乐世界!, 首先教你SQL整体优化、快速优化实施、如何读懂执行计划、如何左右执行计划这四大必杀招。整这些干嘛呢?答案是,传授一个先整体后局部的宏观解决思路,走进“道”的世界。, 接下来带领大家飞翔在“术”的天空。教你体系结构、逻辑结构、表设计、索引设计、表连接这五大要领。这么多套路,这又是要干嘛?别急,这是教你如何解决问题,准确地说,是如何不改写即完成SQL优化。, 随后《收获,不止SQL优化——抓住SQL的本质》指引大家学会等价改写、过程包优化、高级SQL、分析函数、需求优化这些相关的五大神功。有点头晕,能否少一点套路?淡定,这还是“术”的范畴,依然是教你如何解决问题,只不过这次是如何改写SQL完成优化。, 最后一个章节没套路了,其中跟随你多年的错误认识是否让你怀疑人生,其中让SQL跑得更慢的观点,是否让你三观尽毁?, 再多一点真诚吧,《收获,不止SQL优化——抓住SQL的本质》提供扫二维码辅助学习,是不是心被笔者给暖到了?, 读完全书,来,合上书本,闭上眼睛,深呼吸,用心来感受SQL优化的世界。, 一个字:“爽”!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值