ITPub博客

首页 > 数据库 > Oracle > PRINTSQL

PRINTSQL

Oracle 作者:xypincle 时间:2017-04-09 23:54:39 0 删除 编辑

  1. create or replace procedure PRINTSQL
  2. (i_n_id in number,
  3.  i_vc_idtype in varchar2) is
  4. /*
  5. 功能: 打印对应spid或sid所对应的sql以及其执行计划
  6. 作者: 老熊,dbsnake
  7. 创建日期:2010-11-12

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

  11. 输出参数:
  12. 无

  13. 输入输出参数:
  14. 无

  15. 调用到的存储过程:
  16. 无
  17. */

  18. o_vc_return_flag varchar2(4000);

  19. type typsqltext is table of varchar2(1000) index by binary_integer;
  20. typsqltexts typsqltext;

  21. vc_paddr varchar2(4000);
  22. n_hashvalue number;
  23. n_childnumber number;
  24. rec_session v$session%rowtype;
  25. rec_sessionwait v$session_wait%rowtype;
  26. rec_sql v$sql%rowtype;

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

  34. type type_hash_value is table of v$sql.HASH_VALUE%type index by binary_integer;
  35. hash_values type_hash_value;
  36. type type_child_number is table of v$sql.CHILD_NUMBER%type index by binary_integer;
  37. child_numbers type_child_number;
  38. type type_plan_hash_value is table of v$sql.PLAN_HASH_VALUE%type index by binary_integer;
  39. plan_hash_values type_plan_hash_value;
  40. type type_execution is table of v$sql.EXECUTIONS%type index by binary_integer;
  41. executions type_execution;
  42. type type_buffer_get is table of v$sql.BUFFER_GETS%type index by binary_integer;
  43. buffer_gets type_buffer_get;
  44. type type_gets_per_exec is table of v$sql.BUFFER_GETS%type index by binary_integer;
  45. gets_per_execs type_gets_per_exec;
  46. type type_rows_processed is table of v$sql.ROWS_PROCESSED%type index by binary_integer;
  47. rows_processeds type_rows_processed;
  48. type type_rows_per_exec is table of v$sql.ROWS_PROCESSED%type index by binary_integer;
  49. rows_per_execs type_rows_per_exec;
  50. type type_disk_read is table of v$sql.DISK_READS%type index by binary_integer;
  51. disk_reads type_disk_read;
  52. type type_reads_per_exec is table of v$sql.DISK_READS%type index by binary_integer;
  53. reads_per_execs type_reads_per_exec;
  54. type type_cpu_time is table of v$sql.CPU_TIME%type index by binary_integer;
  55. cpu_times type_cpu_time;
  56. type type_cpu_per_exec is table of v$sql.CPU_TIME%type index by binary_integer;
  57. cpu_per_execs type_cpu_per_exec;
  58. type type_ELAPSED_TIME is table of v$sql.ELAPSED_TIME%type index by binary_integer;
  59. ELAPSED_TIMEs type_ELAPSED_TIME;
  60. type type_ela_per_exec is table of v$sql.ELAPSED_TIME%type index by binary_integer;
  61. ela_per_execs type_ela_per_exec;


  62. -- cursor c_display_cursor(in_address varchar2, in_hash_value number, in_child_number number) is
  63. s_display_cursor varchar2(32767) := '
  64. 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,
  65. lpad('' '', depth) || operation || '' '' || options as operation,
  66. object_name as name,
  67. starts,
  68. cardinality as e_rows,
  69. outrows as a_rows,
  70. 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,
  71. crgets + cugets as buffers,
  72. case reads when 0 then null else reads end as reads,
  73. case writes when 0 then null else writes end as writes,
  74. case other_tag
  75. when ''PARALLEL_TO_SERIAL'' then ''P->S''
  76. when ''PARALLEL_COMBINED_WITH_PARENT'' then ''PCWP''
  77. when ''PARALLEL_COMBINED_WITH_CHILD'' then ''PCWC''
  78. when ''SERIAL_TO_PARALLEL'' then ''S->P''
  79. when ''PARALLEL_TO_PARALLEL'' then ''P->P''
  80. when ''PARALLEL_FROM_SERIAL'' then ''P<-S''
  81. else other_tag end as in_out,
  82. partition_start,
  83. partition_stop,
  84. distribution,
  85. mem_opt,
  86. mem_one,
  87. last_mem_used || case last_mem_usage when ''OPTIMAL'' then '' (0)'' when ''ONE PASS'' then '' (1)'' when ''MULTI-PASS'' then '' (M)'' end,
  88. case last_degree when 0 then null when 1 then null else last_degree end as last_degree,
  89. --opt_cnt,
  90. --one_cnt,
  91. --multi_cnt,
  92. --max_tmp,
  93. last_tmp,
  94. access_predicates,
  95. filter_predicates,
  96. dynamic_sampling_flag,
  97. id
  98. from (
  99. SELECT /*+ opt_param(''parallel_execution_enabled'', ''false'') */
  100.                       id, position, depth , operation, options, object_name, cardinality, bytes, temp_space, cost, io_cost,
  101.                       cpu_cost, partition_start, partition_stop, object_node, other_tag, distribution, null, access_predicates, filter_predicates,
  102.                       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,
  103.                       opt_cnt, one_cnt, multi_cnt, max_tmp, last_tmp, dynamic_sampling_flag from (
  104.                           select /*+ no_merge */
  105.                           id, depth, position, operation, options,
  106.                           cost, cardinality, bytes, object_node,
  107.                           object_name, other_tag, partition_start,
  108.                           partition_stop, distribution, temp_space, io_cost,
  109.                           cpu_cost, filter_predicates, access_predicates, other,
  110.                           last_starts starts,
  111.                                     last_output_rows outrows,
  112.                                     last_cr_buffer_gets crgets,
  113.                                     last_cu_buffer_gets cugets,
  114.                                     last_disk_reads reads,
  115.                                     last_disk_writes writes,
  116.                                     last_elapsed_time etime,
  117.                                     to_char(numtodsinterval(round(last_elapsed_time/10000)*10000/1000000, ''SECOND'')) as e_time_interval,
  118.                                     estimated_optimal_size mem_opt,
  119.                                     estimated_onepass_size mem_one,
  120.                                     last_memory_used last_mem_used,
  121.                                     last_degree,
  122.                                     last_execution last_mem_usage,
  123.                                     optimal_executions opt_cnt,
  124.                                     onepass_executions one_cnt,
  125.                                     multipasses_executions multi_cnt,
  126.                                     max_tempseg_size max_tmp,
  127.                                     last_tempseg_size last_tmp,
  128.                                     case 0 /*instr(other_xml, ''dynamic_sampling'')*/ when 0 then NULL else ''YES'' end as dynamic_sampling_flag
  129.               from V$SQL_PLAN_STATISTICS_ALL vp
  130.               --where address = hextoraw(:in_address)
  131.               where hash_value = :in_hash_value
  132.               and child_number = :in_child_number)
  133. )
  134. order by id';

  135. s_display_cursor2 varchar2(32767) := '
  136. 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,
  137. lpad('' '', depth) || operation || '' '' || options as operation,
  138. object_name as name,
  139. cardinality as e_rows,
  140. bytes,
  141. temp_space,
  142. cost,
  143. cpu_cost,
  144. object_node,
  145. case other_tag
  146. when ''PARALLEL_TO_SERIAL'' then ''P->S''
  147. when ''PARALLEL_COMBINED_WITH_PARENT'' then ''PCWP''
  148. when ''PARALLEL_COMBINED_WITH_CHILD'' then ''PCWC''
  149. when ''SERIAL_TO_PARALLEL'' then ''S->P''
  150. when ''PARALLEL_TO_PARALLEL'' then ''P->P''
  151. when ''PARALLEL_FROM_SERIAL'' then ''P<-S''
  152. else other_tag end as in_out,
  153. partition_start,
  154. partition_stop,
  155. distribution,
  156. access_predicates,
  157. filter_predicates,
  158. dynamic_sampling_flag,
  159. id
  160. from (
  161. SELECT /*+ opt_param(''parallel_execution_enabled'', ''false'') */
  162.                       id, position, depth , operation, options, object_name, cardinality, bytes, temp_space, cost, io_cost,
  163.                       cpu_cost, partition_start, partition_stop, object_node, other_tag, distribution, null, access_predicates, filter_predicates,
  164.                       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,
  165.                       opt_cnt, one_cnt, multi_cnt, max_tmp, last_tmp, dynamic_sampling_flag from (
  166.                           select /*+ no_merge */
  167.                           id, depth, position, operation, options,
  168.                           cost, cardinality, bytes, object_node,
  169.                           object_name, other_tag, partition_start,
  170.                           partition_stop, distribution, temp_space, io_cost,
  171.                           cpu_cost, filter_predicates, access_predicates, other,
  172.                           0 starts,
  173.                                     0 outrows,
  174.                                     0 crgets,
  175.                                     0 cugets,
  176.                                     0 reads,
  177.                                     0 writes,
  178.                                     0 etime,
  179.                                     0 e_time_interval,
  180.                                     0 mem_opt,
  181.                                     0 mem_one,
  182.                                     null last_mem_used,
  183.                                     0 last_degree,
  184.                                     null last_mem_usage,
  185.                                     0 opt_cnt,
  186.                                     0 one_cnt,
  187.                                     0 multi_cnt,
  188.                                     0 max_tmp,
  189.                                     0 last_tmp,
  190.                                     case 0 /*instr(other_xml, ''dynamic_sampling'')*/ when 0 then NULL else ''YES'' end as dynamic_sampling_flag
  191.               from V$SQL_PLAN vp
  192.               --where address = hextoraw(:in_address)
  193.               where hash_value = :in_hash_value
  194.               and child_number = :in_child_number)
  195. )
  196. order by id';

  197. type t_list_varchar2 is table of varchar2(4000) index by pls_integer;
  198. type t_column_record is record (
  199. a_data t_list_varchar2,
  200. b_has_data boolean,
  201. s_heading varchar2(255),
  202. b_is_number boolean default false,
  203. s_alignment varchar2(20),
  204. n_max_size pls_integer);
  205. type t_column_list is table of t_column_record index by pls_integer;
  206. a_column_list t_column_list;
  207. n_row_size pls_integer;
  208. s_row varchar2(4000);
  209. a_access_pred t_list_varchar2;
  210. a_filter_pred t_list_varchar2;
  211. s_plan_hash varchar2(255);
  212. a_dyn_sampl t_list_varchar2;
  213. a_id_list t_list_varchar2;
  214. s_output varchar2(32767);
  215. s_sql_address varchar2(255);
  216. s_hash_value varchar2(255);
  217. s_child_num varchar2(255);
  218. b_has_stat boolean := TRUE;

  219. max_line_size constant pls_integer := 255;
  220. c_display_cursor sys_refcursor;
  221. n_cnt pls_integer;

  222. function has_collection_only_nulls(in_coll in t_list_varchar2)
  223. return boolean is
  224.   b_return boolean := true;
  225. begin
  226.   if in_coll.count > 0 then
  227.     for i in in_coll.first..in_coll.last loop
  228.       if in_coll(i) is not null then
  229.         b_return := false;
  230.         exit;
  231.       end if;
  232.     end loop;
  233.   end if;
  234.   return b_return;
  235. end has_collection_only_nulls;

  236. function get_max_size(in_coll in t_list_varchar2)
  237. return pls_integer is
  238.   n_return pls_integer := 0;
  239. begin
  240.   if in_coll.count > 0 then
  241.     for i in in_coll.first..in_coll.last loop
  242.       if in_coll(i) is not null then
  243.         n_return := greatest(n_return, length(in_coll(i)));
  244.       end if;
  245.     end loop;
  246.   end if;
  247.   return n_return;
  248. end get_max_size;

  249. function display_cursor_format_number(in_data in varchar2)
  250. return varchar2 is
  251.   s_return varchar2(20);
  252.   s_trail varchar2(32767);
  253.   s_data varchar2(32767);
  254.   n_number number;
  255.   n_delim_pos number;
  256.   e_num_val_error exception;
  257.   pragma exception_init(e_num_val_error, -6502);
  258. begin
  259.   n_delim_pos := instr(in_data, ' ');
  260.   if n_delim_pos > 0 then
  261.     s_trail := substr(in_data, n_delim_pos);
  262.     s_data := substr(in_data, 1, n_delim_pos - 1);
  263.   else
  264.     s_data := in_data;
  265.   end if;
  266.   n_number := to_number(s_data);
  267.   s_return :=
  268.   case
  269.   when n_number >= 100000000000000000000 then to_char(n_number/1000000000000000000, 'FM99999') || 'E'
  270.   when n_number >= 100000000000000000 then to_char(n_number/1000000000000000, 'FM99999') || 'P'
  271.   when n_number >= 100000000000000 then to_char(n_number/1000000000000, 'FM99999') || 'T'
  272.   when n_number >= 100000000000 then to_char(n_number/1000000000, 'FM99999') || 'G'
  273.   when n_number >= 100000000 then to_char(n_number/1000000, 'FM99999') || 'M'
  274.   when n_number >= 100000 then to_char(n_number/1000, 'FM99999') || 'K'
  275.   else to_char(n_number, 'FM99999')
  276.   end;
  277.   return s_return || s_trail;
  278. exception
  279. when e_num_val_error then
  280.   return in_data;
  281. end display_cursor_format_number;

  282. procedure put_line_smart(in_string in varchar2, in_line_prefix in varchar2 default '', in_line_size in pls_integer default 180) is
  283.   n_offset pls_integer;
  284.   s_delimiter varchar2(1);
  285.   n_size_current_line pls_integer;
  286.   n_line_counter pls_integer;
  287. begin
  288.   n_offset := 1;
  289.   n_size_current_line := in_line_size;
  290.   n_line_counter := 1;
  291.   while case when n_line_counter > 1 and length(in_line_prefix) > 0
  292.         then length(in_string) + length(in_line_prefix)
  293.         else length(in_string) end
  294.         + 1 - n_offset > in_line_size loop
  295.     -- dbms_output.put_line('Debug n_offset: ' || n_offset);
  296.     if n_line_counter > 1 and length(in_line_prefix) > 0 then
  297.       n_size_current_line := greatest(n_size_current_line - length(in_line_prefix), length(in_line_prefix) + 10);
  298.     end if;
  299.     -- dbms_output.put_line('Debug n_size_current_line: ' || n_size_current_line);
  300.     loop
  301.       s_delimiter := substr(in_string, n_offset - 1 + n_size_current_line, 1);
  302.       exit when s_delimiter in (' ', chr(9), chr(10), chr(13)/*, '(', ')', '[', ']'*/) or n_size_current_line < 1;
  303.       n_size_current_line := n_size_current_line - 1;
  304.     end loop;
  305.     if n_size_current_line < 1 then
  306.       if n_line_counter > 1 and length(in_line_prefix) > 0 then
  307.         n_size_current_line := greatest(n_size_current_line - length(in_line_prefix), length(in_line_prefix) + 10);
  308.       else
  309.         n_size_current_line := in_line_size;
  310.       end if;
  311.     end if;
  312.     if s_delimiter in (chr(13), chr(10)) then
  313.       n_size_current_line := n_size_current_line - 1;
  314.     end if;
  315.     dbms_output.put_line(case when n_line_counter > 1 then in_line_prefix end || substr(in_string, n_offset, n_size_current_line));
  316.     if s_delimiter in (chr(13), chr(10)) then
  317.       while substr(in_string, n_offset - 1 + n_size_current_line, 1) in (chr(10), chr(13)) loop
  318.         n_size_current_line := n_size_current_line + 1;
  319.       end loop;
  320.     end if;
  321.     n_offset := n_offset + n_size_current_line;
  322.     n_size_current_line := in_line_size;
  323.     n_line_counter := n_line_counter + 1;
  324.   end loop;
  325.   dbms_output.put_line(case when n_line_counter > 1 then in_line_prefix end || substr(in_string, n_offset));
  326. end put_line_smart;

  327. begin

  328.   dbms_output.put_line('--------------------------------------------------------------------------------------');

  329.   if ( upper(i_vc_idtype) = 'SPID' ) then
  330.     select addr into vc_paddr from v$process where spid=to_char(i_n_id);
  331.     select * into rec_session from v$session where paddr=vc_paddr;
  332.     select * into rec_sessionwait from v$session_wait where sid=rec_session.SID;
  333.     select decode(sql_hash_value,0,prev_hash_value,sql_hash_value) into n_hashvalue from v$session where sid=rec_session.SID;
  334.     select sql_text bulk collect into typsqltexts from v$sqltext where hash_value=n_hashvalue order by piece;

  335.     if ( typsqltexts.count > 0 ) then
  336.       for i in typsqltexts.first .. typsqltexts.last loop
  337.           ---这里处理掉"dbms_output.put_line"不能处理超过255个字符的限制,并且考虑到了sql语句中可能有中文
  338.           loop
  339.           exit when typsqltexts(i) is null;
  340.             dbms_output.put_line( substrb( typsqltexts(i), 1, 254 ) );
  341.             typsqltexts(i) := substrb( typsqltexts(i), 255 );
  342.           end loop;
  343.       end loop;
  344.     else
  345.       dbms_output.put_line('The sql text has been aged out from the shared pool.');
  346.     end if;
  347.   elsif ( upper(i_vc_idtype) = 'SID' ) then
  348.     select * into rec_session from v$session where sid=i_n_id;
  349.     select decode(sql_hash_value,0,prev_hash_value,sql_hash_value) into n_hashvalue from v$session where sid=i_n_id;
  350.     select sql_text bulk collect into typsqltexts from v$sqltext where hash_value=n_hashvalue order by piece;

  351.     if ( typsqltexts.count > 0 ) then
  352.       for i in typsqltexts.first .. typsqltexts.last loop
  353.           ---这里处理掉"dbms_output.put_line"不能处理超过255个字符的限制,并且考虑到了sql语句中可能有中文
  354.           loop
  355.           exit when typsqltexts(i) is null;
  356.             dbms_output.put_line( substrb( typsqltexts(i), 1, 254 ) );
  357.             typsqltexts(i) := substrb( typsqltexts(i), 255 );
  358.           end loop;
  359.       end loop;
  360.     else
  361.       dbms_output.put_line('The sql text has been aged out from the shared pool.');
  362.     end if;
  363.   else
  364.     dbms_output.put_line('invalid input id type parameter!');
  365.     return;
  366.   end if;

  367.   dbms_output.put_line('--------------------------------------------------------------------------------------');
  368.   dbms_output.put_line('The session id is ' || rec_session.SID);
  369.   dbms_output.put_line('The status is ' || rec_session.STATUS);
  370.   dbms_output.put_line('The sql hash value is ' || rec_session.SQL_HASH_VALUE);
  371.   --dbms_output.put_line('The child cursor number is ' || rec_session.SQL_CHILD_NUMBER);
  372.   dbms_output.put_line('The prev hash value is ' || rec_session.PREV_HASH_VALUE);
  373.   --dbms_output.put_line('The prev child cursor number is ' || rec_session.PREV_CHILD_NUMBER);
  374.   dbms_output.put_line('The osuser is ' || rec_session.OSUSER);
  375.   dbms_output.put_line('The machine is ' || rec_session.MACHINE);
  376.   dbms_output.put_line('The terminal is ' || rec_session.TERMINAL);
  377.   dbms_output.put_line('The program is ' || rec_session.PROGRAM);
  378.   dbms_output.put_line('The event is ' || rec_sessionwait.EVENT);
  379.   dbms_output.put_line('--------------------------------------------------------------------------------------');

  380.   --demo: alter system kill session '417,21188' immediate;
  381.   dbms_output.put_line('alter system kill session ''' || rec_session.SID || ',' || rec_session.SERIAL# || ''' immediate;');

  382.   select hash_value,child_number,plan_hash_value,executions,buffer_gets,buffer_gets/decode(executions,0,1,executions) gets_per_exec,
  383.     rows_processed,rows_processed/decode(executions,0,1,executions) rows_per_exec,
  384.     disk_reads,disk_reads/decode(executions,0,1,executions) reads_per_exec,
  385.     cpu_time/1000000 cpu_time,cpu_time/decode(executions,0,1,executions)/1000000 cpu_per_exec,
  386.     ELAPSED_TIME/1000000 ELAPSED_TIME,ELAPSED_TIME/decode(executions,0,1,executions)/1000000 ela_per_exec
  387.     bulk collect into hash_values,child_numbers,plan_hash_values,executions,buffer_gets,gets_per_execs,
  388.     rows_processeds,rows_per_execs,disk_reads,reads_per_execs,cpu_times,cpu_per_execs,ELAPSED_TIMEs,ela_per_execs
  389.     from v$sql where hash_value=n_hashvalue and rownum<=100;

  390.   if( hash_values.count > 0 ) then
  391.     for i in hash_values.first .. hash_values.last loop
  392.      
  393.      dbms_output.put_line('--------------------------------------------------------------------------------------');
  394.      dbms_output.put_line('The hash_value is ' || hash_values(i));
  395.      dbms_output.put_line('The child_number is ' || child_numbers(i));
  396.      dbms_output.put_line('The plan_hash_value is ' || plan_hash_values(i));
  397.      dbms_output.put_line('The execution is ' || executions(i));
  398.      dbms_output.put_line('The buffer_gets is ' || buffer_gets(i));
  399.      dbms_output.put_line('The gets_per_exec is ' || gets_per_execs(i));
  400.      dbms_output.put_line('The rows_processed is ' || rows_processeds(i));
  401.      dbms_output.put_line('The rows_per_exec is ' || rows_per_execs(i));
  402.      dbms_output.put_line('The disk_reads is ' || disk_reads(i));
  403.      dbms_output.put_line('The reads_per_exec is ' || reads_per_execs(i));
  404.      dbms_output.put_line('The cpu_time is ' || cpu_times(i));
  405.      dbms_output.put_line('The cpu_per_exec is ' || cpu_per_execs(i));
  406.      dbms_output.put_line('The ELAPSED_TIME is ' || ELAPSED_TIMEs(i));
  407.      dbms_output.put_line('The ela_per_exec is ' || ela_per_execs(i));
  408.      dbms_output.put_line('--------------------------------------------------------------------------------------');
  409.      
  410.       s_hash_value := n_hashvalue;
  411.       s_child_num := child_numbers(i);
  412.       -- Header information
  413.       dbms_output.put_line(chr(13));
  414.       put_line_smart(in_string => ' HASH_VALUE: ' || s_hash_value || ' CHILD_NUMBER: ' || s_child_num , in_line_size => max_line_size);
  415.       put_line_smart(in_string => '---------------------------------------------------------------------------------------------------------------------------------------------', in_line_size => max_line_size);
  416.       begin
  417.           execute immediate '
  418.         select sql_text,
  419.         plan_hash_value
  420.         from v$sql
  421.         where hash_value = to_number(:s_hash_value)
  422.         and child_number = to_number(:s_child_num)'
  423.         into s_output, s_plan_hash using s_hash_value, s_child_num;
  424.       exception
  425.       when NO_DATA_FOUND then
  426.         null;
  427.       when others then
  428.         dbms_output.put_line('Error getting SQL text from V$SQL, check privileges');
  429.       end;
  430.     
  431.       put_line_smart(s_output);
  432.       dbms_output.put_line(chr(13));
  433.       open c_display_cursor for s_display_cursor using to_number(s_hash_value), to_number(s_child_num);
  434.     
  435.       n_cnt := 1;
  436.     
  437.       fetch c_display_cursor into
  438.         a_column_list(1).a_data(n_cnt), -- a_p_id(n_cnt),
  439.         a_column_list(2).a_data(n_cnt), -- a_operation(n_cnt),
  440.         a_column_list(3).a_data(n_cnt), -- a_name(n_cnt),
  441.         a_column_list(4).a_data(n_cnt), -- a_starts(n_cnt),
  442.         a_column_list(5).a_data(n_cnt), -- a_e_rows(n_cnt),
  443.         a_column_list(6).a_data(n_cnt), -- a_a_rows(n_cnt),
  444.         a_column_list(7).a_data(n_cnt), -- a_a_time(n_cnt),
  445.         a_column_list(8).a_data(n_cnt), -- a_buffers(n_cnt),
  446.         a_column_list(9).a_data(n_cnt), -- a_reads(n_cnt),
  447.         a_column_list(10).a_data(n_cnt), -- a_writes(n_cnt),
  448.         a_column_list(11).a_data(n_cnt), -- a_in_out(n_cnt),
  449.         a_column_list(12).a_data(n_cnt), -- a_partition_start(n_cnt),
  450.         a_column_list(13).a_data(n_cnt), -- a_partition_stop(n_cnt),
  451.         a_column_list(14).a_data(n_cnt), -- a_distribution(n_cnt),
  452.         a_column_list(15).a_data(n_cnt), -- a_last_mem_usage(n_cnt),
  453.         a_column_list(16).a_data(n_cnt), -- a_last_degree(n_cnt),
  454.         a_column_list(17).a_data(n_cnt), -- a_mem_opt(n_cnt),
  455.         a_column_list(18).a_data(n_cnt), -- a_mem_one(n_cnt),
  456.         --a_column_list(17).a_data(n_cnt), -- a_opt_cnt(n_cnt),
  457.         --a_column_list(18).a_data(n_cnt), -- a_one_cnt(n_cnt),
  458.         --a_column_list(19).a_data(n_cnt), -- a_multi_cnt(n_cnt),
  459.         --a_column_list(22).a_data(n_cnt), -- a_max_tmp(n_cnt),
  460.         a_column_list(19).a_data(n_cnt), -- a_last_tmp(n_cnt),
  461.         a_access_pred(n_cnt),
  462.         a_filter_pred(n_cnt),
  463.         a_dyn_sampl(n_cnt),
  464.         a_id_list(n_cnt);
  465.     
  466.       if c_display_cursor%notfound then
  467.          close c_display_cursor;
  468.          --dbms_output.put_line('Debug : Select V$SQL_PLAN');
  469.          b_has_stat := FALSE;
  470.     
  471.          a_column_list(1).s_heading := 'Id'; --a_column_list(1).b_is_number := true;
  472.          a_column_list(2).s_heading := 'Operation';
  473.          a_column_list(3).s_heading := 'Name';
  474.          a_column_list(4).s_heading := 'Rows'; a_column_list(4).b_is_number := true;
  475.          a_column_list(5).s_heading := 'Bytes'; a_column_list(5).b_is_number := true;
  476.          a_column_list(6).s_heading := 'TempSpc'; a_column_list(6).b_is_number := true;
  477.          a_column_list(7).s_heading := 'Cost';a_column_list(7).b_is_number := true;
  478.          a_column_list(8).s_heading := 'Cpu-Cost';a_column_list(8).b_is_number := true;
  479.          a_column_list(9).s_heading := 'TQ';
  480.          a_column_list(10).s_heading := 'In-Out';
  481.          a_column_list(11).s_heading := 'Pstart'; a_column_list(10).b_is_number := true;
  482.          a_column_list(12).s_heading := 'Pstop'; a_column_list(11).b_is_number := true;
  483.          a_column_list(13).s_heading := 'PQ Distrib';
  484.     
  485.          open c_display_cursor for s_display_cursor2 using to_number(s_hash_value), to_number(s_child_num);
  486.          n_cnt := 0;
  487.       else
  488.          -- The plan statistics
  489.          a_column_list(1).s_heading := 'Id'; --a_column_list(1).b_is_number := true;
  490.          a_column_list(2).s_heading := 'Operation';
  491.          a_column_list(3).s_heading := 'Name';
  492.          a_column_list(4).s_heading := 'Starts'; a_column_list(4).b_is_number := true;
  493.          a_column_list(5).s_heading := 'E-Rows'; a_column_list(5).b_is_number := true;
  494.          a_column_list(6).s_heading := 'A-Rows'; a_column_list(6).b_is_number := true;
  495.          a_column_list(7).s_heading := 'A-Time';
  496.          a_column_list(8).s_heading := 'Buffers'; a_column_list(8).b_is_number := true;
  497.          a_column_list(9).s_heading := 'Reads'; a_column_list(9).b_is_number := true;
  498.          a_column_list(10).s_heading := 'Writes'; a_column_list(10).b_is_number := true;
  499.          a_column_list(11).s_heading := 'In-Out';
  500.          a_column_list(12).s_heading := 'Pstart'; a_column_list(12).b_is_number := true;
  501.          a_column_list(13).s_heading := 'Pstop'; a_column_list(13).b_is_number := true;
  502.          a_column_list(14).s_heading := 'PQ Distrib';
  503.          a_column_list(15).s_heading := 'OMem'; a_column_list(15).b_is_number := true;
  504.          a_column_list(16).s_heading := '1Mem'; a_column_list(16).b_is_number := true;
  505.          a_column_list(17).s_heading := 'Used-Mem'; a_column_list(17).b_is_number := true; --a_column_list(15).s_alignment := 'RIGHT';
  506.          a_column_list(18).s_heading := 'Last-Degree'; a_column_list(18).b_is_number := true;
  507.          --a_column_list(19).s_heading := 'Opt-Cnt'; a_column_list(17).b_is_number := true;
  508.          --a_column_list(20).s_heading := 'One-Cnt'; a_column_list(18).b_is_number := true;
  509.          --a_column_list(21).s_heading := 'Multi-Cnt'; a_column_list(19).b_is_number := true;
  510.          --a_column_list(19).s_heading := 'Max-Tmp'; a_column_list(19).b_is_number := true;
  511.          a_column_list(19).s_heading := 'Last-Tmp'; a_column_list(19).b_is_number := true;
  512.     
  513.          n_cnt := 1;
  514.       end if;
  515.     
  516.       loop
  517.         exit when c_display_cursor%notfound;
  518.         n_cnt := n_cnt + 1;
  519.         if b_has_stat then
  520.             fetch c_display_cursor into
  521.             a_column_list(1).a_data(n_cnt), -- a_p_id(n_cnt),
  522.             a_column_list(2).a_data(n_cnt), -- a_operation(n_cnt),
  523.             a_column_list(3).a_data(n_cnt), -- a_name(n_cnt),
  524.             a_column_list(4).a_data(n_cnt), -- a_starts(n_cnt),
  525.             a_column_list(5).a_data(n_cnt), -- a_e_rows(n_cnt),
  526.             a_column_list(6).a_data(n_cnt), -- a_a_rows(n_cnt),
  527.             a_column_list(7).a_data(n_cnt), -- a_a_time(n_cnt),
  528.             a_column_list(8).a_data(n_cnt), -- a_buffers(n_cnt),
  529.             a_column_list(9).a_data(n_cnt), -- a_reads(n_cnt),
  530.             a_column_list(10).a_data(n_cnt), -- a_writes(n_cnt),
  531.             a_column_list(11).a_data(n_cnt), -- a_in_out(n_cnt),
  532.             a_column_list(12).a_data(n_cnt), -- a_partition_start(n_cnt),
  533.             a_column_list(13).a_data(n_cnt), -- a_partition_stop(n_cnt),
  534.             a_column_list(14).a_data(n_cnt), -- a_distribution(n_cnt),
  535.             a_column_list(15).a_data(n_cnt), -- a_last_mem_usage(n_cnt),
  536.             a_column_list(16).a_data(n_cnt), -- a_last_degree(n_cnt),
  537.             a_column_list(17).a_data(n_cnt), -- a_mem_opt(n_cnt),
  538.             a_column_list(18).a_data(n_cnt), -- a_mem_one(n_cnt),
  539.             a_column_list(19).a_data(n_cnt), -- a_last_tmp(n_cnt),
  540.             a_access_pred(n_cnt),
  541.             a_filter_pred(n_cnt),
  542.             a_dyn_sampl(n_cnt),
  543.             a_id_list(n_cnt);
  544.         else
  545.             fetch c_display_cursor into
  546.             a_column_list(1).a_data(n_cnt),
  547.             a_column_list(2).a_data(n_cnt),
  548.             a_column_list(3).a_data(n_cnt),
  549.             a_column_list(4).a_data(n_cnt),
  550.             a_column_list(5).a_data(n_cnt),
  551.             a_column_list(6).a_data(n_cnt),
  552.             a_column_list(7).a_data(n_cnt),
  553.             a_column_list(8).a_data(n_cnt),
  554.             a_column_list(9).a_data(n_cnt),
  555.             a_column_list(10).a_data(n_cnt),
  556.             a_column_list(11).a_data(n_cnt),
  557.             a_column_list(12).a_data(n_cnt),
  558.             a_column_list(13).a_data(n_cnt),
  559.             a_access_pred(n_cnt),
  560.             a_filter_pred(n_cnt),
  561.             a_dyn_sampl(n_cnt),
  562.             a_id_list(n_cnt);
  563.          end if;
  564.       end loop;
  565.     
  566.       close c_display_cursor;
  567.       if a_column_list(1).a_data.count > 0 then
  568.         dbms_output.put_line('Plan hash value: ' || s_plan_hash);
  569.         dbms_output.put_line(chr(13));
  570.         n_row_size := 1;
  571.         for i in a_column_list.first..a_column_list.last loop
  572.           if a_column_list(i).b_is_number then
  573.             if a_column_list(i).a_data.count > 0 then
  574.               for j in a_column_list(i).a_data.first..a_column_list(i).a_data.last loop
  575.                 begin
  576.                   a_column_list(i).a_data(j) := display_cursor_format_number(a_column_list(i).a_data(j));
  577.                 exception
  578.                 when others then
  579.                   dbms_output.put_line('Column:' || a_column_list(i).s_heading || ' Data: ' || a_column_list(i).a_data(j));
  580.                   raise;
  581.                 end;
  582.               end loop;
  583.             end if;
  584.           end if;
  585.           -- column size is greatest of max size of content + 2 (leading + trailing blanks) and size of column heading
  586.           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);
  587.           a_column_list(i).b_has_data := not has_collection_only_nulls(a_column_list(i).a_data);
  588.           if a_column_list(i).b_has_data then
  589.             n_row_size := n_row_size + a_column_list(i).n_max_size + 1;
  590.           end if;
  591.         end loop;
  592.         -- Header
  593.         put_line_smart(in_string => lpad('-', n_row_size, '-'), in_line_size => max_line_size);
  594.         s_row := '';
  595.         for i in a_column_list.first..a_column_list.last loop
  596.           if a_column_list(i).b_has_data then
  597.             if a_column_list(i).s_alignment is null then
  598.               if a_column_list(i).b_is_number then
  599.                 s_row := s_row || '|' || lpad(a_column_list(i).s_heading, a_column_list(i).n_max_size - 1) || ' ';
  600.               else
  601.                 s_row := s_row || '|' || ' ' || rpad(a_column_list(i).s_heading, a_column_list(i).n_max_size - 1);
  602.               end if;
  603.             else
  604.               if a_column_list(i).s_alignment = 'RIGHT' then
  605.                 s_row := s_row || '|' || lpad(a_column_list(i).s_heading, a_column_list(i).n_max_size - 1) || ' ';
  606.               else
  607.                 s_row := s_row || '|' || ' ' || rpad(a_column_list(i).s_heading, a_column_list(i).n_max_size - 1);
  608.               end if;
  609.             end if;
  610.           end if;
  611.         end loop;
  612.         s_row := s_row || '|';
  613.         put_line_smart(in_string => s_row, in_line_size => max_line_size);
  614.         -- Data
  615.         put_line_smart(in_string => lpad('-', n_row_size, '-'), in_line_size => max_line_size);
  616.         for j in a_column_list(1).a_data.first..a_column_list(1).a_data.last loop
  617.           s_row := '';
  618.           for i in a_column_list.first..a_column_list.last loop
  619.             if a_column_list(i).b_has_data then
  620.               if a_column_list(i).b_is_number then
  621.                 s_row := s_row || '|' || lpad(nvl(a_column_list(i).a_data(j), ' '), a_column_list(i).n_max_size - 1) || ' ';
  622.               else
  623.                 s_row := s_row || '|' || ' ' || rpad(nvl(a_column_list(i).a_data(j), ' '), a_column_list(i).n_max_size - 1);
  624.               end if;
  625.             end if;
  626.           end loop;
  627.           s_row := s_row || '|';
  628.           put_line_smart(in_string => s_row, in_line_size => max_line_size);
  629.         end loop;
  630.         -- Footer
  631.         put_line_smart(in_string => lpad('-', n_row_size, '-'), in_line_size => max_line_size);
  632.         -- Predicate information
  633.         dbms_output.put_line(chr(13));
  634.         dbms_output.put_line('Predicate Information (identified by operation id):');
  635.         dbms_output.put_line('---------------------------------------------------');
  636.         for j in a_column_list(1).a_data.first..a_column_list(1).a_data.last loop
  637.           if a_access_pred(j) is not null or a_filter_pred(j) is not null then
  638.             s_output := lpad(to_char(to_number(a_id_list(j)), 'FM9999'), 4, ' ') || ' - ';
  639.             if a_access_pred(j) is not null then
  640.               put_line_smart(s_output || 'access(' || a_access_pred(j) || ')', lpad(' ', length(s_output), ' '));
  641.             end if;
  642.             if a_filter_pred(j) is not null then
  643.               if a_access_pred(j) is not null then
  644.                 put_line_smart(lpad(' ', length(s_output), ' ') || 'filter(' || a_filter_pred(j) || ')', lpad(' ', length(s_output), ' '));
  645.               else
  646.                 put_line_smart(s_output || 'filter(' || a_filter_pred(j) || ')', lpad(' ', length(s_output), ' '));
  647.               end if;
  648.             end if;
  649.           end if;
  650.         end loop;
  651.         --dbms_output.put_line('DEBUG:Begin Notes');
  652.         -- Notes section
  653.         if not a_column_list(4).b_has_data or a_dyn_sampl(1) = 'YES' then
  654.           dbms_output.put_line(chr(13));
  655.           dbms_output.put_line('Note');
  656.           dbms_output.put_line('-----');
  657.         end if;
  658.         if a_dyn_sampl(1) = 'YES' then
  659.           dbms_output.put_line(' - dynamic sampling used for this statement');
  660.         end if;
  661.         if not a_column_list(4).b_has_data then
  662.           dbms_output.put_line(' - Warning: basic plan statistics not available. These are only collected when:');
  663.           dbms_output.put_line(' * parameter ''statistics_level'' is set to ''ALL'', at session or system level');
  664.         end if;
  665.       else
  666.         dbms_output.put_line('SQL information could not be found for HASH_VALUE: ' || s_hash_value || ',CHILD_NUMBER: ' || s_child_num);
  667.         dbms_output.put_line('Please verify value of SQL address, hash_value and child_number;');
  668.         dbms_output.put_line('It could also be that the plan is no longer in cursor cache (check v$sql_plan)');
  669.       end if;

  670.     end loop;
  671.   end if;

  672. exception
  673.   when others then
  674.     o_vc_return_flag := 'E' || '_' || sqlcode || '_' || sqlerrm;
  675.     dbms_output.put_line(o_vc_return_flag);
  676.     return;

  677. end PRINTSQL;
  678. /

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/28878983/viewspace-2136888/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: display_cursor_9i.sql
请登录后发表评论 登录
全部评论

注册时间:2013-05-11

  • 博文量
    208
  • 访问量
    212342