标签:
/* 打印对应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