码迷,mamicode.com
首页 > 数据库 > 详细

printsql.sql 打印对应spid或sid所对应的sql以及其执行计划

时间:2015-01-22 15:07:48      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:

/* 打印对应spid或sid所对应的sql以及其执行计划 */
CREATE OR REPLACE PROCEDURE PRINTSQL (i_n_id        IN NUMBER,
                                      i_vc_idtype   IN VARCHAR2)
IS
   /*
   功能: 打印对应spid或sid所对应的sql以及其执行计划
   作者: 老熊,dbsnake
   创建日期:2010-11-12

   输入参数:
   i_n_id: 输入的spid或sid
   i_vc_idtype : 输入的ID的类型,‘SPID‘表示输入的是spid,‘SID‘表示输入的是sid.

   输出参数:
   无

   输入输出参数:
   无

   调用到的存储过程:
   无
[oracle@txy ~]$ ps -ef | grep 2837
oracle    2837  2724 24 16:21 pts/2    00:00:12 sqlplus            
oracle    2839  2837  0 16:21 ?        00:00:00 oracleorcl (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
oracle    2896  2866  0 16:22 pts/3    00:00:00 grep 2837

set serveroutput on size 1000000
--传入 2839 注意传入的是SPID 不是 PID
exec PRINTSQL(2839,‘SPID‘)
   
其中会吧alter system kill session ‘138,8628‘ immediate; 打印出来
   */

   o_vc_return_flag         VARCHAR2 (4000);

   TYPE typsqltext IS TABLE OF VARCHAR2 (1000)
      INDEX BY BINARY_INTEGER;

   typsqltexts              typsqltext;

   vc_paddr                 VARCHAR2 (4000);
   n_hashvalue              NUMBER;
   n_childnumber            NUMBER;
   rec_session              v$session%ROWTYPE;
   rec_sessionwait          v$session_wait%ROWTYPE;
   rec_sql                  v$sql%ROWTYPE;

   /*select hash_value,child_number,plan_hash_value,executions,buffer_gets,buffer_gets/decode(executions,0,1,executions) gets_per_exec,
   rows_processed,rows_processed/decode(executions,0,1,executions) rows_per_exec,
   disk_reads,disk_reads/decode(executions,0,1,executions)  reads_per_exec,
   cpu_time/1000000 cpu_time,cpu_time/decode(executions,0,1,executions)/1000000 cpu_per_exec,
   ELAPSED_TIME/1000000 ELAPSED_TIME,ELAPSED_TIME/decode(executions,0,1,executions)/1000000 ela_per_exec
   from v$sql where hash_value=&1
   and rownum<=100;*/

   TYPE type_hash_value IS TABLE OF v$sql.HASH_VALUE%TYPE
      INDEX BY BINARY_INTEGER;

   hash_values              type_hash_value;

   TYPE type_child_number IS TABLE OF v$sql.CHILD_NUMBER%TYPE
      INDEX BY BINARY_INTEGER;

   child_numbers            type_child_number;

   TYPE type_plan_hash_value IS TABLE OF v$sql.PLAN_HASH_VALUE%TYPE
      INDEX BY BINARY_INTEGER;

   plan_hash_values         type_plan_hash_value;

   TYPE type_execution IS TABLE OF v$sql.EXECUTIONS%TYPE
      INDEX BY BINARY_INTEGER;

   executions               type_execution;

   TYPE type_buffer_get IS TABLE OF v$sql.BUFFER_GETS%TYPE
      INDEX BY BINARY_INTEGER;

   buffer_gets              type_buffer_get;

   TYPE type_gets_per_exec IS TABLE OF v$sql.BUFFER_GETS%TYPE
      INDEX BY BINARY_INTEGER;

   gets_per_execs           type_gets_per_exec;

   TYPE type_rows_processed IS TABLE OF v$sql.ROWS_PROCESSED%TYPE
      INDEX BY BINARY_INTEGER;

   rows_processeds          type_rows_processed;

   TYPE type_rows_per_exec IS TABLE OF v$sql.ROWS_PROCESSED%TYPE
      INDEX BY BINARY_INTEGER;

   rows_per_execs           type_rows_per_exec;

   TYPE type_disk_read IS TABLE OF v$sql.DISK_READS%TYPE
      INDEX BY BINARY_INTEGER;

   disk_reads               type_disk_read;

   TYPE type_reads_per_exec IS TABLE OF v$sql.DISK_READS%TYPE
      INDEX BY BINARY_INTEGER;

   reads_per_execs          type_reads_per_exec;

   TYPE type_cpu_time IS TABLE OF v$sql.CPU_TIME%TYPE
      INDEX BY BINARY_INTEGER;

   cpu_times                type_cpu_time;

   TYPE type_cpu_per_exec IS TABLE OF v$sql.CPU_TIME%TYPE
      INDEX BY BINARY_INTEGER;

   cpu_per_execs            type_cpu_per_exec;

   TYPE type_ELAPSED_TIME IS TABLE OF v$sql.ELAPSED_TIME%TYPE
      INDEX BY BINARY_INTEGER;

   ELAPSED_TIMEs            type_ELAPSED_TIME;

   TYPE type_ela_per_exec IS TABLE OF v$sql.ELAPSED_TIME%TYPE
      INDEX BY BINARY_INTEGER;

   ela_per_execs            type_ela_per_exec;


   -- cursor c_display_cursor(in_address varchar2, in_hash_value number, in_child_number number) is
   s_display_cursor         VARCHAR2 (32767)
      := ‘ 
select case when access_predicates is not null or filter_predicates is not null then ‘
‘*‘‘ else ‘‘ ‘‘ end || substr(to_char(id, ‘‘999‘‘), -3) as p_id, 
lpad(‘
‘ ‘‘, depth) || operation || ‘‘ ‘‘ || options as operation, 
object_name as name, 
starts, 
cardinality as e_rows, 
outrows as a_rows, 
to_char(to_number(substr(e_time_interval, 2, 9)) * 24 + to_number(substr(e_time_interval, 12, 2)), ‘
‘FM900‘‘) || substr(e_time_interval, 14, 9) as a_time, 
crgets + cugets as buffers, 
case reads when 0 then null else reads end as reads, 
case writes when 0 then null else writes end as writes, 
case other_tag 
when ‘
‘PARALLEL_TO_SERIAL‘‘ then ‘‘P->S‘‘ 
when ‘
‘PARALLEL_COMBINED_WITH_PARENT‘‘ then ‘‘PCWP‘‘ 
when ‘
‘PARALLEL_COMBINED_WITH_CHILD‘‘ then ‘‘PCWC‘‘ 
when ‘
‘SERIAL_TO_PARALLEL‘‘ then ‘‘S->P‘‘ 
when ‘
‘PARALLEL_TO_PARALLEL‘‘ then ‘‘P->P‘‘ 
when ‘
‘PARALLEL_FROM_SERIAL‘‘ then ‘‘P<-S‘‘ 
else other_tag end as in_out, 
partition_start, 
partition_stop, 
distribution, 
mem_opt, 
mem_one, 
last_mem_used || case last_mem_usage when ‘
‘OPTIMAL‘‘ then ‘‘ (0)‘‘ when ‘‘ONE PASS‘‘ then ‘‘ (1)‘‘ when ‘‘MULTI-PASS‘‘ then ‘‘ (M)‘‘ end, 
case last_degree when 0 then null when 1 then null else last_degree end as last_degree, 
--opt_cnt, 
--one_cnt, 
--multi_cnt, 
--max_tmp, 
last_tmp, 
access_predicates, 
filter_predicates, 
dynamic_sampling_flag, 
id 
from ( 
SELECT /*+ opt_param(‘
‘parallel_execution_enabled‘‘, ‘‘false‘‘) */ 
                      id, position, depth , operation, options, object_name, cardinality, bytes, temp_space, cost, io_cost, 
                      cpu_cost, partition_start, partition_stop, object_node, other_tag, distribution, null, access_predicates, filter_predicates, 
                      null, null, null, starts, outrows, crgets, cugets, reads, writes, etime, e_time_interval, mem_opt, mem_one, last_mem_used, last_degree, last_mem_usage, 
                      opt_cnt, one_cnt, multi_cnt, max_tmp, last_tmp, dynamic_sampling_flag from ( 
                          select /*+ no_merge */ 
                          id, depth, position, operation, options, 
                          cost, cardinality, bytes, object_node, 
                          object_name, other_tag, partition_start, 
                          partition_stop, distribution, temp_space, io_cost, 
                          cpu_cost, filter_predicates, access_predicates, other, 
                          last_starts starts, 
                                    last_output_rows outrows, 
                                    last_cr_buffer_gets crgets, 
                                    last_cu_buffer_gets cugets, 
                                    last_disk_reads reads, 
                                    last_disk_writes writes, 
                                    last_elapsed_time etime, 
                                    to_char(numtodsinterval(round(last_elapsed_time/10000)*10000/1000000, ‘
‘SECOND‘‘)) as e_time_interval, 
                                    estimated_optimal_size mem_opt, 
                                    estimated_onepass_size mem_one, 
                                    last_memory_used last_mem_used, 
                                    last_degree, 
                                    last_execution last_mem_usage, 
                                    optimal_executions opt_cnt, 
                                    onepass_executions one_cnt, 
                                    multipasses_executions multi_cnt, 
                                    max_tempseg_size max_tmp, 
                                    last_tempseg_size last_tmp, 
                                    case 0 /*instr(other_xml, ‘
‘dynamic_sampling‘‘)*/ when 0 then NULL else ‘‘YES‘‘ end as dynamic_sampling_flag 
              from V$SQL_PLAN_STATISTICS_ALL vp 
              --where address = hextoraw(:in_address) 
              where hash_value = :in_hash_value 
              and child_number = :in_child_number) 

order by id‘
;

   s_display_cursor2        VARCHAR2 (32767)
      := ‘ 
select case when access_predicates is not null or filter_predicates is not null then ‘
‘*‘‘ else ‘‘ ‘‘ end || substr(to_char(id, ‘‘999‘‘), -3) as p_id, 
lpad(‘
‘ ‘‘, depth) || operation || ‘‘ ‘‘ || options as operation, 
object_name as name, 
cardinality as e_rows, 
bytes, 
temp_space, 
cost, 
cpu_cost, 
object_node, 
case other_tag 
when ‘
‘PARALLEL_TO_SERIAL‘‘ then ‘‘P->S‘‘ 
when ‘
‘PARALLEL_COMBINED_WITH_PARENT‘‘ then ‘‘PCWP‘‘ 
when ‘
‘PARALLEL_COMBINED_WITH_CHILD‘‘ then ‘‘PCWC‘‘ 
when ‘
‘SERIAL_TO_PARALLEL‘‘ then ‘‘S->P‘‘ 
when ‘
‘PARALLEL_TO_PARALLEL‘‘ then ‘‘P->P‘‘ 
when ‘
‘PARALLEL_FROM_SERIAL‘‘ then ‘‘P<-S‘‘ 
else other_tag end as in_out, 
partition_start, 
partition_stop, 
distribution, 
access_predicates, 
filter_predicates, 
dynamic_sampling_flag, 
id 
from ( 
SELECT /*+ opt_param(‘
‘parallel_execution_enabled‘‘, ‘‘false‘‘) */ 
                      id, position, depth , operation, options, object_name, cardinality, bytes, temp_space, cost, io_cost, 
                      cpu_cost, partition_start, partition_stop, object_node, other_tag, distribution, null, access_predicates, filter_predicates, 
                      null, null, null, starts, outrows, crgets, cugets, reads, writes, etime, e_time_interval, mem_opt, mem_one, last_mem_used, last_degree, last_mem_usage, 
                      opt_cnt, one_cnt, multi_cnt, max_tmp, last_tmp, dynamic_sampling_flag from ( 
                          select /*+ no_merge */ 
                          id, depth, position, operation, options, 
                          cost, cardinality, bytes, object_node, 
                          object_name, other_tag, partition_start, 
                          partition_stop, distribution, temp_space, io_cost, 
                          cpu_cost, filter_predicates, access_predicates, other, 
                          0 starts, 
                                    0 outrows, 
                                    0 crgets, 
                                    0 cugets, 
                                    0 reads, 
                                    0 writes, 
                                    0 etime, 
                                    0 e_time_interval, 
                                    0 mem_opt, 
                                    0 mem_one, 
                                    null last_mem_used, 
                                    0 last_degree, 
                                    null last_mem_usage, 
                                    0 opt_cnt, 
                                    0 one_cnt, 
                                    0 multi_cnt, 
                                    0 max_tmp, 
                                    0 last_tmp, 
                                    case 0 /*instr(other_xml, ‘
‘dynamic_sampling‘‘)*/ when 0 then NULL else ‘‘YES‘‘ end as dynamic_sampling_flag 
              from V$SQL_PLAN vp 
              --where address = hextoraw(:in_address) 
              where hash_value = :in_hash_value 
              and child_number = :in_child_number) 

order by id‘
;

   TYPE t_list_varchar2 IS TABLE OF VARCHAR2 (4000)
      INDEX BY PLS_INTEGER;

   TYPE t_column_record IS RECORD
   (
      a_data        t_list_varchar2,
      b_has_data    BOOLEAN,
      s_heading     VARCHAR2 (255),
      b_is_number   BOOLEAN DEFAULT FALSE,
      s_alignment   VARCHAR2 (20),
      n_max_size    PLS_INTEGER
   );

   TYPE t_column_list IS TABLE OF t_column_record
      INDEX BY PLS_INTEGER;

   a_column_list            t_column_list;
   n_row_size               PLS_INTEGER;
   s_row                    VARCHAR2 (4000);
   a_access_pred            t_list_varchar2;
   a_filter_pred            t_list_varchar2;
   s_plan_hash              VARCHAR2 (255);
   a_dyn_sampl              t_list_varchar2;
   a_id_list                t_list_varchar2;
   s_output                 VARCHAR2 (32767);
   s_sql_address            VARCHAR2 (255);
   s_hash_value             VARCHAR2 (255);
   s_child_num              VARCHAR2 (255);
   b_has_stat               BOOLEAN := TRUE;

   max_line_size   CONSTANT PLS_INTEGER := 255;
   c_display_cursor         SYS_REFCURSOR;
   n_cnt                    PLS_INTEGER;

   FUNCTION has_collection_only_nulls (in_coll IN t_list_varchar2)
      RETURN BOOLEAN
   IS
      b_return   BOOLEAN := TRUE;
   BEGIN
      IF in_coll.COUNT > 0
      THEN
         FOR i IN in_coll.FIRST .. in_coll.LAST
         LOOP
            IF in_coll (i) IS NOT NULL
            THEN
               b_return := FALSE;
               EXIT;
            END IF;
         END LOOP;
      END IF;

      RETURN b_return;
   END has_collection_only_nulls;

   FUNCTION get_max_size (in_coll IN t_list_varchar2)
      RETURN PLS_INTEGER
   IS
      n_return   PLS_INTEGER := 0;
   BEGIN
      IF in_coll.COUNT > 0
      THEN
         FOR i IN in_coll.FIRST .. in_coll.LAST
         LOOP
            IF in_coll (i) IS NOT NULL
            THEN
               n_return := GREATEST (n_return, LENGTH (in_coll (i)));
            END IF;
         END LOOP;
      END IF;

      RETURN n_return;
   END get_max_size;

   FUNCTION display_cursor_format_number (in_data IN VARCHAR2)
      RETURN VARCHAR2
   IS
      s_return          VARCHAR2 (20);
      s_trail           VARCHAR2 (32767);
      s_data            VARCHAR2 (32767);
      n_number          NUMBER;
      n_delim_pos       NUMBER;
      e_num_val_error   EXCEPTION;
      PRAGMA EXCEPTION_INIT (e_num_val_error, -6502);
   BEGIN
      n_delim_pos := INSTR (in_data, ‘ ‘);

      IF n_delim_pos > 0
      THEN
         s_trail := SUBSTR (in_data, n_delim_pos);
         s_data := SUBSTR (in_data, 1, n_delim_pos - 1);
      ELSE
         s_data := in_data;
      END IF;

      n_number := TO_NUMBER (s_data);
      s_return :=
         CASE
            WHEN n_number >= 100000000000000000000
            THEN
               TO_CHAR (n_number / 1000000000000000000, ‘FM99999‘) || ‘E‘
            WHEN n_number >= 100000000000000000
            THEN
               TO_CHAR (n_number / 1000000000000000, ‘FM99999‘) || ‘P‘
            WHEN n_number >= 100000000000000
            THEN
               TO_CHAR (n_number / 1000000000000, ‘FM99999‘) || ‘T‘
            WHEN n_number >= 100000000000
            THEN
               TO_CHAR (n_number / 1000000000, ‘FM99999‘) || ‘G‘
            WHEN n_number >= 100000000
            THEN
               TO_CHAR (n_number / 1000000, ‘FM99999‘) || ‘M‘
            WHEN n_number >= 100000
            THEN
               TO_CHAR (n_number / 1000, ‘FM99999‘) || ‘K‘
            ELSE
               TO_CHAR (n_number, ‘FM99999‘)
         END;
      RETURN s_return || s_trail;
   EXCEPTION
      WHEN e_num_val_error
      THEN
         RETURN in_data;
   END display_cursor_format_number;

   PROCEDURE put_line_smart (in_string        IN VARCHAR2,
                             in_line_prefix   IN VARCHAR2 DEFAULT ‘‘,
                             in_line_size     IN PLS_INTEGER DEFAULT 180)
   IS
      n_offset              PLS_INTEGER;
      s_delimiter           VARCHAR2 (1);
      n_size_current_line   PLS_INTEGER;
      n_line_counter        PLS_INTEGER;
   BEGIN
      n_offset := 1;
      n_size_current_line := in_line_size;
      n_line_counter := 1;

      WHILE   CASE
                 WHEN n_line_counter > 1 AND LENGTH (in_line_prefix) > 0
                 THEN
                    LENGTH (in_string) + LENGTH (in_line_prefix)
                 ELSE
                    LENGTH (in_string)
              END
            + 1
            - n_offset > in_line_size
      LOOP
         -- dbms_output.put_line(‘Debug n_offset: ‘ || n_offset);
         IF n_line_counter > 1 AND LENGTH (in_line_prefix) > 0
         THEN
            n_size_current_line :=
               GREATEST (n_size_current_line - LENGTH (in_line_prefix),
                         LENGTH (in_line_prefix) + 10);
         END IF;

         -- dbms_output.put_line(‘Debug n_size_current_line: ‘ || n_size_current_line);
         LOOP
            s_delimiter :=
               SUBSTR (in_string, n_offset - 1 + n_size_current_line, 1);
            EXIT WHEN    s_delimiter IN (‘ ‘,
                                         CHR (9),
                                         CHR (10),
                                         CHR (13)     /*, ‘(‘, ‘)‘, ‘[‘, ‘]‘*/
                                                 )
                      OR n_size_current_line < 1;
            n_size_current_line := n_size_current_line - 1;
         END LOOP;

         IF n_size_current_line < 1
         THEN
            IF n_line_counter > 1 AND LENGTH (in_line_prefix) > 0
            THEN
               n_size_current_line :=
                  GREATEST (n_size_current_line - LENGTH (in_line_prefix),
                            LENGTH (in_line_prefix) + 10);
            ELSE
               n_size_current_line := in_line_size;
            END IF;
         END IF;

         IF s_delimiter IN (CHR (13), CHR (10))
         THEN
            n_size_current_line := n_size_current_line - 1;
         END IF;

         DBMS_OUTPUT.put_line (
               CASE WHEN n_line_counter > 1 THEN in_line_prefix END
            || SUBSTR (in_string, n_offset, n_size_current_line));

         IF s_delimiter IN (CHR (13), CHR (10))
         THEN
            WHILE SUBSTR (in_string, n_offset - 1 + n_size_current_line, 1) IN (CHR (
                                                                                   10),
                                                                                CHR (
                                                                                   13))
            LOOP
               n_size_current_line := n_size_current_line + 1;
            END LOOP;
         END IF;

         n_offset := n_offset + n_size_current_line;
         n_size_current_line := in_line_size;
         n_line_counter := n_line_counter + 1;
      END LOOP;

      DBMS_OUTPUT.put_line (
            CASE WHEN n_line_counter > 1 THEN in_line_prefix END
         || SUBSTR (in_string, n_offset));
   END put_line_smart;
BEGIN
   DBMS_OUTPUT.put_line (
      ‘--------------------------------------------------------------------------------------‘);

   IF (UPPER (i_vc_idtype) = ‘SPID‘)
   THEN
      SELECT addr
        INTO vc_paddr
        FROM v$process
       WHERE spid = TO_CHAR (i_n_id);

      SELECT *
        INTO rec_session
        FROM v$session
       WHERE paddr = vc_paddr;

      SELECT *
        INTO rec_sessionwait
        FROM v$session_wait
       WHERE sid = rec_session.SID;

      SELECT DECODE (sql_hash_value, 0, prev_hash_value, sql_hash_value)
        INTO n_hashvalue
        FROM v$session
       WHERE sid = rec_session.SID;

        SELECT sql_text
          BULK COLLECT INTO typsqltexts
          FROM v$sqltext
         WHERE hash_value = n_hashvalue
      ORDER BY piece;

      IF (typsqltexts.COUNT > 0)
      THEN
         FOR i IN typsqltexts.FIRST .. typsqltexts.LAST
         LOOP
            ---这里处理掉"dbms_output.put_line"不能处理超过255个字符的限制,并且考虑到了sql语句中可能有中文
            LOOP
               EXIT WHEN typsqltexts (i) IS NULL;
               DBMS_OUTPUT.put_line (SUBSTRB (typsqltexts (i), 1, 254));
               typsqltexts (i) := SUBSTRB (typsqltexts (i), 255);
            END LOOP;
         END LOOP;
      ELSE
         DBMS_OUTPUT.put_line (
            ‘The sql text has been aged out from the shared pool.‘);
      END IF;
   ELSIF (UPPER (i_vc_idtype) = ‘SID‘)
   THEN
      SELECT *
        INTO rec_session
        FROM v$session
       WHERE sid = i_n_id;

      SELECT DECODE (sql_hash_value, 0, prev_hash_value, sql_hash_value)
        INTO n_hashvalue
        FROM v$session
       WHERE sid = i_n_id;

        SELECT sql_text
          BULK COLLECT INTO typsqltexts
          FROM v$sqltext
         WHERE hash_value = n_hashvalue
      ORDER BY piece;

      IF (typsqltexts.COUNT > 0)
      THEN
         FOR i IN typsqltexts.FIRST .. typsqltexts.LAST
         LOOP
            ---这里处理掉"dbms_output.put_line"不能处理超过255个字符的限制,并且考虑到了sql语句中可能有中文
            LOOP
               EXIT WHEN typsqltexts (i) IS NULL;
               DBMS_OUTPUT.put_line (SUBSTRB (typsqltexts (i), 1, 254));
               typsqltexts (i) := SUBSTRB (typsqltexts (i), 255);
            END LOOP;
         END LOOP;
      ELSE
         DBMS_OUTPUT.put_line (
            ‘The sql text has been aged out from the shared pool.‘);
      END IF;
   ELSE
      DBMS_OUTPUT.put_line (‘invalid input id type parameter!‘);
      RETURN;
   END IF;

   DBMS_OUTPUT.put_line (
      ‘--------------------------------------------------------------------------------------‘);
   DBMS_OUTPUT.put_line (‘The session id is ‘ || rec_session.SID);
   DBMS_OUTPUT.put_line (‘The status is ‘ || rec_session.STATUS);
   DBMS_OUTPUT.put_line (
      ‘The sql hash value is ‘ || rec_session.SQL_HASH_VALUE);
   --dbms_output.put_line(‘The child cursor number is ‘ || rec_session.SQL_CHILD_NUMBER);
   DBMS_OUTPUT.put_line (
      ‘The prev hash value is ‘ || rec_session.PREV_HASH_VALUE);
   --dbms_output.put_line(‘The prev child cursor number is ‘ || rec_session.PREV_CHILD_NUMBER);
   DBMS_OUTPUT.put_line (‘The osuser is ‘ || rec_session.OSUSER);
   DBMS_OUTPUT.put_line (‘The machine is ‘ || rec_session.MACHINE);
   DBMS_OUTPUT.put_line (‘The terminal is ‘ || rec_session.TERMINAL);
   DBMS_OUTPUT.put_line (‘The program is ‘ || rec_session.PROGRAM);
   DBMS_OUTPUT.put_line (‘The event is ‘ || rec_sessionwait.EVENT);
   DBMS_OUTPUT.put_line (
      ‘--------------------------------------------------------------------------------------‘);

   --demo: alter system kill session ‘417,21188‘ immediate;
   DBMS_OUTPUT.put_line (
         ‘alter system kill session ‘‘‘
      || rec_session.SID
      || ‘,‘
      || rec_session.SERIAL#
      || ‘‘‘ immediate;‘);

   SELECT hash_value,
          child_number,
          plan_hash_value,
          executions,
          buffer_gets,
          buffer_gets / DECODE (executions, 0, 1, executions) gets_per_exec,
          rows_processed,
          rows_processed / DECODE (executions, 0, 1, executions)
             rows_per_exec,
          disk_reads,
          disk_reads / DECODE (executions, 0, 1, executions) reads_per_exec,
          cpu_time / 1000000 cpu_time,
          cpu_time / DECODE (executions, 0, 1, executions) / 1000000
             cpu_per_exec,
          ELAPSED_TIME / 1000000 ELAPSED_TIME,
          ELAPSED_TIME / DECODE (executions, 0, 1, executions) / 1000000
             ela_per_exec
     BULK COLLECT INTO hash_values,
          child_numbers,
          plan_hash_values,
          executions,
          buffer_gets,
          gets_per_execs,
          rows_processeds,
          rows_per_execs,
          disk_reads,
          reads_per_execs,
          cpu_times,
          cpu_per_execs,
          ELAPSED_TIMEs,
          ela_per_execs
     FROM v$sql
    WHERE hash_value = n_hashvalue AND ROWNUM <= 100;

   IF (hash_values.COUNT > 0)
   THEN
      FOR i IN hash_values.FIRST .. hash_values.LAST
      LOOP
         DBMS_OUTPUT.put_line (
            ‘--------------------------------------------------------------------------------------‘);
         DBMS_OUTPUT.put_line (‘The hash_value is ‘ || hash_values (i));
         DBMS_OUTPUT.put_line (‘The child_number is ‘ || child_numbers (i));
         DBMS_OUTPUT.put_line (
            ‘The plan_hash_value is ‘ || plan_hash_values (i));
         DBMS_OUTPUT.put_line (‘The execution is ‘ || executions (i));
         DBMS_OUTPUT.put_line (‘The buffer_gets is ‘ || buffer_gets (i));
         DBMS_OUTPUT.put_line (‘The gets_per_exec is ‘ || gets_per_execs (i));
         DBMS_OUTPUT.put_line (
            ‘The rows_processed is ‘ || rows_processeds (i));
         DBMS_OUTPUT.put_line (‘The rows_per_exec is ‘ || rows_per_execs (i));
         DBMS_OUTPUT.put_line (‘The disk_reads is ‘ || disk_reads (i));
         DBMS_OUTPUT.put_line (
            ‘The reads_per_exec is ‘ || reads_per_execs (i));
         DBMS_OUTPUT.put_line (‘The cpu_time is ‘ || cpu_times (i));
         DBMS_OUTPUT.put_line (‘The cpu_per_exec is ‘ || cpu_per_execs (i));
         DBMS_OUTPUT.put_line (‘The ELAPSED_TIME is ‘ || ELAPSED_TIMEs (i));
         DBMS_OUTPUT.put_line (‘The ela_per_exec is ‘ || ela_per_execs (i));
         DBMS_OUTPUT.put_line (
            ‘--------------------------------------------------------------------------------------‘);

         s_hash_value := n_hashvalue;
         s_child_num := child_numbers (i);
         -- Header information
         DBMS_OUTPUT.put_line (CHR (13));
         put_line_smart (
            in_string      =>    ‘ HASH_VALUE: ‘
                              || s_hash_value
                              || ‘   CHILD_NUMBER: ‘
                              || s_child_num,
            in_line_size   => max_line_size);
         put_line_smart (
            in_string      => ‘---------------------------------------------------------------------------------------------------------------------------------------------‘,
            in_line_size   => max_line_size);

         BEGIN
            EXECUTE IMMEDIATE
               ‘ 
        select sql_text, 
        plan_hash_value 
        from v$sql 
        where hash_value = to_number(:s_hash_value) 
        and child_number = to_number(:s_child_num)‘

               INTO s_output, s_plan_hash
               USING s_hash_value, s_child_num;
         EXCEPTION
            WHEN NO_DATA_FOUND
            THEN
               NULL;
            WHEN OTHERS
            THEN
               DBMS_OUTPUT.put_line (
                  ‘Error getting SQL text from V$SQL, check privileges‘);
         END;

         put_line_smart (s_output);
         DBMS_OUTPUT.put_line (CHR (13));

         OPEN c_display_cursor FOR s_display_cursor
            USING TO_NUMBER (s_hash_value), TO_NUMBER (s_child_num);

         n_cnt := 1;

         FETCH c_display_cursor
            INTO a_column_list (1).a_data (n_cnt),           -- a_p_id(n_cnt),
                 a_column_list (2).a_data (n_cnt),      -- a_operation(n_cnt),
                 a_column_list (3).a_data (n_cnt),           -- a_name(n_cnt),
                 a_column_list (4).a_data (n_cnt),         -- a_starts(n_cnt),
                 a_column_list (5).a_data (n_cnt),         -- a_e_rows(n_cnt),
                 a_column_list (6).a_data (n_cnt),         -- a_a_rows(n_cnt),
                 a_column_list (7).a_data (n_cnt),         -- a_a_time(n_cnt),
                 a_column_list (8).a_data (n_cnt),        -- a_buffers(n_cnt),
                 a_column_list (9).a_data (n_cnt),          -- a_reads(n_cnt),
                 a_column_list (10).a_data (n_cnt),        -- a_writes(n_cnt),
                 a_column_list (11).a_data (n_cnt),        -- a_in_out(n_cnt),
                 a_column_list (12).a_data (n_cnt), -- a_partition_start(n_cnt),
                 a_column_list (13).a_data (n_cnt), -- a_partition_stop(n_cnt),
                 a_column_list (14).a_data (n_cnt),  -- a_distribution(n_cnt),
                 a_column_list (15).a_data (n_cnt), -- a_last_mem_usage(n_cnt),
                 a_column_list (16).a_data (n_cnt),   -- a_last_degree(n_cnt),
                 a_column_list (17).a_data (n_cnt),       -- a_mem_opt(n_cnt),
                 a_column_list (18).a_data (n_cnt),       -- a_mem_one(n_cnt),
                 --a_column_list(17).a_data(n_cnt), -- a_opt_cnt(n_cnt),
                 --a_column_list(18).a_data(n_cnt), -- a_one_cnt(n_cnt),
                 --a_column_list(19).a_data(n_cnt), -- a_multi_cnt(n_cnt),
                 --a_column_list(22).a_data(n_cnt), -- a_max_tmp(n_cnt),
                 a_column_list (19).a_data (n_cnt),      -- a_last_tmp(n_cnt),
                 a_access_pred (n_cnt),
                 a_filter_pred (n_cnt),
                 a_dyn_sampl (n_cnt),
                 a_id_list (n_cnt);

         IF c_display_cursor%NOTFOUND
         THEN
            CLOSE c_display_cursor;

            --dbms_output.put_line(‘Debug : Select V$SQL_PLAN‘);
            b_has_stat := FALSE;

            a_column_list (1).s_heading := ‘Id‘; --a_column_list(1).b_is_number := true;
            a_column_list (2).s_heading := ‘Operation‘;
            a_column_list (3).s_heading := ‘Name‘;
            a_column_list (4).s_heading := ‘Rows‘;
            a_column_list (4).b_is_number := TRUE;
            a_column_list (5).s_heading := ‘Bytes‘;
            a_column_list (5).b_is_number := TRUE;
            a_column_list (6).s_heading := ‘TempSpc‘;
            a_column_list (6).b_is_number := TRUE;
            a_column_list (7).s_heading := ‘Cost‘;
            a_column_list (7).b_is_number := TRUE;
            a_column_list (8).s_heading := ‘Cpu-Cost‘;
            a_column_list (8).b_is_number := TRUE;
            a_column_list (9).s_heading := ‘TQ‘;
            a_column_list (10).s_heading := ‘In-Out‘;
            a_column_list (11).s_heading := ‘Pstart‘;
            a_column_list (10).b_is_number := TRUE;
            a_column_list (12).s_heading := ‘Pstop‘;
            a_column_list (11).b_is_number := TRUE;
            a_column_list (13).s_heading := ‘PQ Distrib‘;

            OPEN c_display_cursor FOR s_display_cursor2
               USING TO_NUMBER (s_hash_value), TO_NUMBER (s_child_num);

            n_cnt := 0;
         ELSE
            -- The plan statistics
            a_column_list (1).s_heading := ‘Id‘; --a_column_list(1).b_is_number := true;
            a_column_list (2).s_heading := ‘Operation‘;
            a_column_list (3).s_heading := ‘Name‘;
            a_column_list (4).s_heading := ‘Starts‘;
            a_column_list (4).b_is_number := TRUE;
            a_column_list (5).s_heading := ‘E-Rows‘;
            a_column_list (5).b_is_number := TRUE;
            a_column_list (6).s_heading := ‘A-Rows‘;
            a_column_list (6).b_is_number := TRUE;
            a_column_list (7).s_heading := ‘A-Time‘;
            a_column_list (8).s_heading := ‘Buffers‘;
            a_column_list (8).b_is_number := TRUE;
            a_column_list (9).s_heading := ‘Reads‘;
            a_column_list (9).b_is_number := TRUE;
            a_column_list (10).s_heading := ‘Writes‘;
            a_column_list (10).b_is_number := TRUE;
            a_column_list (11).s_heading := ‘In-Out‘;
            a_column_list (12).s_heading := ‘Pstart‘;
            a_column_list (12).b_is_number := TRUE;
            a_column_list (13).s_heading := ‘Pstop‘;
            a_column_list (13).b_is_number := TRUE;
            a_column_list (14).s_heading := ‘PQ Distrib‘;
            a_column_list (15).s_heading := ‘OMem‘;
            a_column_list (15).b_is_number := TRUE;
            a_column_list (16).s_heading := ‘1Mem‘;
            a_column_list (16).b_is_number := TRUE;
            a_column_list (17).s_heading := ‘Used-Mem‘;
            a_column_list (17).b_is_number := TRUE; --a_column_list(15).s_alignment := ‘RIGHT‘;
            a_column_list (18).s_heading := ‘Last-Degree‘;
            a_column_list (18).b_is_number := TRUE;
            --a_column_list(19).s_heading := ‘Opt-Cnt‘; a_column_list(17).b_is_number := true;
            --a_column_list(20).s_heading := ‘One-Cnt‘; a_column_list(18).b_is_number := true;
            --a_column_list(21).s_heading := ‘Multi-Cnt‘; a_column_list(19).b_is_number := true;
            --a_column_list(19).s_heading := ‘Max-Tmp‘; a_column_list(19).b_is_number := true;
            a_column_list (19).s_heading := ‘Last-Tmp‘;
            a_column_list (19).b_is_number := TRUE;

            n_cnt := 1;
         END IF;

         LOOP
            EXIT WHEN c_display_cursor%NOTFOUND;
            n_cnt := n_cnt + 1;

            IF b_has_stat
            THEN
               FETCH c_display_cursor
                  INTO a_column_list (1).a_data (n_cnt),     -- a_p_id(n_cnt),
                       a_column_list (2).a_data (n_cnt), -- a_operation(n_cnt),
                       a_column_list (3).a_data (n_cnt),     -- a_name(n_cnt),
                       a_column_list (4).a_data (n_cnt),   -- a_starts(n_cnt),
                       a_column_list (5).a_data (n_cnt),   -- a_e_rows(n_cnt),
                       a_column_list (6).a_data (n_cnt),   -- a_a_rows(n_cnt),
                       a_column_list (7).a_data (n_cnt),   -- a_a_time(n_cnt),
                       a_column_list (8).a_data (n_cnt),  -- a_buffers(n_cnt),
                       a_column_list (9).a_data (n_cnt),    -- a_reads(n_cnt),
                       a_column_list (10).a_data (n_cnt),  -- a_writes(n_cnt),
                       a_column_list (11).a_data (n_cnt),  -- a_in_out(n_cnt),
                       a_column_list (12).a_data (n_cnt), -- a_partition_start(n_cnt),
                       a_column_list (13).a_data (n_cnt), -- a_partition_stop(n_cnt),
                       a_column_list (14).a_data (n_cnt), -- a_distribution(n_cnt),
                       a_column_list (15).a_data (n_cnt), -- a_last_mem_usage(n_cnt),
                       a_column_list (16).a_data (n_cnt), -- a_last_degree(n_cnt),
                       a_column_list (17).a_data (n_cnt), -- a_mem_opt(n_cnt),
                       a_column_list (18).a_data (n_cnt), -- a_mem_one(n_cnt),
                       a_column_list (19).a_data (n_cnt), -- a_last_tmp(n_cnt),
                       a_access_pred (n_cnt),
                       a_filter_pred (n_cnt),
                       a_dyn_sampl (n_cnt),
                       a_id_list (n_cnt);
            ELSE
               FETCH c_display_cursor
                  INTO a_column_list (1).a_data (n_cnt),
                       a_column_list (2).a_data (n_cnt),
                       a_column_list (3).a_data (n_cnt),
                       a_column_list (4).a_data (n_cnt),
                       a_column_list (5).a_data (n_cnt),
                       a_column_list (6).a_data (n_cnt),
                       a_column_list (7).a_data (n_cnt),
                       a_column_list (8).a_data (n_cnt),
                       a_column_list (9).a_data (n_cnt),
                       a_column_list (10).a_data (n_cnt),
                       a_column_list (11).a_data (n_cnt),
                       a_column_list (12).a_data (n_cnt),
                       a_column_list (13).a_data (n_cnt),
                       a_access_pred (n_cnt),
                       a_filter_pred (n_cnt),
                       a_dyn_sampl (n_cnt),
                       a_id_list (n_cnt);
            END IF;
         END LOOP;

         CLOSE c_display_cursor;

         IF a_column_list (1).a_data.COUNT > 0
         THEN
            DBMS_OUTPUT.put_line (‘Plan hash value: ‘ || s_plan_hash);
            DBMS_OUTPUT.put_line (CHR (13));
            n_row_size := 1;

            FOR i IN a_column_list.FIRST .. a_column_list.LAST
            LOOP
               IF a_column_list (i).b_is_number
               THEN
                  IF a_column_list (i).a_data.COUNT > 0
                  THEN
                     FOR j IN a_column_list (i).a_data.FIRST ..
                              a_column_list (i).a_data.LAST
                     LOOP
                        BEGIN
                           a_column_list (i).a_data (j) :=
                              display_cursor_format_number (
                                 a_column_list (i).a_data (j));
                        EXCEPTION
                           WHEN OTHERS
                           THEN
                              DBMS_OUTPUT.put_line (
                                    ‘Column:‘
                                 || a_column_list (i).s_heading
                                 || ‘ Data: ‘
                                 || a_column_list (i).a_data (j));
                              RAISE;
                        END;
                     END LOOP;
                  END IF;
               END IF;

               -- column size is greatest of max size of content + 2 (leading + trailing blanks) and size of column heading
               a_column_list (i).n_max_size :=
                  GREATEST (get_max_size (a_column_list (i).a_data) + 2,
                            LENGTH (a_column_list (i).s_heading) + 2);
               a_column_list (i).b_has_data :=
                  NOT has_collection_only_nulls (a_column_list (i).a_data);

               IF a_column_list (i).b_has_data
               THEN
                  n_row_size := n_row_size + a_column_list (i).n_max_size + 1;
               END IF;
            END LOOP;

            -- Header
            put_line_smart (in_string      => LPAD (‘-‘, n_row_size, ‘-‘),
                            in_line_size   => max_line_size);
            s_row := ‘‘;

            FOR i IN a_column_list.FIRST .. a_column_list.LAST
            LOOP
               IF a_column_list (i).b_has_data
               THEN
                  IF a_column_list (i).s_alignment IS NULL
                  THEN
                     IF a_column_list (i).b_is_number
                     THEN
                        s_row :=
                              s_row
                           || ‘|‘
                           || LPAD (a_column_list (i).s_heading,
                                    a_column_list (i).n_max_size - 1)
                           || ‘ ‘;
                     ELSE
                        s_row :=
                              s_row
                           || ‘|‘
                           || ‘ ‘
                           || RPAD (a_column_list (i).s_heading,
                                    a_column_list (i).n_max_size - 1);
                     END IF;
                  ELSE
                     IF a_column_list (i).s_alignment = ‘RIGHT‘
                     THEN
                        s_row :=
                              s_row
                           || ‘|‘
                           || LPAD (a_column_list (i).s_heading,
                                    a_column_list (i).n_max_size - 1)
                           || ‘ ‘;
                     ELSE
                        s_row :=
                              s_row
                           || ‘|‘
                           || ‘ ‘
                           || RPAD (a_column_list (i).s_heading,
                                    a_column_list (i).n_max_size - 1);
                     END IF;
                  END IF;
               END IF;
            END LOOP;

            s_row := s_row || ‘|‘;
            put_line_smart (in_string => s_row, in_line_size => max_line_size);
            -- Data
            put_line_smart (in_string      => LPAD (‘-‘, n_row_size, ‘-‘),
                            in_line_size   => max_line_size);

            FOR j IN a_column_list (1).a_data.FIRST ..
                     a_column_list (1).a_data.LAST
            LOOP
               s_row := ‘‘;

               FOR i IN a_column_list.FIRST .. a_column_list.LAST
               LOOP
                  IF a_column_list (i).b_has_data
                  THEN
                     IF a_column_list (i).b_is_number
                     THEN
                        s_row :=
                              s_row
                           || ‘|‘
                           || LPAD (NVL (a_column_list (i).a_data (j), ‘ ‘),
                                    a_column_list (i).n_max_size - 1)
                           || ‘ ‘;
                     ELSE
                        s_row :=
                              s_row
                           || ‘|‘
                           || ‘ ‘
                           || RPAD (NVL (a_column_list (i).a_data (j), ‘ ‘),
                                    a_column_list (i).n_max_size - 1);
                     END IF;
                  END IF;
               END LOOP;

               s_row := s_row || ‘|‘;
               put_line_smart (in_string      => s_row,
                               in_line_size   => max_line_size);
            END LOOP;

            -- Footer
            put_line_smart (in_string      => LPAD (‘-‘, n_row_size, ‘-‘),
                            in_line_size   => max_line_size);
            -- Predicate information
            DBMS_OUTPUT.put_line (CHR (13));
            DBMS_OUTPUT.put_line (
               ‘Predicate Information (identified by operation id):‘);
            DBMS_OUTPUT.put_line (
               ‘---------------------------------------------------‘);

            FOR j IN a_column_list (1).a_data.FIRST ..
                     a_column_list (1).a_data.LAST
            LOOP
               IF    a_access_pred (j) IS NOT NULL
                  OR a_filter_pred (j) IS NOT NULL
               THEN
                  s_output :=
                        LPAD (TO_CHAR (TO_NUMBER (a_id_list (j)), ‘FM9999‘),
                              4,
                              ‘ ‘)
                     || ‘ - ‘;

                  IF a_access_pred (j) IS NOT NULL
                  THEN
                     put_line_smart (
                        s_output || ‘access(‘ || a_access_pred (j) || ‘)‘,
                        LPAD (‘ ‘, LENGTH (s_output), ‘ ‘));
                  END IF;

                  IF a_filter_pred (j) IS NOT NULL
                  THEN
                     IF a_access_pred (j) IS NOT NULL
                     THEN
                        put_line_smart (
                              LPAD (‘ ‘, LENGTH (s_output), ‘ ‘)
                           || ‘filter(‘
                           || a_filter_pred (j)
                           || ‘)‘,
                           LPAD (‘ ‘, LENGTH (s_output), ‘ ‘));
                     ELSE
                        put_line_smart (
                           s_output || ‘filter(‘ || a_filter_pred (j) || ‘)‘,
                           LPAD (‘ ‘, LENGTH (s_output), ‘ ‘));
                     END IF;
                  END IF;
               END IF;
            END LOOP;

            --dbms_output.put_line(‘DEBUG:Begin Notes‘);
            -- Notes section
            IF NOT a_column_list (4).b_has_data OR a_dyn_sampl (1) = ‘YES‘
            THEN
               DBMS_OUTPUT.put_line (CHR (13));
               DBMS_OUTPUT.put_line (‘Note‘);
               DBMS_OUTPUT.put_line (‘-----‘);
            END IF;

            IF a_dyn_sampl (1) = ‘YES‘
            THEN
               DBMS_OUTPUT.put_line (
                  ‘   - dynamic sampling used for this statement‘);
            END IF;

            IF NOT a_column_list (4).b_has_data
            THEN
               DBMS_OUTPUT.put_line (
                  ‘   - Warning: basic plan statistics not available. These are only collected when:‘);
               DBMS_OUTPUT.put_line (
                  ‘       * parameter ‘‘statistics_level‘‘ is set to ‘‘ALL‘‘, at session or system level‘);
            END IF;
         ELSE
            DBMS_OUTPUT.put_line (
                  ‘SQL information could not be found for HASH_VALUE: ‘
               || s_hash_value
               || ‘,CHILD_NUMBER: ‘
               || s_child_num);
            DBMS_OUTPUT.put_line (
               ‘Please verify value of SQL address, hash_value and child_number;‘);
            DBMS_OUTPUT.put_line (
               ‘It could also be that the plan is no longer in cursor cache (check v$sql_plan)‘);
         END IF;
      END LOOP;
   END IF;
EXCEPTION
   WHEN OTHERS
   THEN
      o_vc_return_flag := ‘E‘ || ‘_‘ || SQLCODE || ‘_‘ || SQLERRM;
      DBMS_OUTPUT.put_line (o_vc_return_flag);
      RETURN;
END PRINTSQL;
/




printsql.sql 打印对应spid或sid所对应的sql以及其执行计划

标签:

原文地址:http://www.cnblogs.com/cure-t-x-y/p/4241409.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!