TKPROF报告及其自动化

获取当前连接的trace文件

SELECT (SELECT value FROM v$parameter WHERE name='user_dump_dest')
|| '/'  || (SELECT instance_name FROM v$instance ) || '_ora_' ||spid ||'.trc' trace_file
FROM v$process
WHERE addr = (SELECT paddr FROM v$session WHERE sid IN (SELECT sid FROM v$mystat WHERE rownum=1));
--11g +
SELECT value
from   v$diag_info
WHERE  name = 'Default Trace File';


开启10046

alter session set timed_statistics=true;
alter session set events '10046 trace name context forever, level 12';
--Works for Oracle 10g+
EXEC DBMS_MONITOR.client_id_trace_enable(client_id=>'hello', waits=>TRUE, binds=>FALSE);
EXEC DBMS_MONITOR.client_id_trace_disable(client_id=>'hello');

Tkprof

login oracle server.
cp ~/
tkprof my.txt
vi my.txt

Tkprof报告解读

tkprof包含:
  • SQL_ID
  • 原始SQL。不显示绑定变量的值。
  • SQL在parse, execute各阶段的统计信息
  • 执行计划及统计信息
  • wait events
Execute VS Fetch
EXECUTE: Actual execution of the statement by Oracle. For INSERT, UPDATE, and DELETE statements, this modifies the data. For SELECT statements, this identifies the selected rows.
FETCH: Retrieves rows returned by a query. Fetches are only performed for SELECT statements.
fetch = sql*net message to/from client == rows processed/arraysize. 这里rows processed 是指最终结果集里有多少行数据。

CPU Time VS Elapsed Time
单进程时,CPU时间通常小于流逝时间。流逝时间包含CPU运算,IO操作,Oracle等待。
Oracle并发执行SQL时,因为多个CPU参与工作,CPU时间可能大于流逝时间。
当CPU time << elapsed时,一种可能是Oracle的wait events过多。比如IO, 网络。比如Arraysize设置过小,Oracle不得不频繁等待网络传送。
CPU Time Elapsed Times,同时wait events也不多的话。可能是服务器上除了Oracle外,运行了其他非常消耗CPU的程序。Oracle不等不等待OS分配CPU。

Misses in library cache during parse: 1  表示这是一个硬解析

Query: Consistent read. 涉及到读取undo,而undo是由redo保护的。
Current: current read。常见于update/delete,Oracle需要读取数据的当前版本做update/delete。

cr = consistent read
pr = physical read
pw = physical write
time = 0 us 百万分之一秒

自动化脚本参考了Tom Kyte Effective Oracle by Design一书的代码:
create or replace directory UDUMP_DIR as 'xxxx';

create view sess_trc_file_name
as
select d.instance_name || '_ora_' || ltrim(to_char(a.spid)) || 
       '.trc' filename
  from v$process a, v$session b, v$instance d
 where a.addr = b.paddr
   and b.audsid = sys_context( 'userenv', 'sessionid');


create or replace package tkprof_util 
as
  TYPE vcarray IS table of varchar2(4000);  
  function trace_file_contents( p_filename in varchar2 )  
      return vcarray  
      pipelined;  
end;
/
show errors;

create or replace package body tkprof_util as
  function trace_file_contents( p_filename in varchar2 )  
    return vcArray  
    pipelined  
    as  
        l_bfile       bfile := bfilename('UDUMP_DIR',p_filename);  
        l_last        number := 1;  
        l_current     number := 0;  
    begin  
        dbms_lob.fileopen( l_bfile );  
        loop  
            l_current := dbms_lob.instr(l_bfile, '0A', l_last, 1);  
            exit when (nvl(l_current,0) = 0);  
            pipe row(  
              utl_raw.cast_to_varchar2(  
                  dbms_lob.substr( l_bfile, l_current-l_last+1,  
                                                        l_last ) )  
            );  
            l_last := l_current+1;  
        end loop;  
        dbms_lob.fileclose(l_bfile);  
        return;  
    end;  
end;

grant execute on tkprof_util to public;
创建SQL脚本: tkprof.sql
set termout off
set heading off
set feedback off
set embedded on
set linesize 4000
set arraysize 400
set trimspool on
set verify off

column filename new_val f
select filename from sess_trace_file;

alter session set timed_statistics=true;
alter session set events '10046 trace name context forever, level 12';

--Replace this with your SQL
@exe1.sql

alter session set events '10046 trace name context off';

spool &f
select * from TABLE( acrm.trace_file_contents( '&f' ) );
spool off

set heading on
col sql_text format a40
spool &f.stats

@stats.sql;

spool off
exit
将要执行的SQL放入:exe1.sql
创建stats.sql
select substr(sql_text, 1,40) sql_text,sql_id, to_char(last_active_time, 'yyyy/mm/dd hh24:mi:ss') last_active_time, parse_calls, disk_reads, direct_writes, buffer_gets,
rows_processed, round(cpu_time/1000000,2) cpu_seconds, round(elapsed_time/1000000,2) elapsed_second, round(concurrency_wait_time/1000000,2) concurrency_seconds, round(user_io_wait_time/1000000,2) io_seconds,
round(plsql_exec_time/1000000,2) plsql_seconds
from v$sqlstats where sql_text like '%&f%' and
last_active_time is not null
and trunc(last_active_time)=trunc(sysdate)
order by last_active_time desc;
用sqlplus 执行创建的脚本: sqlplus /@ @tkprof.sql

追踪PX/QC 
内容来源于 https://blogs.oracle.com/db/entry/how_to_get_a_10046_trace_for_a_parallel_query
alter session set timed_statistics = true;
alter session set statistics_level=all;
alter session set "_px_trace" = low , messaging;
alter session set max_dump_file_size = unlimited;
alter session set events '10046 trace name context forever,level 12';

select /*+ parallel(2) */ count(*) from bisample.samp_revenue_f;

alter session set events '10046 trace name context off';
alter session set "_px_trace" = none;
在QC session的trace文件中含有如下:
Acquired 2 slaves on 1 instances avg height=2 #set=1 qser=3073
3991                 P000 inst 1 spid 5759
3992                 P001 inst 1 spid 5763
slave process的trace文件名中含有spid 5759, 5793。
然后在background_dump目录里查找文件名含有p00x的trc文件。
用tkprof工具格式化后就可以查看到slave process, QC的完整tkprof报告了。
对于同一SQL,各个QC/PX的执行计划一样。但是统计信息会不一样,比如:第一二三列rows, cr(Consistent read), time 等等,通过观察这些,我们可以知道每个进程在整个执行计划中负担的工作,完成工作需要的时间,进而得到一个总体印象。
QC负责调度,实际的工作都有px完成。因而查看px的tkprof报告才能得到更准确的信息。
QC/PX的报告中等待事件常常不一样,生产者进程中常见PX Deq Credit: send blkd,消费者进程常见PX Deq: Execution Msg。QC常见PX Deq: Execute Reply



你可能感兴趣的:(10046,tkprof,Oracle调优)