1. 程式人生 > >2.3 如何得到真實的執行計劃 《基於Oracle的優化(學習筆記)》

2.3 如何得到真實的執行計劃 《基於Oracle的優化(學習筆記)》

  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;