diff --git a/tests/lib/mystats/README.txt b/tests/lib/mystats/README.md similarity index 52% rename from tests/lib/mystats/README.txt rename to tests/lib/mystats/README.md index 5fafb00f4..c012220a6 100644 --- a/tests/lib/mystats/README.txt +++ b/tests/lib/mystats/README.md @@ -1,40 +1,34 @@ +# MYSTATS -MYSTATS README -============== +## 1.0 Introduction +This repository contains two versions of the MyStats utility. This reports on the resource usage between two snapshots in an active database session. It is a combination of Jonathan Lewis's SNAP_MY_STATS package and my own re-factoring of Tom Kyte's runstats utility (also available via www.oracle-developer.net or github.com/oracle-developer/runstats). I've also added some functionality and flexibility around the statistics reporting section. -1.0 Introduction ----------------- -This archive contains two versions of the MyStats utility. This reports on the resource usage between two snapshots in an active database session. It is a combination of Jonathan Lewis's SNAP_MY_STATS package and my own re-factoring of Tom Kyte's runstats utility (also available via www.oracle-developer.net). I've also added some functionality and flexibility around the statistics reporting section. +## 2.0 Versions +There are two versions provided. -2.0 Versions ------------- -There are two versions provided: - -2.1 mystats_pkg.sql -- - - - - - - - - - +### 2.1 mystats_pkg.sql This creates via a single PL/SQL package named MYSTATS_PKG. This uses invoker rights and dynamic SQL to workaround the common issue whereby developers are not given explicit grants on the required V$ views but have V$ access via a role. See the comments in the package header for more details and usage instructions. -2.2 mystats.sql -- - - - - - - - +### 2.2 mystats.sql This version is a standalone SQL*Plus script that runs MyStats from your SQLPATH without the need to create any database objects. This can be used if you are not able to create the PL/SQL package version of MyStats. See the comments in the script header for more details and usage instructions. -3.0 Version History -------------------- +## 3.0 Version History +``` Version Date Description --------- --------------- -------------------------------------------- +-------- --------------- ---------------------------------------------- 1.0 June 2007 Original version 1.1 January 2009 Added extended reporting options 2.0 October 2011 Re-design for standalone script version 2.01 November 2011 Bug-fix for numeric overflow +3.0 November 2015 Added extended snapshot and reporting options +``` -4.0 Credits ------------ -Credit is given to Jonathan Lewis for his original idea of taking two snapshots to identify resource consumption. +## 4.0 Credits +1. Credit is given to Jonathan Lewis for his original idea of taking two snapshots to identify resource consumption. +2. Thanks to Martin Bach for suggesting (and providing a prototype) for extended snapshot and reporting options. -5.0 Disclaimer --------------- +## 5.0 Disclaimer See http://www.oracle-developer.net/disclaimer.php Adrian Billington (c) www.oracle-developer.net - diff --git a/tests/lib/mystats/mystats.sql b/tests/lib/mystats/mystats.sql index bfd42a219..1d09a0c09 100644 --- a/tests/lib/mystats/mystats.sql +++ b/tests/lib/mystats/mystats.sql @@ -2,105 +2,143 @@ -- ---------------------------------------------------------------------------------------------- -- -- Utility: MyStats --- +-- -- Script: mystats.sql --- --- Version: 2.01 --- +-- +-- Version: 3.0 +-- -- Author: Adrian Billington -- www.oracle-developer.net --- (c) oracle-developer.net --- +-- (c) oracle-developer.net +-- -- Description: A free-standing SQL*Plus script to output the resource consumption of a unit or --- units of work as recorded in v$mystat, v$latch and v$sess_time_model. +-- units of work as recorded in v$mystat, v$latch and v$sess_time_model. -- Based on Jonathan Lewis's SNAP_MY_STATS package but as a standalone script (i.e. --- no database objects need to be created. --- +-- no database objects need to be created). +-- -- Key Differences -- --------------- --- +-- -- a) This is a SQL*Plus script that requires no objects to be created; --- +-- -- b) This includes latch statistics and makes use of Tom -- Kyte's RUNSTATS method for distinguising between stats -- and latches; --- +-- -- c) This includes advanced reporting options (see Usage and Examples -- sections below for details); --- +-- -- d) This includes a session time model report; --- +-- -- e) This requires at least version 10.1 to run because it -- makes use of collection methods such as MEMBER OF and -- reports on V$SESS_TIME_MODEL statistics. --- +-- -- Configuration: Edit the c_ms_rmcmd variable in the Constants section at the start of this -- script to use the correct file deletion command for your SQL*Plus client -- platform. It is defaulted to a Windows "del" command, so you will need to -- change it if you are using a Linux/Unix SQL*Plus client. --- +-- -- Reason: To make this run in standalone mode, a couple of temporary files -- are written to your current directory. These files are automatically -- removed on completion of this script. --- --- Usage: @mystats start +-- +-- Usage: @mystats start [optional statistics type(s)] -- ---- -- @mystats stop [optional reporting parameter] +-- +-- Optional statistics types format: -- --- Optional reporting parameter formats: --- --- Short Format Long Format Equivalent --- --------------- ---------------------- --- t= threshold= --- l= like= --- n= names= +-- Short Format Long Format Equivalent +-- ----------------------- ---------------------- +-- s=[csv] stattypes=[csv] +-- +-- Statistics types values for the csv list are as follows: -- --- Use double-quotes when the strings contain spaces. +-- Statistics Type Short Format Long Format Equivalent +-- --------------- ------------ ---------------------- +-- Statistic s statistic +-- Latch l latch +-- Time Model t time +-- All (default) a all -- +-- Optional reporting parameter formats: +-- +-- Short Format Long Format Equivalent +-- ----------------------- ---------------------- +-- t= threshold= +-- l= like= +-- n= names= +-- r= regexp= +-- +-- Use double-quotes when the strings contain spaces, +-- e.g. "option=value with space" +-- -- Examples: 1. Output all statistics -- ------------------------------------------------------------- -- @mystats start -- ---- -- @mystats stop --- +-- -- 2. Output statistics with delta values >= 1,000 --- ------------------------------------------------------------- +-- ------------------------------------------------------------- -- @mystats start -- ---- -- @mystats stop t=1000 --- +-- -- 3. Output statistics for "redo size" and "user commits" only -- ------------------------------------------------------------- -- @mystats start -- ---- -- @mystats stop "n=redo size, user commits" --- --- 4. Output statistics for those containing the word 'memory' +-- +-- 4. Output statistics for those containing the word 'memory' -- ------------------------------------------------------------- -- @mystats start -- ---- -- @mystats stop l=memory -- +-- 5. Output statistics for those with I/O, IO, i/o or io in the name +-- ------------------------------------------------------------------ +-- @mystats start +-- ---- +-- @mystats stop r=I/?O\s +-- +-- 6. Capture and output statistics and time model only +-- ------------------------------------------------------------- +-- @mystats start s=s,t +-- ---- +-- @mystats stop +-- +-- 7. Output statistics only for those containing 'parallel' +-- ------------------------------------------------------------- +-- @mystats start s=s +-- ---- +-- @mystats stop l=parallel +-- -- Notes: 1. See http://www.jlcomp.demon.co.uk/snapshot.html for original -- version. --- +-- -- 2. As described in Configuration above, this script writes and removes -- a couple of temporary files during execution. -- --- 3. A PL/SQL package version of MyStats is also available. +-- 3. A PL/SQL package version of MyStats (v3.0) is also available. -- +-- 4. Thanks to Martin Bach for the idea to provide a regexp reporting filter +-- option and some example code. +-- -- Disclaimer: http://www.oracle-developer.net/disclaimer.php -- -- ---------------------------------------------------------------------------------------------- -set define on autoprint off +set define on autoprint off set serveroutput on format wrapped -- Constants... -- ----------------------------------------------------------------------- -define c_ms_version = 2.01 ---define c_ms_rmcmd = "del" --Windows -define c_ms_rmcmd = "rm" --Unix/Linux +define c_ms_version = 3.0 +define c_ms_rmcmd = "del" --Windows +--define c_ms_rmcmd = "rm" --Unix/Linux define c_ms_init = "_ms_init.sql" define c_ms_clear = "_ms_teardown.sql" @@ -114,7 +152,7 @@ col 2 new_value 2 select null as "1" , null as "2" -from dual +from dual where 1=2; @@ -149,10 +187,14 @@ host &c_ms_rmcmd "&c_ms_init" -- Parse the options... -- ----------------------------------------------------------------------- -column threshold noprint new_value v_ms_threshold -column namelist noprint new_value v_ms_name_list -column namelike noprint new_value v_ms_name_like -column ms_option noprint new_value v_ms_option +column threshold noprint new_value v_ms_threshold +column namelist noprint new_value v_ms_name_list +column namelike noprint new_value v_ms_name_like +column regexplike noprint new_value v_ms_name_regexp +column stattypes noprint new_value v_ms_stattypes +column ms_option noprint new_value v_ms_option +column start_option noprint new_value v_ms_start_option +column stop_option noprint new_value v_ms_stop_option select case when o in ('threshold','t') @@ -161,7 +203,11 @@ select case then 2 when o in ('like','l') then 3 - else 4 + when o in ('regex','r') + then 4 + when o in ('stattype','s') + then 5 + else 0 end as ms_option , case when o in ('threshold','t') @@ -178,13 +224,44 @@ select case then '''%' || v || '%''' else 'null' end as namelike +, case + when o in ('regexp','r') + then '''' || v || '''' + else 'null' + end as regexplike +&v_ms_if_start , case +&v_ms_if_start when o in ('stattype','s') +&v_ms_if_start then regexp_replace(v, ' *, *', ',') +&v_ms_if_start when o is null +&v_ms_if_start then 'all' +&v_ms_if_start end as stattypes +&v_ms_if_start , p as start_option +, p as stop_option from ( select trim(regexp_substr(lower('&p_ms_option'), '[^=]+')) as o , trim(regexp_substr('&p_ms_option', '[^=]+', 1, 2)) as v + , '&p_ms_option' as p from dual ); +-- Stattypes include/exclude section... +-- ----------------------------------------------------------------------- +column snap noprint +column include_stats noprint new_value v_ms_include_statistics +column include_latches noprint new_value v_ms_include_latches +column include_time noprint new_value v_ms_include_time_model + +select snap +&v_ms_if_start , case when regexp_like('&v_ms_stattypes', '(^|,)(s|statistic|a|all)(,|$)') then 'Y' else 'N' end as include_stats +&v_ms_if_start , case when regexp_like('&v_ms_stattypes', '(^|,)(l|latch|a|all)(,|$)') then 'Y' else 'N' end as include_latches +&v_ms_if_start , case when regexp_like('&v_ms_stattypes', '(^|,)(t|time|a|all)(,|$)') then 'Y' else 'N' end as include_time +from ( + select rtrim(lower('&p_ms_snap'),';') as snap + from dual + ); + + -- The utility... -- ----------------------------------------------------------------------- set termout on @@ -216,10 +293,17 @@ declare -- Utility info... -- ------------------------------------------------------------------------- + procedure ms_options is + begin + dbms_output.put_line('- Statistics types : ' || nvl('&v_ms_start_option', 'all')); + dbms_output.put_line('- Reporting filter : ' || nvl('&v_ms_stop_option', 'none')); + end ms_options; + procedure ms_info is begin dbms_output.put_line('- MyStats v&c_ms_version by Adrian Billington (http://www.oracle-developer.net)'); - dbms_output.put_line('- Based on the SNAP_MY_STATS utility by Jonathan Lewis'); + dbms_output.put_line('- Original version based on the SNAP_MY_STATS utility by Jonathan Lewis'); + dbms_output.new_line(); end ms_info; -- Snapshot procedure... @@ -233,17 +317,20 @@ declare from v$statname a , v$mystat b where a.statistic# = b.statistic# + and '&v_ms_include_statistics' = 'Y' union all select 'LATCH' , name - , gets + , gets from v$latch + where '&v_ms_include_latches' = 'Y' union all select 'TIME' , stat_name , value from v$sess_time_model - where sid = sys_context('userenv','sid')]' + where sid = sys_context('userenv','sid') + and '&v_ms_include_time_model' = 'Y']' ) into p_stats from dual; end ms_snap; @@ -338,17 +425,23 @@ declare where (&v_ms_option = 1 and abs(diff) >= &v_ms_threshold) or (&v_ms_option = 2 and name in (&v_ms_name_list)) or (&v_ms_option = 3 and name like &v_ms_name_like) - or &v_ms_option = 4 + or (&v_ms_option = 4 and regexp_like(name, &v_ms_name_regexp, 'i')) + or &v_ms_option = 0 order by abs(diff) ) loop - dbms_output.put_line(rpad(r.type,8) || rpad(r.name,64) || + dbms_output.put_line(rpad(r.type,8) || rpad(r.name,64) || lpad(to_char(r.diff,'999,999,999,999'),18)); end loop; + -- Options... + -- ---------- + sh('3. Options Used', false); + ms_options; + -- About... -- ------- - sh('3. About', false); + sh('4. About', false); ms_info; nl; @@ -376,7 +469,7 @@ begin ms_snap(g_snaps.snap2); ms_report(g_times, g_snaps); else - raise_application_error( -20000, + raise_application_error( -20000, 'Incorrect parameter at position 1 '|| '[used="&v_ms_snap"; valid="start" or "stop"]', false ); @@ -392,6 +485,12 @@ spool "&c_ms_clear" replace prompt &v_ms_if_stop undefine bv_ms_start prompt &v_ms_if_stop undefine bv_ms_ela_start prompt &v_ms_if_stop undefine bv_ms_cpu_start +prompt &v_ms_if_stop undefine v_ms_stattypes +prompt &v_ms_if_stop undefine v_ms_include_statistics +prompt &v_ms_if_stop undefine v_ms_include_latches +prompt &v_ms_if_stop undefine v_ms_include_time_model +prompt &v_ms_if_stop undefine v_ms_start_option +prompt &v_ms_if_stop undefine v_ms_stop_option spool off @"&c_ms_clear" host &c_ms_rmcmd "&c_ms_clear" @@ -408,6 +507,7 @@ undefine v_ms_if_start undefine v_ms_threshold undefine v_ms_name_list undefine v_ms_name_like +undefine v_ms_name_regexp undefine v_ms_option undefine c_ms_version set termout on diff --git a/tests/lib/mystats/mystats_pkg.sql b/tests/lib/mystats/mystats_pkg.sql index e1938f182..ef9006c21 100644 --- a/tests/lib/mystats/mystats_pkg.sql +++ b/tests/lib/mystats/mystats_pkg.sql @@ -9,7 +9,7 @@ create or replace package mystats_pkg authid current_user as || || Script: mystats_pkg.sql || - || Version: 2.01 + || Version: 3.0 || || Author: Adrian Billington || www.oracle-developer.net @@ -43,7 +43,28 @@ create or replace package mystats_pkg authid current_user as || makes use of collection methods such as MEMBER OF and || also reports on V$SESS_TIME_MODEL statistics. || - || Usage: 1. Output all statistics + || Usage: exec mystats_pkg.ms_start( [optional statistics include/exclude parameters] ) + || ---- + || exec mystats_pkg.ms_stop( [optional reporting parameters] ) + || + || Optional statistics types are selected during calls to the MS_START procedure + || and are all included by default: + || + || 1. Statistics (V$SESSTAT) + || 2. Latches (V$LATCH) + || 3. Time Model (V$SESS_TIME_MODEL) + || + || Optional reporting parameters are specified during calls to the MS_STOP procedure + || and take one of the following formats: + || + || 1. Threshold (numeric, using P_THRESHOLD parameter (numeric)) + || 2. Statistic names (array of statnames, using P_STATNAMES parameter (collection)) + || 3. Statistic name LIKE pattern (statname pattern, using P_STATNAME_LIKE parameter (string)) + || 4. Statistic name REGEXP pattern (statname pattern, using P_STATNAME_LIKE and P_USE_REGEXP parameters (string and boolean)) + || + || See examples below. + || + || 1. Output all statistics || ------------------------------------------------------------- || exec mystats_pkg.ms_start; || ---- @@ -53,19 +74,37 @@ create or replace package mystats_pkg authid current_user as || ------------------------------------------------------------- || exec mystats_pkg.ms_start; || ---- - || exec mystats_pkg.ms_stop(1000); + || exec mystats_pkg.ms_stop(p_threshold=>1000); || || 3. Output statistics for "redo size" and "user commits" only || ------------------------------------------------------------- || exec mystats_pkg.ms_start; || ---- - || exec mystats_pkg.ms_stop(mystats_pkg.statname_ntt('redo size', 'user commits')); + || exec mystats_pkg.ms_stop(p_statnames=>mystats_pkg.statname_ntt('redo size', 'user commits')); || || 4. Output statistics for those containing the word 'memory' || ----------------------------------------------------------- || exec mystats_pkg.ms_start; || ---- - || exec mystats_pkg.ms_stop('memory'); + || exec mystats_pkg.ms_stop(p_statname_like=>'memory'); + || + || 5. Output statistics for those with I/O, IO, i/o or io in the name + || ------------------------------------------------------------------ + || exec mystats_pkg.ms_start; + || ---- + || exec mystats_pkg.ms_stop(p_statname_like=>'I/?O\s', p_use_regexp=>true); + || + || 6. Capture and output statistics and time model only (exclude latches) + || ---------------------------------------------------------------------- + || exec mystats_pkg.ms_start(p_include_latches=>false); + || ---- + || exec mystats_pkg.ms_stop; + || + || 7. Output statistics only for those containing 'parallel' + || ------------------------------------------------------------- + || exec mystats_pkg.ms_start(p_include_latches=>false, p_include_time_model=>false); + || ---- + || exec mystats_pkg.ms_stop(p_statname_like=>'parallel'); || || Notes: 1. Serveroutput must be on (and set higher than default); || @@ -83,7 +122,9 @@ create or replace package mystats_pkg authid current_user as type statname_ntt is table of varchar2(64); - procedure ms_start; + procedure ms_start( p_include_statistics in boolean default true, + p_include_latches in boolean default true, + p_include_time_model in boolean default true ); procedure ms_stop; @@ -91,20 +132,21 @@ create or replace package mystats_pkg authid current_user as procedure ms_stop( p_statnames in mystats_pkg.statname_ntt ); - procedure ms_stop( p_statname_like in varchar2 ); + procedure ms_stop( p_statname_like in varchar2, + p_use_regexp in boolean default false ); end mystats_pkg; / create or replace package body mystats_pkg as - /* - || A range of (sub)types for capturing statistics information... - */ - subtype st_stattype is varchar2(6); - subtype st_statname is varchar2(64); - subtype st_statvalue is integer; - subtype st_output is varchar2(255); + -- A range of (sub)types for capturing statistics information... + -- ------------------------------------------------------------- + subtype st_option_flag is varchar2(1); + subtype st_stattype is varchar2(6); + subtype st_statname is varchar2(64); + subtype st_statvalue is integer; + subtype st_output is varchar2(255); type rt_statistic is record ( type st_stattype @@ -117,21 +159,18 @@ create or replace package body mystats_pkg as type aat_mystats is table of aat_statistic index by pls_integer; - /* - || This is the "mystats array" to hold two snapshots... - */ + -- This is the "mystats array" to hold two snapshots... + -- ---------------------------------------------------- ga_mystats aat_mystats; - /* - || Array offsets into the main mystats array, used to - || determine the start and end points of a run... - */ + -- Array offsets into the main mystats array, used to + -- determine the start and end points of a run... + -- -------------------------------------------------- c_run1 constant pls_integer := 1; c_run2 constant pls_integer := 2; - /* - || Globals for elapsed time calculation... - */ + -- Globals for elapsed time calculation... + -- --------------------------------------- type rt_time is record ( ela_time integer , cpu_time integer ); @@ -139,10 +178,44 @@ create or replace package body mystats_pkg as g_start_time rt_time; g_end_time rt_time; + -- Globals to capture snapshot options... + g_include_statistics st_option_flag; + g_include_latches st_option_flag; + g_include_time_model st_option_flag; + + ------------------------------------------------------------------------------ + procedure ms_options( p_threshold in pls_integer, + p_statnames in mystats_pkg.statname_ntt, + p_statname_like in varchar2, + p_statname_regexp in varchar2 ) is + v_filter varchar2(4000); + begin + dbms_output.put('- Statistics types : '); + dbms_output.put('statistics=' || g_include_statistics || ', '); + dbms_output.put('latches=' || g_include_latches || ', '); + dbms_output.put_line('time model=' || g_include_time_model); + if p_threshold is not null then + v_filter := 'threshold=' || p_threshold; + elsif p_statname_like is not null then + v_filter := 'statnames like=' || p_statname_like || ', regular expression=N'; + elsif p_statname_regexp is not null then + v_filter := 'statnames like=' || p_statname_regexp || ', regular expression=Y'; + elsif p_statnames is not null and p_statnames is not empty then + v_filter := 'statnames in='; + for i in 1 .. p_statnames.count loop + v_filter := v_filter || p_statnames(i) || ','; + end loop; + v_filter := rtrim(v_filter, ','); + else + v_filter := 'None'; + end if; + dbms_output.put_line('- Reporting filter : ' || v_filter); + end ms_options; + ------------------------------------------------------------------------------ procedure ms_info is begin - dbms_output.put_line('- MyStats v2.01 by Adrian Billington (http://www.oracle-developer.net)'); + dbms_output.put_line('- MyStats v3.0 by Adrian Billington (http://www.oracle-developer.net)'); dbms_output.put_line('- Based on the SNAP_MY_STATS utility by Jonathan Lewis'); end ms_info; @@ -168,34 +241,38 @@ create or replace package body mystats_pkg as snap_time; end if; - /* - || Dynamic SQL (combined with invoker rights in the spec) works around - || the need to have explicit select granted on the referenced v$ views. - || Of course, we still need access granted via a role or other privilege - || but I've always been able to get the latter and rarely the former... - */ + -- Dynamic SQL (combined with invoker rights in the spec) works around + -- the need to have explicit select granted on the referenced v$ views. + -- Of course, we still need access granted via a role or other privilege + -- but I've always been able to get the latter and rarely the former... + -- --------------------------------------------------------------------- open rc_stat for q'[select 'STAT' as type , a.name , b.value from v$statname a , v$mystat b where a.statistic# = b.statistic# + and :g_include_statistics = 'Y' union all select 'LATCH' , name , gets from v$latch + where :g_include_latches = 'Y' union all select 'TIME' , 'elapsed time' , hsecs from v$timer + where :g_include_time_model = 'Y' union all select 'TIME' , stat_name , value from v$sess_time_model - where sid = sys_context('userenv','sid')]'; + where sid = sys_context('userenv','sid') + and :g_include_time_model = 'Y']' + using g_include_statistics, g_include_latches, g_include_time_model, g_include_time_model; fetch rc_stat bulk collect into aa_stats; close rc_stat; for i in 1 .. aa_stats.count loop @@ -210,47 +287,44 @@ create or replace package body mystats_pkg as end ms_snap; ------------------------------------------------------------------------------ - procedure ms_report( p_threshold in pls_integer default null, - p_statnames in mystats_pkg.statname_ntt default null, - p_statname_like in varchar2 default null ) is + procedure ms_report( p_threshold in pls_integer default null, + p_statnames in mystats_pkg.statname_ntt default null, + p_statname_like in varchar2 default null, + p_statname_regexp in varchar2 default null ) is v_name st_statname; --<-- offset for varchar2 associative arrays v_indx pls_integer; --<-- offset for pls_integer associative arrays v_type st_stattype; --<-- statistic type v_value st_statvalue; --<-- snapshot value for a statistic - /* - || Downside of using associative arrays is that we have to sort - || the output. So here's a couple of types and a variable to enable us - || to do that... - */ + -- Downside of using associative arrays is that we have to sort + -- the output. So here's a couple of types and a variable to enable us + -- to do that... + -- ------------------------------------------------------------------- type aat_mystats_output is table of st_output index by st_statname; type aat_mystats_sorted is table of aat_mystats_output index by pls_integer; aa_mystats_sorted aat_mystats_sorted; - /* - || Procedure to add a statistic to the sorted mystats array... - */ + -- Procedure to add a statistic to the sorted mystats array... + -- ----------------------------------------------------------- procedure sort ( p_stattype in st_stattype, p_statname in st_statname, p_value in number ) is v_offset pls_integer; v_output st_output; begin - /* - || Workaround the offset limits of a PLS_INTEGER associative array... - */ + -- Workaround the offset limits of a PLS_INTEGER associative array... + -- ------------------------------------------------------------------ v_offset := least(abs(p_value),2147483647); v_output := rpad(p_stattype, 8) || rpad(p_statname, 64) || lpad(to_char(p_value,'999,999,999,999'),18); aa_mystats_sorted(v_offset)(p_statname) := v_output; end sort; - /* - || Report formatting procedures... - */ + -- Report formatting procedures... + -- ------------------------------- procedure div( p_divider in varchar2 default '-', p_width in pls_integer default 90 ) is begin @@ -280,54 +354,48 @@ create or replace package body mystats_pkg as begin - /* - || Report header... - */ + -- Report header... + -- ---------------- nl; div('='); dbms_output.put_line('MyStats report : ' || to_char(sysdate,'dd-MON-YYYY hh24:mi:ss')); div('='); - /* - || Summary timings... - */ + -- Summary timings... + -- ------------------ sh('1. Summary Timings'); dbms_output.put_line(rpad('TIMER', 8) || rpad('snapshot interval (seconds)', 64) || lpad(to_char(round((g_end_time.ela_time-g_start_time.ela_time)/100,2), 'fm999,990.00'),18)); dbms_output.put_line(rpad('TIMER', 8) || rpad('CPU time used (seconds)', 64) || lpad(to_char(round((g_end_time.cpu_time-g_start_time.cpu_time)/100,2), 'fm999,990.00'),18)); - /* - || Now sort the output according to difference. A fudge is that we have to sort - || it manually and also work around the offset limits of an associative array... - */ + -- Now sort the output according to difference. A fudge is that we have to sort + -- it manually and also work around the offset limits of an associative array... + -- ----------------------------------------------------------------------------- v_name := ga_mystats(c_run1).first; while v_name is not null loop - /* - || Retrieve stattype... - */ + -- Retrieve stattype... + -- -------------------- v_type := ga_mystats(c_run1)(v_name).type; - /* - || Calculate the value of the current statistic... - */ + -- Calculate the value of the current statistic... + -- ----------------------------------------------- v_value := ga_mystats(c_run2)(v_name).value - ga_mystats(c_run1)(v_name).value; - /* - || If it's greater than the threshold or a statistic we are interested in, - || then output it. The downside of using purely associative arrays is that - || we don't have any easy way of sorting. So we have to do it ourselves... - */ + -- If it's greater than the threshold or a statistic we are interested in, + -- then output it. The downside of using purely associative arrays is that + -- we don't have any easy way of sorting. So we have to do it ourselves... + -- ----------------------------------------------------------------------- if (p_threshold is not null and abs(v_value) >= p_threshold) or (p_statnames is not empty and v_name member of p_statnames) - or (p_statname_like is not null and v_name like '%'||p_statname_like||'%') + or (p_statname_like is not null and v_name like '%'||p_statname_like||'%') + or (p_statname_regexp is not null and regexp_like(v_name, p_statname_regexp, 'i')) then - /* - || Fix for bug 1713403. If redo goes over 2Gb then it is reported as a negative - || number. Recommended workaround (prior to fix in 10g) is to use redo blocks written - || but this seems to be 0 in V$MYSTAT or V$SESSTAT. Output a bug message... - */ + -- Fix for bug 1713403. If redo goes over 2Gb then it is reported as a negative + -- number. Recommended workaround (prior to fix in 10g) is to use redo blocks written + -- but this seems to be 0 in V$MYSTAT or V$SESSTAT. Output a bug message... + -- ---------------------------------------------------------------------------------- if v_name = 'redo size' and v_value < 0 then sort('BUG','redo size > 2gb gives -ve value. Use redo blocks written',0); else @@ -335,16 +403,14 @@ create or replace package body mystats_pkg as end if; end if; - /* - || Next statname please... - */ + -- Next statname please... + -- ----------------------- v_name := ga_mystats(c_run1).next(v_name); end loop; - /* - || Now we can output the sorted snapshot... - */ + -- Now we can output the sorted snapshot... + -- ---------------------------------------- sh('2. Statistics Report'); v_indx := aa_mystats_sorted.first; @@ -360,10 +426,14 @@ create or replace package body mystats_pkg as end loop; - /* - || Info... - */ - sh('3. About', false); + -- Options... + -- ------- + sh('3. Options', false); + ms_options(p_threshold, p_statnames, p_statname_like, p_statname_regexp); + + -- Info... + -- ------- + sh('4. About', false); ms_info; nl; @@ -373,25 +443,50 @@ create or replace package body mystats_pkg as end ms_report; + ------------------------------------------------------------------------------ + procedure ms_set_snap_options( p_include_statistics in boolean, + p_include_latches in boolean, + p_include_time_model in boolean ) is + function ms_set_option( p_option in boolean ) return varchar2 is + begin + return case + when p_option + then 'Y' + else 'N' + end; + end ms_set_option; + begin + g_include_statistics := ms_set_option(p_include_statistics); + g_include_latches := ms_set_option(p_include_latches); + g_include_time_model := ms_set_option(p_include_time_model); + end ms_set_snap_options; + ------------------------------------------------------------------------------ procedure ms_reset is begin ga_mystats.delete; - g_start_time := null; - g_end_time := null; + g_start_time := null; + g_end_time := null; + g_include_statistics := null; + g_include_latches := null; + g_include_time_model := null; end ms_reset; ------------------------------------------------------------------------------ - procedure ms_start is + procedure ms_start( p_include_statistics in boolean default true, + p_include_latches in boolean default true, + p_include_time_model in boolean default true ) is begin ms_reset; + ms_set_snap_options(p_include_statistics, p_include_latches, p_include_time_model); ms_snap(c_run1, ga_mystats, g_start_time); end ms_start; ------------------------------------------------------------------------------ - procedure ms_stop_internal( p_threshold in integer default null, - p_statnames in mystats_pkg.statname_ntt default null, - p_statname_like in varchar2 default null) is + procedure ms_stop_internal( p_threshold in integer default null, + p_statnames in mystats_pkg.statname_ntt default null, + p_statname_like in varchar2 default null, + p_statname_regexp in varchar2 default null ) is begin if g_start_time.ela_time is not null then ms_snap(c_run2, ga_mystats, g_end_time); @@ -402,6 +497,8 @@ create or replace package body mystats_pkg as then ms_report(p_statnames => p_statnames); when p_statname_like is not null then ms_report(p_statname_like => p_statname_like); + when p_statname_regexp is not null + then ms_report(p_statname_regexp => p_statname_regexp); else ms_report; end case; ms_reset; @@ -418,6 +515,7 @@ create or replace package body mystats_pkg as ms_stop_internal(p_threshold => 0); end ms_stop; + ------------------------------------------------------------------------------ procedure ms_stop( p_threshold in integer ) is begin ms_stop_internal(p_threshold => p_threshold); @@ -430,9 +528,14 @@ create or replace package body mystats_pkg as end ms_stop; ------------------------------------------------------------------------------ - procedure ms_stop( p_statname_like in varchar2 ) is + procedure ms_stop( p_statname_like in varchar2, + p_use_regexp in boolean default false ) is begin - ms_stop_internal(p_statname_like => p_statname_like); + if p_use_regexp then + ms_stop_internal(p_statname_regexp => p_statname_like); + else + ms_stop_internal(p_statname_like => p_statname_like); + end if; end ms_stop; end mystats_pkg;