2026-03-12 20:23:15

This commit is contained in:
root
2026-03-12 21:23:47 +01:00
parent eab4b36eca
commit 93039b8489
3332 changed files with 699614 additions and 0 deletions

View File

@@ -0,0 +1,168 @@
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
================================================================================
SESSPACK v0.05 readme
================================================================================
About:
Sesspack can be best described as session level statspack for Oracle.
It collects less data than statspack, "only" the session level wait events
and v$sesstat info and stores it in its repository.
However Sesspack allows you to select the sampled sessions very flexibly,
you can sample all sessions in an instance or only few, based on various
conditions like SID, username, osuser, program, client machine, currently
effective module and action etc.
Sesspack doesn't add extra instrumentation overhead to the database, it
just queries v$session_event, v$sesstat and few other views when executed.
Note that with large number of sessions (1000+) you may want to sample
sessions selectively to save disk space and reduce snapshot CPU usage
For further information, see http://www.tanelpoder.com
Installation:
1) Using SQLPLUS, log on as user who can *grant* access on V$ views (SYS for example)
2) Create a user if want to have sesspack object in separate schema and grant connect to it
3) run install_sesspack.sql <username> <password> <connect_string>
e.g. @install_sesspack sesspack mypassword prod01
4) check sesspack_install.log
Usage example:
Note that the reports require fairly wide linesize (120+)
1) exec sesspack.snap_orauser('<USERNAME>')
2) do some work
3) exec sesspack.snap_orauser('<USERNAME>')
4) @list
5) @sr sid,program 1 2
This will take snapshot 1 and 2 of user <USERNAME>
Reference:
Taking snapshots:
sesspack.snap_me - snaps current session stats
sesspack.snap_sid - snaps given SIDs stats
sesspack.snap_orauser('<orauser>') - snaps all given ORACLE user's sessions's stats
sesspack.snap_osuser('<osuser>') - snaps all given OS user's sessions's stats
sesspack.snap_program('<program>') - snaps all given programs session stats
sesspack.snap_machine('<machine>') - snaps all given machines session stats
sesspack.snap_spid('spid') - snaps all given SPID session stats
sesspack.snap_cpid('cpid') - snaps all given client PID session stats
sesspack.snap_all - snaps all session stats
sesspack.snap_bg - snaps background processes sessions stats
sesspack.snap_fg - snaps foreground processes sessions stats
sesspack.snap_sidlist_internal('select sid from v$sesstat where <your custom conditions>')
- snaps all SIDs returned by custom SQL
Reporting performance data:
list.sql shows you snapshots with brief descriptions
sr.sql <grouping_col> <x> <y>
shows you the session event deltas between selected snapshots, grouped by a column
Columns can be:
1
SID
AUDSID
SERIAL#
USERNAME
PROGRAM
TERMINAL
MACHINE
OSUSER
PROCESS
To get a session-level resource usage breakdown, use:
@sr sid <start> <end>
To get resource usage summed and rolled up by client program nama, use:
@sr program <start> <end>
To get resource usage on sid level but you also want to see other data columns in output,
you can combine the columns:
@sr program,module <start> <end>
To sum up all measured resource consumption in the snap, use dummy column 1:
@sr 1 <start> <end>
Purging old data:
1) exec sesspack.purge_data; -- purges all data older than a week
or
exec sesspack.purge_data(<days_to_keep);
2) commit;
Customization:
For disk space reasons ony the sesspack.snap_me procedure gathers all v$sesstat statistics.
Other procedures gather session statistics based on
Roadmap/Notes/bugs/issues:
v0.05
========
fixes in gathering snaps & sr report
Schema - large tables compressed IOTs
performance report allows grouping by any field
purge capability
v0.04
========
customizable template-based session stats sampling
more snap procedures
v0.03b
========
Using V$SESSION_TIME_MODEL for getting if 10g+
v0.03
========
Multi-session snapshots should work ok now
I realized that standard-snapshots can't include all v$sesstat contents in snapshot by default - too much data generated
This is ok though, as we usually need only CPU time from there anyway.
V0.02
========
Lots.
Test first with only single Oracle user session - with multiple simultaneous logged on sessions there's some cartesian join somewhere

View File

@@ -0,0 +1,29 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
drop public synonym sawr$snapshots;
drop public synonym sawr$sessions;
drop public synonym sawr$session_events;
drop public synonym sawr$session_stats;
drop public synonym sawr$snapid_seq;
drop public synonym sawr$sidlist;
--drop public synonym sawr$sess_event_delta;
drop public synonym sawr$sess_event;
drop public synonym sesspack;
drop public synonym sawr$sess_stat;
drop public synonym sawr$session_stat_mode;

View File

@@ -0,0 +1,37 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
define spuser=PERFSTAT
define spconn=""
accept spuser default &spuser prompt "Specify the schema where SAWR and SESSPACK are installed [&spuser]: "
accept sppassword prompt "Specify the password for &spuser user: " hide
accept spconn prompt "Enter connect string PREFIXED WITH @ if connecting to remote database [&spconn]: "
-- @@unprepare_user
connect &spuser/&sppassword&spconn
prompt Uninstalling schema...
@@drop_sesspack_packages.sql
@@drop_sesspack_schema.sql
prompt Schema uninstalled.
prompt
prompt Uninstallation completed.
prompt Currently connected as &spuser&spconn....
prompt

View File

@@ -0,0 +1,17 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
drop package sesspack;

View File

@@ -0,0 +1,28 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
@@drop_grants_syns.sql
drop view sawr$sess_event;
drop view sawr$sess_stat;
drop sequence sawr$snapid_seq;
drop table sawr$snapshots;
drop table sawr$sessions;
drop table sawr$session_events;
drop table sawr$session_stats;
drop table sawr$session_stat_mode;
drop type sawr$SIDList;

View File

@@ -0,0 +1,52 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
-- grants for procs & types
grant execute on sesspack to sesspack_user_role;
grant execute on sawr$sidlist to sesspack_user_role;
-- grants for sequences
grant select on sawr$snapid_seq to sesspack_user_role;
-- grants for tables
grant select, insert on sawr$snapshots to sesspack_user_role;
grant select, insert on sawr$sessions to sesspack_user_role;
grant select, insert on sawr$session_events to sesspack_user_role;
grant select, insert on sawr$session_stats to sesspack_user_role;
grant select on sawr$session_stat_mode to sesspack_user_role;
-- grants for views
grant select on sawr$sess_event to sesspack_user_role;
--grant select on sawr$sess_event_delta to sesspack_user_role;
grant select on sawr$sess_stat to sesspack_user_role;
-- synonyms for procs & types
create public synonym sesspack for sesspack;
create public synonym sawr$sidlist for sawr$sidlist;
-- synonyms for sequences
create public synonym sawr$snapid_seq for sawr$snapid_seq;
-- synonyms for tables
create public synonym sawr$snapshots for sawr$snapshots;
create public synonym sawr$sessions for sawr$sessions;
create public synonym sawr$session_events for sawr$session_events;
create public synonym sawr$session_stats for sawr$session_stats;
create public synonym sawr$session_stat_mode for sawr$session_stat_mode;
-- synonyms for views
create public synonym sawr$sess_event for sawr$sess_event;
--create public synonym sawr$sess_event_delta for sawr$sess_event_delta;
create public synonym sawr$sess_stat for sawr$sess_stat;

View File

@@ -0,0 +1,70 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
-- add on script for pre-10g databases which need to record CPU usage
-- for long-running calls (as 9i doesnt update session cpu usage in
-- v$ views before end of call)
--
-- this script needs tidying up
--
-- rm /tmp/sawr_vmstat_pipe
-- rm /tmp/sawr_ps_pipe
-- mknod /tmp/sawr_vmstat_pipe p
-- mknod /tmp/sawr_ps_pipe p
-- create directory osstat as 'c:/tmp';
-- drop directory sawr$osstat;
create directory sawr$osstat as '/tmp';
grant read,write on directory sawr$osstat to &spuser;
drop table vmstat;
drop table ps;
CREATE TABLE sawr$ext_vmstat (
value number,
parameter varchar2(100)
)
ORGANIZATION EXTERNAL (
TYPE oracle_loader
DEFAULT DIRECTORY sawr$osstat
ACCESS PARAMETERS (
FIELDS TERMINATED BY ';'
MISSING FIELD VALUES ARE NULL
(value, parameter)
)
LOCATION ('sawr_vmstat_pipe')
)
;
CREATE TABLE sawr$ext_ps (
ospid varchar2(100),
value varchar2(100)
)
ORGANIZATION EXTERNAL (
TYPE oracle_loader
DEFAULT DIRECTORY sawr$osstat
ACCESS PARAMETERS (
FIELDS TERMINATED BY ';'
MISSING FIELD VALUES ARE NULL
(ospid, value)
)
LOCATION ('sawr_ps_pipe')
)
;

View File

@@ -0,0 +1,81 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
spool sesspack_install.log
prompt
prompt =================================================================================
prompt
prompt Welcome to the Semi-Automatic Workload Repository installer!
prompt
prompt This script will create some SAWR tables and SESSPACK package in specified schema
prompt
prompt Refer to README.txt for usage and further information
prompt
prompt (c) Tanel Poder http://www.tanelpoder.com
prompt
prompt =================================================================================
prompt
prompt
prompt You must be already connected to your target database as SYS or any other user
prompt who can grant privileges on some V$ objects for preparing SAWR user
prompt
-- this section is for initializing couple of "preprocessor" variables which create
-- different PLSQL based on target database version
column sesspack_v9 noprint new_value version_9_enable
column sesspack_v10 noprint new_value version_10_enable
with SQ as (
select substr(
substr(banner, instr(banner, 'Release ')+8),
1,
instr(substr(banner, instr(banner, 'Release ')+8),'.')-1
) db_version
from v$version
where rownum = 1
)
select
case when db_version = '9' then '--' else '/*' end sesspack_v9,
case when db_version != '9' then '--' else '/*' end sesspack_v10
from sq;
-- end of preprocessor initialization
-- Defines for non-interactive installation
define spuser="&1"
define sppassword="&2"
define spconn="@&3"
-- Uncomment for interactive installation
--define spuser="SESSPACK"
--define spconn=""
--accept spuser default &spuser prompt "Specify the schema for SAWR and SESSPACK installation [&spuser]: "
--accept sppassword prompt "Specify the password for &spuser user: " hide
--accept spconn prompt "Enter connect string PREFIXED WITH @ if installing into remote database [&spconn]: "
@@prepare_user.sql
connect &spuser/&sppassword&spconn
@@install_sesspack_schema.sql
@@install_sesspack_packages.sql
@@install_grants_syns.sql
prompt Installation completed.
prompt Currently connected as &spuser&spconn....
prompt
spool off

View File

@@ -0,0 +1,716 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
create or replace package sesspack
authid definer -- using definer authid so executing users don't have to have explicit grants on
-- schema and V$ objects
-- authid current_user -- safer option, allows use of privileges granted through roles
is
function in_list( p_sql in varchar2 ) return sawr$SIDlist;
function valid_stat_modes return sawr$ModeList;
procedure snap_sidlist_internal( p_sidlist in sawr$SIDlist, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
procedure snap_sidlist_internal( p_sql in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap current session
procedure snap_me ( p_session_stats in varchar2 default 'ALL', p_snapid in number default null );
-- snap session with given SID
procedure snap_sid ( p_sid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
procedure snap_sid ( p_sid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap all sessions by oracle user
procedure snap_orauser( p_username in varchar2 default user, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap all sessions by os user
procedure snap_osuser( p_username in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap all sessions by program name (v$session.program)
procedure snap_program( p_program in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap all sessions by terminal (v$session.terminal)
procedure snap_terminal( p_terminal in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap all sessions by machine (v$session.machine)
procedure snap_machine( p_machine in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap the session being served by SPID (v$process.spid)
procedure snap_spid( p_spid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
procedure snap_spid( p_spid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap all sessions by client PID (v$session.process)
procedure snap_cpid( p_cpid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
procedure snap_cpid( p_cpid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap all sessions
procedure snap_all ( p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap background sessions
procedure snap_bg ( p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- snap user sessions
procedure snap_fg ( p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null );
-- purge repository data
procedure purge_data ( p_days_threshold in number default 7, p_snapid in number default null );
end sesspack;
/
create or replace package body sesspack as
--==================================================================================================================
--==================================================================================================================
--
-- Global Variables
--
--==================================================================================================================
--==================================================================================================================
--------------------------------------------------------------------------------------------------------------------
-- g_snap_mode is inserted into sawr$snapshots table during first call to assign_snapid()
-- the global variable is changed in the beginning of each external procedure which can be
-- called directly. this means the directly-called procedure's g_snap_mode will be recorded
-- to sawr$snapshots table and its values will be ignored from there on
--------------------------------------------------------------------------------------------------------------------
g_snap_mode varchar2(100) := 'Undefined';
--==================================================================================================================
--==================================================================================================================
--
-- Internal Procs used by sesspack itself
--
--==================================================================================================================
--==================================================================================================================
--------------------------------------------------------------------------------------------------------------------
-- FUNCTION: assign_snapid
-- PURPOSE: generate new snapid if the the parent snap function is executed standalone.
-- if its executed from proper top-level function, a snapid to use should have been
-- passed down from there.
-- the reason for that is that we might need to run several different snap commands
-- for getting a snapshot (e.g. get all sessions where USERNAME = 'SYS' and all with
-- MODULE='HR')
--------------------------------------------------------------------------------------------------------------------
function assign_snapid (p_snapid in number, l_snap_comment varchar2 default '' ) return number
as
l_snapid number;
begin
if (p_snapid is null) then
-- insert a line for each distinct snapshot. primary method of entry for querying
-- snapshot data
--
-- TODO: update the snapshot row with snapshot end sysdate too
-- or put the number of milliseconds spent taking the snapshot
select sawr$snapid_seq.nextval into l_snapid from dual;
insert into sawr$snapshots values ( l_snapid, sysdate, user, g_snap_mode, l_snap_comment );
return l_snapid;
else
return p_snapid;
end if;
end assign_snapid;
--------------------------------------------------------------------------------------------------------------------
-- FUNCTION: in_list
-- PURPOSE: generic function for returning a collection of numbers from the dynamic query
-- passed in p_sql parameter.
-- for example, it's used for getting list of SIDs based on dynamic query
-- against v$session
-- PARAMETERS:
-- p_sql : SQL text string which should return a list of session IDs (in number format)
-- : no restriction where and how the list of SIDs is retrieved, such SIDs should
-- : just exist in V$SESSION, otherwise nothing is sampled
-- : for example, value can be 'select sid from v$session where username = '''APPS''''
-- : or 'select sid from v$session where status = '''ACTIVE''' and last_call_et > 5'
--------------------------------------------------------------------------------------------------------------------
function in_list( p_sql in varchar2 ) return sawr$SIDlist
as
type rc is ref cursor;
l_cursor rc;
l_tmp number;
l_data sawr$sidlist := sawr$SIDlist();
begin
open l_cursor for p_sql;
loop
fetch l_cursor into l_tmp;
exit when l_cursor%notfound;
l_data.extend;
l_data(l_data.count) := l_tmp;
end loop;
close l_cursor;
return l_data;
end in_list; -- ( p_sql in varchar2 )
--------------------------------------------------------------------------------------------------------------------
-- FUNCTION: valid_stat_modes
-- PURPOSE: Function for returning a collection of valid snap modes as determined by
-- the sawr$session_stat_mode table.
--------------------------------------------------------------------------------------------------------------------
function valid_stat_modes return sawr$ModeList is
l_modes sawr$ModeList;
begin
select distinct upper(mode_id) bulk collect into l_modes
from sawr$session_stat_mode;
return l_modes;
end valid_stat_modes;
--------------------------------------------------------------------------------------------------------------------
-- FUNCTION: snap_sidlist_internal (overloaded, p_sidlist as sawr$SIDlist type)
--
-- PURPOSE: this is the low-level procedure doing the actual sampling from V$ views
-- and inserting the result to SAWR$ tables
--
-- PARAMETERS:
-- p_sidlist : sawr$SIDlist collection, this is array of SIDs to be sampled from V$SESSION
-- p_snapid : snapshot ID to be inserted into SAWR$ tables. normally this comes from
-- parent functions, but is autogenerated when the low-level function is
-- executed manually and by leaving p_snapid as NULL.
--------------------------------------------------------------------------------------------------------------------
procedure snap_sidlist_internal( p_sidlist in sawr$SIDlist, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null)
as
l_snapid number;
l_codeloc varchar2(200) := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): BEGIN';
begin
-- this variable is here for easier catching of exception sources in pre-10g dbs
l_codeloc:= 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): CALL ASSIGN_SNAPID';
-- allocate a new snapid if a global one hasn't been passed down from caller
-- new snapid allocation inserts a line to SAWR$SNAPSHOTS table
l_snapid := assign_snapid(p_snapid);
------------------------------------------------------------------------------------------------------------
-- insert sessions matching parameter conditions into SAWR$SESSIONS table
------------------------------------------------------------------------------------------------------------
l_codeloc := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): INSERT INTO SAWR$SESSIONS';
insert into
sawr$sessions (
snapid
, snaptime
, program
, username
, machine
, osuser
, terminal
, module
, action
, audsid
, sid
, serial#
, process
, logon_time
)
select
l_snapid
, sysdate as snaptime
, nvl(s.program , '-')
, nvl(s.username , '-')
, nvl(s.machine , '-')
, nvl(s.osuser , '-')
, nvl(s.terminal , '-')
, nvl(module , '-')
, nvl(action , '-')
, s.audsid
, s.sid
, s.serial#
, s.process
, s.logon_time
from
v$session s
where
sid in (
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
);
------------------------------------------------------------------------------------------------------------
-- insert matching session wait events into SAWR$SESSION_EVENTS table
------------------------------------------------------------------------------------------------------------
l_codeloc := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): INSERT INTO SAWR$SESSION_EVENTS';
insert into
sawr$session_events (
snapid
, snaptime
, audsid
, sid
, serial#
, event#
, total_waits
, total_timeouts
, average_wait
, max_wait
, time_waited_micro
)
select --+ ORDERED tanel9
l_snapid,
sysdate as snaptime,
s.audsid,
e.sid,
s.serial#,
en.event#,
e.total_waits,
e.total_timeouts,
e.average_wait,
e.max_wait,
-- e.time_waited_micro + ( decode(e.event||w.state, w.event||'WAITING', w.seconds_in_wait, 0) * 1000000 ) time_waited_micro
e.time_waited_micro + NVL( CASE e.event||w.state
WHEN w.event||'WAITING' THEN
CASE
WHEN w.event IN ( select event from v$system_event where total_timeouts != 0 ) THEN 0
ELSE w.seconds_in_wait
END
ELSE 0
END
* 1000000, 0 ) time_waited_micro
from
v$session s,
v$session_event e,
v$session_wait w,
v$event_name en
where
e.sid = s.sid
and s.sid = w.sid
and w.sid = e.sid
and e.event = en.name
and s.sid in (
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
);
------------------------------------------------------------------------------------------------------------
-- insert used CPU time to session events table as well
-- in 9i V$SESSTAT (CPU used by this session) is used
-- from 10g V$SESS_TIME_MODEL is used as this is more accurate and is updated every 5 seconds
-- even during database CALL
--
-- note that the installer script automatically comments out the irrelevant part depending on db version
------------------------------------------------------------------------------------------------------------
-- the line below is substituted by "/*" by sqlplus during installation onto 9i database
&version_9_enable
-- 9i version for getting session CPU usage
insert into
sawr$session_events (
snapid
, snaptime
, audsid
, sid
, serial#
, event#
, total_waits
, time_waited_micro
)
select --+ ORDERED USE_NL(s st)
l_snapid,
sysdate as snaptime,
s.audsid,
s.sid,
s.serial#,
-1, -- naming CPU usage as event# -1
1, -- setting total waits for CPU to 1 for now (this can be got from perhaps number of calls or sum(events) later on)
st.value * 10000 -- x10000 makes microseconds out of centiseconds
from
v$session s,
v$sesstat st
where
st.statistic# = (select statistic# from v$statname where name = 'CPU used by this session')
and s.sid = st.sid
and s.sid in (
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
);
-- end: version_9_enable
-- */
-- the line below is substituted by "/*" by sqlplus during installation onto 10g and above database
&version_10_enable
-- 10g+ version for getting session CPU usage
insert into
sawr$session_events (
snapid
, snaptime
, audsid
, sid
, serial#
, event#
, total_waits
, time_waited_micro
)
select --+ ORDERED USE_NL(s st)
l_snapid,
sysdate as snaptime,
s.audsid,
s.sid,
s.serial#,
-1, -- naming CPU usage as event# -1
1, -- setting total waits for CPU to 1 for now (this can be got from perhaps number of calls or sum(events) later on)
st.value -- v$sess_time_model reports times in microseconds
from
v$session s,
v$sess_time_model st
where
st.stat_name = 'DB CPU'
and s.sid = st.sid
and s.sid in (
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
);
-- end: version_10_enable
-- */
------------------------------------------------------------------------------------------------------------
-- insert matching session statistics into SAWR$SESSION_STATS table
------------------------------------------------------------------------------------------------------------
l_codeloc := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): INSERT INTO SAWR$SESSION_STATS';
insert into
sawr$session_stats (
snapid
, snaptime
, audsid
, sid
, serial#
, statistic#
, value
)
select --+ ORDERED USE_NL(s ss) INDEX(s) tanel2
l_snapid,
sysdate as snaptime,
s.audsid,
s.sid,
s.serial#,
ss.statistic#,
ss.value
from
v$session s,
v$sesstat ss
where
s.sid = ss.sid
and s.sid in (
select * from ( table(cast(p_sidlist as sawr$SIDlist)) )
)
and ss.statistic# in (
select --+ ORDERED NO_UNNEST
statistic#
from
sawr$session_stat_mode cfg,
v$statname sn
where
sn.name = cfg.statistic_name
and cfg.mode_id = p_session_stats
)
and ss.value != 0;
l_codeloc := 'SNAP_SIDLIST_INTERNAL(P_SIDLIST): END';
exception
when NO_DATA_FOUND then null; -- its ok to find no matches for snapshot query
when others then raise_application_error(-20001, 'Error '||SQLCODE||': '||SQLERRM||' : FAILED AT '|| l_codeloc) ;
end snap_sidlist_internal; -- ( p_sidlist in sawr$SIDlist )
--------------------------------------------------------------------------------------------------------------------
-- FUNCTION: snap_sidlist_internal (overloaded, p_sidlist as VARCHAR2 type)
--
-- PURPOSE: this is a procedure accepting any SQL which returns array of
-- SIDs (NUMBER format) which are then used for calling the
-- snap_sidlist_internal sister function to extract session info
-- from V$SESSION
--
-- PARAMETERS:
-- p_sidlist : sawr$SIDlist collection, this is array of SIDs to be sampled from V$SESSION
-- p_snapid : snapshot ID to be inserted into SAWR$ tables. normally this comes from
-- parent functions, but is autogenerated when the low-level function is
-- executed manually and by leaving p_snapid as NULL.
--------------------------------------------------------------------------------------------------------------------
procedure snap_sidlist_internal(p_sql in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null)
is
l_snapid number;
begin
-- allocate a new snapid if a global one hasn't been passed down from caller
l_snapid := assign_snapid(p_snapid);
-- call the overloaded snap_sidlist_internal sister-function
-- which accepts sawr$SIDlist collection as a parameter
snap_sidlist_internal( in_list(p_sql), p_session_stats, l_snapid );
end snap_sidlist_internal; -- ( p_sql in varchar2 )
--==================================================================================================================
--==================================================================================================================
--
-- External Procs to be executed by users
--
--==================================================================================================================
--==================================================================================================================
--------------------------------------------------------------------------------------------------------------------
-- procedure for snapping current session
-- useful for ad-hoc instrumentation and performance diagnosis for SQL tuning
--------------------------------------------------------------------------------------------------------------------
procedure snap_me(p_session_stats in varchar2 default 'ALL', p_snapid in number default null) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_ME: '||user;
snap_sidlist_internal( 'select sid from v$mystat where rownum = 1', p_session_stats );
commit;
end snap_me;
--------------------------------------------------------------------------------------------------------------------
-- snap session with given SID
--------------------------------------------------------------------------------------------------------------------
procedure snap_sid ( p_sid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_SID: '||to_char(p_sid);
snap_sidlist_internal( 'select sid from v$session where sid in ('||to_char(p_sid)||')' , p_session_stats );
commit;
end snap_sid;
--------------------------------------------------------------------------------------------------------------------
-- snap session with given SID
--------------------------------------------------------------------------------------------------------------------
procedure snap_sid ( p_sid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_SID: '||p_sid;
snap_sidlist_internal( 'select sid from v$session where sid in ('||p_sid||')' , p_session_stats );
commit;
end snap_sid;
--------------------------------------------------------------------------------------------------------------------
-- procedure for snapping all sessions
--------------------------------------------------------------------------------------------------------------------
procedure snap_all(p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_ALL:';
snap_sidlist_internal( 'select sid from v$session' , p_session_stats );
commit;
end snap_all;
--------------------------------------------------------------------------------------------------------------------
-- procedure for snapping all BACKGROUND sessions
--------------------------------------------------------------------------------------------------------------------
procedure snap_bg(p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_BG:';
snap_sidlist_internal( 'select sid from v$session where type = ''BACKGROUND''' , p_session_stats );
commit;
end snap_bg;
--------------------------------------------------------------------------------------------------------------------
-- procedure for snapping all USER sessions
--------------------------------------------------------------------------------------------------------------------
procedure snap_fg(p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_FG:';
snap_sidlist_internal( 'select sid from v$session where type = ''USER''' , p_session_stats );
commit;
end snap_fg;
--------------------------------------------------------------------------------------------------------------------
-- procedure for snapping all sessions estabilished by specified Oracle user
-- default value null will snap all sessions by current user
--------------------------------------------------------------------------------------------------------------------
procedure snap_orauser(p_username in varchar2 default user, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_ORAUSER: '||p_username;
snap_sidlist_internal('select sid from v$session where username like '''|| p_username ||'''' , p_session_stats );
commit;
end snap_orauser;
--------------------------------------------------------------------------------------------------------------------
-- procedure for snapping all sessions estabilished by specified OS user
--------------------------------------------------------------------------------------------------------------------
procedure snap_osuser(p_username in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_OSUSER: '||p_username;
snap_sidlist_internal('select sid from v$session where osuser like '''|| p_username ||'''' , p_session_stats );
commit;
end snap_osuser;
--------------------------------------------------------------------------------------------------------------------
-- snap all sessions by program name (v$session.program)
--------------------------------------------------------------------------------------------------------------------
procedure snap_program( p_program in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_PROGRAM: '||p_program;
snap_sidlist_internal('select sid from v$session where program like '''|| p_program ||'''' , p_session_stats );
commit;
end snap_program;
--------------------------------------------------------------------------------------------------------------------
-- snap all sessions by terminal (v$session.terminal)
--------------------------------------------------------------------------------------------------------------------
procedure snap_terminal( p_terminal in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_TERMINAL: '||p_terminal;
snap_sidlist_internal('select sid from v$session where terminal like '''|| p_terminal ||'''' , p_session_stats );
commit;
end snap_terminal;
--------------------------------------------------------------------------------------------------------------------
-- snap all sessions by machine (v$session.machine)
--------------------------------------------------------------------------------------------------------------------
procedure snap_machine( p_machine in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_MACHINE: '||p_machine;
snap_sidlist_internal('select sid from v$session where machine like '''|| p_machine ||'''' , p_session_stats);
commit;
end snap_machine;
--------------------------------------------------------------------------------------------------------------------
-- snap the session being served by SPID (v$process.spid)
--------------------------------------------------------------------------------------------------------------------
procedure snap_spid( p_spid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_CPID: '||p_spid;
snap_sidlist_internal('select sid from v$session where paddr in ( select addr from v$process where spid in ('''|| p_spid ||'''))' , p_session_stats );
commit;
end snap_spid;
--------------------------------------------------------------------------------------------------------------------
-- snap the session being served by SPID (v$process.spid)
--------------------------------------------------------------------------------------------------------------------
procedure snap_spid( p_spid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_CPID: '||p_spid;
snap_sidlist_internal('select sid from v$session where paddr in ( select addr from v$process where spid in ('''|| to_char(p_spid) ||'''))' , p_session_stats );
commit;
end snap_spid;
--------------------------------------------------------------------------------------------------------------------
-- snap all sessions by client PID (v$session.process)
--------------------------------------------------------------------------------------------------------------------
procedure snap_cpid( p_cpid in varchar2, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_CPID: '||p_cpid;
snap_sidlist_internal('select sid from v$session where process in ('''|| p_cpid ||''')' , p_session_stats );
commit;
end snap_cpid;
--------------------------------------------------------------------------------------------------------------------
-- snap all sessions by client PID (v$session.process)
--------------------------------------------------------------------------------------------------------------------
procedure snap_cpid( p_cpid in number, p_session_stats in varchar2 default 'TYPICAL', p_snapid in number default null ) is
pragma autonomous_transaction;
begin
g_snap_mode:='SNAP_CPID: '||to_char(p_cpid);
snap_sidlist_internal('select sid from v$session where process in ('''|| to_char(p_cpid) ||''')' , p_session_stats );
commit;
end snap_cpid;
--------------------------------------------------------------------------------------------------------------------
-- purge repository data over a certain age threshold
--------------------------------------------------------------------------------------------------------------------
procedure purge_data ( p_days_threshold in number default 7, p_snapid in number default null ) is
type sawr$TableList is table of varchar2(30);
l_tables sawr$TableList := sawr$TableList('SAWR$SNAPSHOTS',
'SAWR$SESSIONS',
'SAWR$SESSION_EVENTS',
'SAWR$SESSION_STATS');
l_snaptime date := trunc(sysdate)-nvl(p_days_threshold,7);
l_codeloc varchar2(200) := 'PURGE_DATA: BEGIN';
l_ddl varchar2(200);
pragma autonomous_transaction;
begin
l_codeloc := 'PURGE_DATA: DELETE DATA';
for i in 1 .. l_tables.count loop
l_codeloc := 'PURGE_DATA: DELETE ' || l_tables(i);
execute immediate ' delete from ' || l_tables(i) ||
' where snaptime < :snaptime ' ||
' and (snapid = :snapid or :snapid is null)'
using l_snaptime, p_snapid, p_snapid;
end loop;
l_codeloc := 'PURGE_DATA: REBUILD_TABLES';
for i in 1 .. l_tables.count loop
l_ddl := case l_tables(i)
when 'SAWR$SNAPSHOTS'
then 'alter index SAWR$SNAPSHOTS_PK coalesce'
else 'alter table ' || l_tables(i) || ' move online'
end;
l_codeloc := 'PURGE_DATA: REBUILD ' || l_tables(i);
execute immediate l_ddl;
end loop;
l_codeloc := 'PURGE_DATA: END';
exception
when others then
raise_application_error(-20001, 'Error '||SQLCODE||': '||SQLERRM||' : FAILED AT '|| l_codeloc) ;
end purge_data;
end sesspack;
/
show errors

View File

@@ -0,0 +1,249 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
create or replace type sawr$SIDList is table of number;
/
create or replace type sawr$ModeList is table of varchar2(30);
/
create sequence sawr$snapid_seq cache 10 order;
create table sawr$snapshots (
snapid number,
snaptime date not null,
takenby varchar2(100) default user not null,
snap_mode varchar2(100) not null,
snap_comment varchar2(4000)
);
create index sawr$snapshots_pk on sawr$snapshots ( snapid, snaptime );
alter table sawr$snapshots add constraint sawr$snapshots_pk primary key (snapid) using index sawr$snapshots_pk;
create table sawr$sessions (
snapid number not null
, snaptime date not null
, program varchar2(48) not null
, module varchar2(48) not null
, action varchar2(32) not null
, username varchar2(30) not null
, machine varchar2(64) not null
, osuser varchar2(30) not null
, terminal varchar2(30) not null
, audsid number not null
, sid number not null
, serial# number not null
, process varchar2(12)
, logon_time date
, sql_hash_value number
, prev_hash_value number
, client_info varchar2(64)
, row_wait_obj# number
, row_wait_file# number
, row_wait_block# number
, row_wait_row# number
, last_call_et number
, client_identifier varchar2(64)
, constraint sawr$sessions_pk primary key (
snapid
, snaptime
, program
, module
, action
, username
, machine
, osuser
, terminal
, sid
, serial#
, audsid
) -- so many PK columns and such column order is used for achieving good compressed IOT storage
)
organization index compress;
create table sawr$session_events (
snapid number
, snaptime date
, audsid number
, sid number
, serial# number
, event# number
, total_timeouts number
, total_waits number
, average_wait number
, max_wait number
, time_waited_micro number
, event_id number
, constraint sawr$session_events_pk primary key (
snapid,
snaptime,
audsid,
sid,
serial#,
event#
)
)
organization index compress;
create table sawr$session_stats (
snapid number
, snaptime date
, audsid number
, sid number
, serial# number
, statistic# number
, value number
, constraint sawr$session_stats_pk primary key (
snapid,
snaptime,
audsid,
sid,
serial#,
statistic#
)
)
organization index compress;
---------------------------------------------------------------------------------
-- Table for V$SESSTAT sampling templates
---------------------------------------------------------------------------------
create table sawr$session_stat_mode (
mode_id varchar(30) not null,
statistic_name varchar2(250) not null,
constraint sawr$session_stat_mode_pk primary key (mode_id, statistic_name)
)
organization index;
insert into sawr$session_stat_mode
select
'MINIMAL',
name
from
v$statname
where
name in (
'user calls',
'user commits'
)
/
insert into sawr$session_stat_mode
select
'TYPICAL',
name
from
v$statname
where
name in (
'user calls',
'user commits',
'parse count (total)',
'parse count (hard)',
'execute count',
'consistent gets',
'db block gets'
)
/
insert into sawr$session_stat_mode
select
'DETAILED',
name
from
v$statname
where
name in (
'user calls',
'user commits',
'parse count (total)',
'parse count (hard)',
'execute count',
'consistent gets',
'consistent gets - examination',
'db block gets',
'parse time cpu',
'parse time elapsed',
'sorts (memory)',
'sorts (disk)',
'sorts (rows)',
'transaction rollbacks',
'user rollbacks'
)
/
insert into sawr$session_stat_mode
select
'ALL',
name
from
v$statname
/
commit;
-- SAWR$SESS_EVENT
-- View consolidating sessions events and values over taken snapshots
create or replace view sawr$sess_event as
select
snap.snapid, snap.snaptime,
s.sid, s.audsid, s.serial#,
s.username, s.program, s.terminal, s.machine,
s.osuser, s.process, s.module, s.action,
en.event#, en.name, e.time_waited_micro,
e.total_waits, e.average_wait, s.logon_time
from
sawr$snapshots snap,
sawr$sessions s,
sawr$session_events e,
( select event#, name from v$event_name
union all
select -1, 'CPU Usage' from dual
) en
where
snap.snapid = s.snapid
and snap.snapid = e.snapid
and s.audsid = e.audsid
and s.sid = e.sid
and s.serial# = e.serial#
and en.event# = e.event#
/
-- SAWR$SESS_STAT
-- View consolidating sessions stats and values over taken snapshots
create or replace view sawr$sess_stat as
select
snap.snapid, snap.snaptime,
s.sid, s.audsid, s.serial#,
s.username, s.program, s.terminal, s.machine,
s.osuser, s.process, s.module, s.action,
sn.statistic#, sn.name, ss.value, s.logon_time
from
sawr$snapshots snap,
sawr$sessions s,
sawr$session_stats ss,
v$statname sn
where
snap.snapid = s.snapid
and snap.snapid = ss.snapid
and s.audsid = ss.audsid
and s.sid = ss.sid
and s.serial# = ss.serial#
and sn.statistic# = ss.statistic#
/

View File

@@ -0,0 +1,40 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
set lines 156
column sawr_list_takenby heading "Taken By" format a20
column sawr_list_snapid heading "Snap ID" format 9999999
column sawr_list_snaptime heading "Snapshot Time" format a20
column sawr_session_count heading "Snapped|Sessions" format 9999999
column sawr_snap_mode heading "Snapshot|Mode" format a40
select
snap.snapid sawr_list_snapid,
to_char(snap.snaptime, 'YYYY-MM-DD HH24:MI:SS') sawr_list_snaptime,
snap.takenby sawr_list_takenby,
snap.snap_mode sawr_snap_mode,
count(*) sawr_session_count
from
sawr$snapshots snap,
sawr$sessions sess
where
snap.snapid = sess.snapid
group by
snap.snapid,
to_char(snap.snaptime, 'YYYY-MM-DD HH24:MI:SS'),
snap.snap_mode,
snap.takenby
order by
to_char(snap.snaptime, 'YYYY-MM-DD HH24:MI:SS')
/

View File

@@ -0,0 +1,167 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
set feedback off null "[NULL]"
-- define _tptmode = normal
define grouping=&1
define start_snap=&2
define end_snap=&3
col wait_ms for 9999999999
col avg_wait_ms for 99999999.9
col ms_per_sec for 999999.9
col program for a30 truncate
col username for a15 truncate
col osuser for a20 truncate
col name for a30 truncate
col machine for a20 truncate
col grouping_break noprint new_value grouping_break
--set termout off
select replace('&grouping', ',', ' on ') grouping_break from dual;
--set termout on
break on &grouping_break skip 1
select
to_char(a.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_begin,
to_char(b.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_end,
(b.snaptime - a.snaptime)*86400 dur_sec,
(b.snaptime - a.snaptime)*86400/60 dur_min
from
(select snaptime from sawr$snapshots where snapid = &2) a,
(select snaptime from sawr$snapshots where snapid = &3) b
/
select
&grouping,
substr(name,1,45) name,
decode(lower('&_tptmode'),'html','','|')||
rpad(
nvl(
lpad('#',
ceil( (nvl(round(sum(us_per_sec/1000000),2),0))*10 ),
'#'),
' '),
10,' ')
||decode(lower('&_tptmode'),'html','','|') "%Total",
sum(us_per_sec)/1000 ms_per_sec,
(sum(wait_us)/decode(sum(waits),0,1,sum(waits))/1000) avg_wait_ms,
sum(waits) waits,
sum(wait_us)/1000 wait_ms
-- ,avg(intrvl)/1000 sec_in_snap
from (
select
e2.sid,
e2.audsid,
nvl(e1.snapid, &start_snap) begin_snapid,
e2.snapid end_snapid,
e2.username,
e2.program,
e2.terminal,
e2.machine,
e2.osuser,
e2.module,
e2.action,
e2.name,
round(e2.time_waited_micro - nvl(e1.time_waited_micro,0)) wait_us,
round(
( e2.time_waited_micro - nvl(e1.time_waited_micro,0) ) / (
decode((e2.snaptime - nvl(e1.snaptime,(select snaptime from sawr$snapshots where snapid = &start_snap)))*86400, 0, 1,
(e2.snaptime - nvl(e1.snaptime,(select snaptime from sawr$snapshots where snapid = &start_snap)))*86400)
)
) us_per_sec,
(e2.snaptime - nvl(e1.snaptime,(select snaptime from sawr$snapshots where snapid = &start_snap)))*86400*1000 intrvl,
e2.total_waits - nvl(e1.total_waits,0) waits
-- e1.average_wait avg1,
-- e2.average_wait avg2,
-- e2.average_wait - nvl(e1.average_wait,0) avgdelta
from
( select * from sawr$sess_event where snapid = &start_snap ) e1,
( select * from sawr$sess_event where snapid = &end_snap ) e2
where
e1.audsid (+) = e2.audsid
and e1.sid (+) = e2.sid
and e1.serial# (+) = e2.serial#
and e1.logon_time (+) = e2.logon_time
and e1.event# (+) = e2.event#
) sq
where
( waits != 0 or wait_us != 0 )
group by
&grouping, name
order by
&grouping, ms_per_sec desc
/
col delta head Delta for 9999999999
col delta_sec head D/sec for 9999999.9
select
&grouping,
substr(name,1,45) name,
decode(lower('&_tptmode'),'html','','|')||
rpad(
nvl(
lpad('#',
ceil( nvl(log(10,abs(decode(sum(delta),0,1,sum(delta)))),0) ),
'#'),
' '),
10,' ')
||decode(lower('&_tptmode'),'html','','|') "log10(D)",
sum(delta) delta,
sum(delta)/(avg(intrvl)/1000) delta_sec
-- ,avg(intrvl)/1000 sec_in_snap
from (
select
s2.sid,
s2.audsid,
nvl(s1.snapid, &start_snap) begin_snapid,
s2.snapid end_snapid,
s2.username,
s2.program,
s2.terminal,
s2.machine,
s2.osuser,
s2.process,
s2.name,
s2.module,
s2.action,
s2.value - nvl(s1.value,0) delta,
(s2.snaptime - nvl(s1.snaptime,(select snaptime from sawr$snapshots where snapid = &start_snap)))*86400*1000 intrvl
from
( select * from sawr$sess_stat where snapid = &start_snap ) s1,
( select * from sawr$sess_stat where snapid = &end_snap ) s2
where
s1.audsid (+) = s2.audsid
and s1.sid (+) = s2.sid
and s1.serial# (+) = s2.serial#
and s1.logon_time (+) = s2.logon_time
and s1.statistic# (+) = s2.statistic#
) sq
where
delta != 0
group by
&grouping, name
order by
&grouping, abs(delta) desc
/
break on _nonexistent
set feedback on null ""

View File

@@ -0,0 +1,61 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
-- whenever sqlerror exit 1 rollback
set verify off
-- create sesspack roles
create role sesspack_user_role;
create role sesspack_admin_role;
-- grant the roles to sesspack schema holder
grant sesspack_user_role to &spuser with admin option;
grant sesspack_user_role to sesspack_admin_role;
grant sesspack_admin_role to &spuser with admin option;
-- two additional privs to sesspack owner to avoid ORA-01720
grant select on sys.v_$event_name to &spuser with grant option;
grant select on sys.v_$statname to &spuser with grant option;
-- grant privs required for taking and scheduling snapshots
grant select on sys.v_$mystat to sesspack_user_role;
grant select on sys.v_$session to sesspack_user_role;
grant select on sys.v_$session_wait to sesspack_user_role;
grant select on sys.v_$session_event to sesspack_user_role;
grant select on sys.v_$system_event to sesspack_user_role;
grant select on sys.v_$sess_time_model to sesspack_user_role;
grant select on sys.v_$sesstat to sesspack_user_role;
grant select on sys.v_$event_name to sesspack_user_role;
grant select on sys.v_$statname to sesspack_user_role;
grant execute on sys.dbms_job to &spuser;
-- for 10g
grant create job to &spuser;
grant create table to &spuser;
grant create view to &spuser;
grant create type to &spuser;
grant create procedure to &spuser;
grant create public synonym to &spuser;
grant select on sys.v_$mystat to &spuser;
grant select on sys.v_$session to &spuser;
grant select on sys.v_$session_wait to &spuser;
grant select on sys.v_$session_event to &spuser;
grant select on sys.v_$system_event to &spuser;
grant select on sys.v_$sess_time_model to &spuser;
grant select on sys.v_$sesstat to &spuser;
grant select on sys.v_$event_name to &spuser;
grant select on sys.v_$statname to &spuser;
set verify on
whenever sqlerror continue

View File

@@ -0,0 +1,59 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
define spuser=perfstat
define sphost=ora92
define sppass=oracle
define sysuser=sys
define syspass=oracle
connect &spuser/&sppass@&sphost
column sesspack_v9 noprint new_value version_9_enable
column sesspack_v10 noprint new_value version_10_enable
with SQ as (
select substr(
substr(banner, instr(banner, 'Release ')+8),
1,
instr(substr(banner, instr(banner, 'Release ')+8),'.')-1
) db_version
from v$version
where rownum = 1
)
select
case when db_version = '9' then '--' else '/*' end sesspack_v9,
case when db_version = '10' then '--' else '/*' end sesspack_v10
from sq;
prompt Uninstalling schema...
@@drop_sesspack_packages.sql
@@drop_sesspack_schema.sql
--connect &sysuser/&syspass@&sphost
-- @@prepare_user.sql
-- connect &spuser/oracle
prompt Installing schema...
@@install_sesspack_schema.sql
@@install_sesspack_packages.sql
@@install_grants_syns.sql
-- connect / as sysdba

View File

@@ -0,0 +1,15 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
@@drop_sesspack.sql
@@install_sesspack.sql

View File

@@ -0,0 +1,10 @@
#!/bin/sh
# Note that this is currently only for Solaris
while true
do
echo `date +%Y%m%d%H%M%S`";"BEGIN_PS_SAMPLE > /tmp/sawr_ps_pipe
ps -u oracle -o pid,time | awk '{ if ( NR > 1 ) print $1";"$2 }' > /tmp/sawr_ps_pipe
done

View File

@@ -0,0 +1,38 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
define spuser=&1
define spkeep=&2
prompt
set heading off feedback off
select 'sesspack_purge: removing records older than '|| to_char( sysdate - &spkeep, 'YYYYMMDD HH24:MI:SS') from dual;
set heading on feedback on
prompt
prompt delete from &spuser..SAWR$SNAPSHOTS where snaptime < sysdate - &spkeep;
delete from &spuser..SAWR$SNAPSHOTS where snaptime < sysdate - &spkeep;
commit;
prompt delete from &spuser..SAWR$SESSIONS where snaptime < sysdate - &spkeep;
delete from &spuser..SAWR$SESSIONS where snaptime < sysdate - &spkeep;
commit;
prompt delete from &spuser..SAWR$SESSION_EVENTS where snaptime < sysdate - &spkeep;
delete from &spuser..SAWR$SESSION_EVENTS where snaptime < sysdate - &spkeep;
commit;
prompt delete from &spuser..SAWR$SESSION_STATS where snaptime < sysdate - &spkeep;
delete from &spuser..SAWR$SESSION_STATS where snaptime < sysdate - &spkeep;
commit;
-- compact the indexes & IOTs for saving space
alter index SAWR$SNAPSHOTS_PK coalesce;
alter table SAWR$SESSIONS move online;
alter table SAWR$SESSION_STATS move online;
alter table SAWR$SESSION_EVENTS move online;
undefine spuser
undefine spkeep

View File

@@ -0,0 +1,18 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
define spuser=&1
prompt Truncating &spuser SAWR$ tables...
set echo on
truncate table &spuser..SAWR$SNAPSHOTS;
truncate table &spuser..SAWR$SESSIONS;
truncate table &spuser..SAWR$SESSION_EVENTS;
truncate table &spuser..SAWR$SESSION_STATS;
set echo off
undefine spuser

View File

@@ -0,0 +1,10 @@
#!/bin/sh
# Note that this is currently only for Solaris
while true
do
echo `date +%Y%m%d%H%M%S`";"BEGIN_SAMPLE > /tmp/sawr_vmstat_pipe
vmstat -s | awk '{ print $1";"$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9 }' > /tmp/sawr_vmstat_pipe
done

View File

@@ -0,0 +1,168 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
set feedback off lines 200 trimspool on
define _tptmode = normal
define grouping = &1
define start_snap = &2
define end_snap = &3
col wait_ms for 9999999999
col avg_wait_ms for 99999999.9
col ms_per_sec for 999999.9 noprint
col pct_in_wait head "% of|Time" for 99999.9
col module for a30 truncate
col action for a30 truncate
col program for a30 truncate
col username for a15 truncate
col osuser for a20 truncate
col name for a30 truncate
col machine for a20 truncate
col histgm for a10 truncate
col grouping_break noprint new_value grouping_break
col mandatory_name_col noprint new_value name_col
--set termout off
select replace('&grouping', ',', ' on ') as grouping_break
, case
when replace(lower('&grouping'), ',', ' ') like '% name %'
or replace(lower('&grouping'), ',', ' ') like '% name'
or replace(lower('&grouping'), ',', ' ') like 'name %'
or trim(lower('&grouping')) = 'name'
then '--,name'
else ',name'
end as mandatory_name_col
from dual;
--set termout on
break on &grouping_break skip 1
select
to_char(a.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_begin,
to_char(b.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_end,
(b.snaptime - a.snaptime)*86400 dur_sec,
(b.snaptime - a.snaptime)*86400/60 dur_min
from
(select snaptime from sawr$snapshots where snapid = &2) a,
(select snaptime from sawr$snapshots where snapid = &3) b
/
rem Events delta report
rem ==================================================================================
with deltas as (
select e2.sid
, nvl(e1.snapid, &start_snap) as begin_snapid
, e2.snapid as end_snapid
, nvl(e1.snaptime, e2.logon_time) as begin_snaptime
, e2.snaptime as end_snaptime
, greatest((e2.snaptime - nvl(e1.snaptime, e2.logon_time))*86400,1) as snap_interval
, e2.audsid
, e2.username
, e2.program
, e2.terminal
, e2.machine
, e2.osuser
, e2.module
, e2.action
, substr(e2.name,1,45) as name
, e2.time_waited_micro - nvl(e1.time_waited_micro,0) as wait_us
, e2.total_waits - nvl(e1.total_waits,0) as waits
from sawr$sess_event e1
right outer join
sawr$sess_event e2
on (e1.audsid = e2.audsid
and e1.sid = e2.sid
and e1.serial# = e2.serial#
and e1.logon_time = e2.logon_time
and e1.event# = e2.event#
and e1.snapid = &start_snap)
where e2.snapid = &end_snap
)
, micros as (
select d.*
, round(d.wait_us/d.snap_interval) as us_per_sec
from deltas d
where d.waits != 0
or d.wait_us != 0
)
select &grouping
&name_col
, rpad('#',trunc(ratio_to_report(sum(wait_us)) over (partition by &grouping)*10),'#') as histgm
, sum(us_per_sec)/1000 as ms_per_sec
, round(sum(us_per_sec)/10000,2) as pct_in_wait
, (sum(wait_us)/decode(sum(waits),0,1,sum(waits))/1000) as avg_wait_ms
, sum(wait_us)/1000 as wait_ms
, sum(waits) as waits
from micros
group by
&grouping
&name_col
order by
&grouping, ms_per_sec desc;
rem Stats delta report
rem ==================================================================================
col delta head Delta for 999999999999999
col delta_per_sec head D/sec for 999999999999.9
with deltas as (
select s2.sid
, nvl(s1.snapid, &start_snap) as begin_snapid
, s2.snapid as end_snapid
, nvl(s1.snaptime, s2.logon_time) as begin_snaptime
, s2.snaptime as end_snaptime
, greatest((s2.snaptime - nvl(s1.snaptime, s2.logon_time))*86400,1) as snap_interval
, s2.audsid
, s2.username
, s2.program
, s2.terminal
, s2.machine
, s2.osuser
, s2.module
, s2.action
, substr(s2.name,1,45) as name
, s2.value - nvl(s1.value,0) as delta
from sawr$sess_stat s1
right outer join
sawr$sess_stat s2
on (s1.audsid = s2.audsid
and s1.sid = s2.sid
and s1.serial# = s2.serial#
and s1.logon_time = s2.logon_time
and s1.statistic# = s2.statistic#
and s1.snapid = &start_snap)
where s2.snapid = &end_snap
)
select &grouping
&name_col
, rpad('#',trunc(ratio_to_report(sum(delta)) over (partition by &grouping)*10),'#') as histgm
, sum(delta)/avg(snap_interval) as delta_per_sec
, sum(delta) as delta
from deltas
where delta != 0
group by
&grouping
&name_col
order by
&grouping, abs(delta) desc;
break on _nonexistent
set feedback on null ""

View File

@@ -0,0 +1,190 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
set feedback 5 lines 200 trimspool on
define _tptmode = normal
define grouping = &1
define start_snap = &2
define end_snap = &3
define stat_cols = "&4"
col wait_ms for 9999999999
col avg_wait_ms for 99999999.9
col ms_per_sec for 999999.9
col module for a30 truncate
col action for a30 truncate
col program for a30 truncate
col username for a15 truncate
col osuser for a20 truncate
col name for a30 truncate
col machine for a20 truncate
col histgm for a10 truncate
col delta head Delta for 9999999999
col delta_per_sec head D/sec for 9999999.9
col grouping_break noprint new_value grouping_break
col mandatory_name_col noprint new_value name_col
col stat_list_cols noprint new_value stat_list
col e2_grouping_cols noprint new_value e2_grouping
col sa_grouping_cols noprint new_value sa_grouping
--set termout off
select case
when replace(lower('&grouping'), ',', ' ') like '% name %'
or replace(lower('&grouping'), ',', ' ') like '% name'
or replace(lower('&grouping'), ',', ' ') like 'name %'
or trim(lower('&grouping')) = 'name'
then '--,name'
else ',name'
end as mandatory_name_col
, replace('&grouping', ',', ' on ') as grouping_break
, replace(replace('e2.&grouping',' '),',',',e2.') as e2_grouping_cols
, replace(replace('sa.&grouping',' '),',',',sa.') as sa_grouping_cols
, replace(
replace(
replace('&stat_cols',', ',','),' ,',','),',',''',''') as stat_list_cols
from dual;
--set termout on
break on &grouping_break on delta_type skip 1
select
to_char(a.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_begin,
to_char(b.snaptime, 'YYYYMMDD HH24:MI:SS') snapshot_end,
(b.snaptime - a.snaptime)*86400 dur_sec,
(b.snaptime - a.snaptime)*86400/60 dur_min
from
(select snaptime from sawr$snapshots where snapid = &start_snap) a,
(select snaptime from sawr$snapshots where snapid = &end_snap) b
/
rem Specific stats and events delta report
rem ==================================================================================
with stat_deltas as (
select s2.sid
, nvl(s1.snapid, &start_snap) as begin_snapid
, s2.snapid as end_snapid
, nvl(s1.snaptime, s2.logon_time) as begin_snaptime
, s2.snaptime as end_snaptime
, greatest((s2.snaptime - nvl(s1.snaptime, s2.logon_time))*86400,1) as snap_interval
, s2.audsid
, s2.username
, s2.program
, s2.terminal
, s2.machine
, s2.osuser
, s2.module
, s2.action
, substr(s2.name,1,45) as name
, s2.value - nvl(s1.value,0) as delta
from sawr$sess_stat s1
right outer join
sawr$sess_stat s2
on (s1.audsid = s2.audsid
and s1.sid = s2.sid
and s1.serial# = s2.serial#
and s1.logon_time = s2.logon_time
and s1.statistic# = s2.statistic#
and s1.snapid = &start_snap)
where s2.snapid = &end_snap
and (s2.name in ( '&stat_list' )
or replace('&stat_list',' ') is null)
)
, stat_aggregates as (
select &grouping
&name_col
, sum(delta)/avg(snap_interval) as delta_per_sec
, sum(delta) as delta
from stat_deltas
where delta != 0
group by
&grouping
&name_col
order by
&grouping, abs(delta) desc
)
, event_deltas as (
select e2.sid
, nvl(e1.snapid, &start_snap) as begin_snapid
, e2.snapid as end_snapid
, nvl(e1.snaptime, e2.logon_time) as begin_snaptime
, e2.snaptime as end_snaptime
, greatest((e2.snaptime - nvl(e1.snaptime, e2.logon_time))*86400,1) as snap_interval
, e2.audsid
, e2.username
, e2.program
, e2.terminal
, e2.machine
, e2.osuser
, e2.module
, e2.action
, substr(e2.name,1,45) as name
, e2.time_waited_micro - nvl(e1.time_waited_micro,0) as wait_us
, e2.total_waits - nvl(e1.total_waits,0) as waits
from sawr$sess_event e1
right outer join
sawr$sess_event e2
on (e1.audsid = e2.audsid
and e1.sid = e2.sid
and e1.serial# = e2.serial#
and e1.logon_time = e2.logon_time
and e1.event# = e2.event#
and e1.snapid = &start_snap)
where e2.snapid = &end_snap
and (&e2_grouping) in (select &sa_grouping from stat_aggregates sa)
)
, event_micros as (
select ed.*
, round(ed.wait_us/ed.snap_interval) as us_per_sec
from event_deltas ed
where ed.waits != 0
or ed.wait_us != 0
)
, event_aggregates as (
select &grouping
&name_col
, rpad('#',trunc(ratio_to_report(sum(wait_us)) over (partition by &grouping)*10),'#') as histgm
, sum(wait_us)/1000 as wait_ms
, sum(us_per_sec)/1000 as ms_per_sec
, round(sum(us_per_sec)/10000,2) as pct_in_wait
, (sum(wait_us)/decode(sum(waits),0,1,sum(waits))/1000) as avg_wait_ms
, sum(waits) as waits
from event_micros
group by
&grouping
&name_col
order by
&grouping, ms_per_sec desc
)
select *
from (
select &grouping
, 'STAT' as delta_type
&name_col
, delta_per_sec
, delta
from stat_aggregates
union all
select &grouping
, 'EVENT' as delta_type
&name_col
, ms_per_sec
, waits
from event_aggregates
)
order by
&grouping, delta_type, delta_per_sec desc;

View File

@@ -0,0 +1,46 @@
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Notes: This software is provided AS IS and doesn't guarantee anything
-- Proofread before you execute it!
--
--------------------------------------------------------------------------------
prompt
prompt Dropping roles...
prompt
drop role sesspack_admin_role;
drop role sesspack_user_role;
prompt
prompt Ready to revoke SAWR privileges from user &spuser
prompt The following commands will be run:
prompt
prompt revoke select on sys.v_$session from &spuser;
prompt revoke select on sys.v_$session_wait from &spuser;
prompt revoke select on sys.v_$session_event from &spuser;
prompt revoke select on sys.v_$sess_time_model from &spuser;
prompt revoke select on sys.v_$sesstat from &spuser;
prompt revoke select on sys.v_$event_name from &spuser;
prompt revoke select on sys.v_$statname from &spuser;
prompt
pause Press CTRL-C if you don't want to run those commands, otherwise press ENTER...
prompt
revoke select on sys.v_$session from &spuser;
revoke select on sys.v_$session_wait from &spuser;
revoke select on sys.v_$session_event from &spuser;
revoke select on sys.v_$sess_time_model from &spuser;
revoke select on sys.v_$sesstat from &spuser;
revoke select on sys.v_$event_name from &spuser;
revoke select on sys.v_$statname from &spuser;
whenever sqlerror continue