2.3 如何得到真實的執行計劃 《基於Oracle的優化(學習筆記)》
阿新 • • 發佈:2018-12-10
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;