您的位置:首页 > 数据库

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

2015-01-22 13:13 323 查看
/* 打印对应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;

/


来自为知笔记(Wiz)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: