Saturday, May 24, 2025

--------------------------------------------------------------------------------------- set lines 155 col dbtime for 999,999.99 col begin_timestamp for a40 select * from ( select begin_snap, end_snap, timestamp begin_timestamp, inst, a/1000000/60 DBtime from ( select e.snap_id end_snap, lag(e.snap_id) over (order by e.snap_id) begin_snap, lag(s.end_interval_time) over (order by e.snap_id) timestamp, s.instance_number inst, e.value, nvl(value-lag(value) over (order by e.snap_id),0) a from dba_hist_sys_time_model e, DBA_HIST_SNAPSHOT s where s.snap_id = e.snap_id and e.instance_number = s.instance_number and to_char(e.instance_number) like nvl('&instance_number',to_char(e.instance_number)) and stat_name = 'DB time' ) where begin_snap between nvl('&begin_snap_id',0) and nvl('&end_snap_id',99999999) and begin_snap=end_snap-1 order by dbtime desc ) where rownum < 31 / -------------------------------------------------------------------------------------------------------------------- -- File name: prashantpoormanscript1.sql -- Version: V1.1 (12-08-2021) Fancy Version -- Purpose: This script can be used on any Oracle DB to know what all running and for how long and waiting -- Also provides details on SQL and SESSION level. -- Author: Prashant Dixit The Fatdba www.fatdba.com -------------------------------------------------------------------------------------------------------------------- set linesize 400 set pagesize 400 col ACTION for a22 col USERNAME for a9 col SQL_ID for a16 col EVENT for a20 col OSUSER for a10 col PROCESS for a8 col MACHINE for a15 col OSUSER for a8 col PROGRAM for a15 col module for a20 col BLOCKING_INSTANCE for a20 select 'InstID .............................................: '||x.inst_id, 'SID ................................................: '||x.sid, 'Serial .............................................: '||x.serial#, 'Username ...........................................: '||x.username, 'SQLID ..............................................: '||x.sql_id, 'PHV ................................................: '||plan_hash_value, 'DISK_READS .........................................: '||sqlarea.DISK_READS, 'BUFFER_GETS ........................................: '||sqlarea.BUFFER_GETS, 'ROWS_PROCESSED ..... ...............................: '||sqlarea.ROWS_PROCESSED, 'Event .............................................: '||x.event, 'OSUser .............................................: '||x.osuser, 'Status .............................................: '||x.status, 'BLOCKING_SESSION_STATUS ............................: '||x.BLOCKING_SESSION_STATUS, 'BLOCKING_INSTANCE ..................................: '||x.BLOCKING_INSTANCE, 'BLOCKING_SESSION ...................................: '||x.BLOCKING_SESSION, 'PROCESS ............................................: '||x.process, 'MACHINE ............................................: '||x.machine, 'PROGRAM ............................................: '||x.program, 'MODULE .............................................: '||x.module, 'ACTION .............................................: '||x.action, 'LOGONTIME ..........................................: '||TO_CHAR(x.LOGON_TIME, 'MM-DD-YYYY HH24:MI:SS') logontime, 'LAST_CALL_ET .......................................: '||x.LAST_CALL_ET, 'SECONDS_IN_WAIT ....................................: '||x.SECONDS_IN_WAIT, 'STATE ..............................................: '||x.state, 'RUNNING_SINCE ......................................: '||ltrim(to_char(floor(x.LAST_CALL_ET/3600), '09')) || ':' || ltrim(to_char(floor(mod(x.LAST_CALL_ET, 3600)/60), '09')) || ':' || ltrim(to_char(mod(x.LAST_CALL_ET, 60), '09')) RUNNING_SINCE, 'SQLTEXT ............................................: '||sql_text from gv$sqlarea sqlarea ,gv$session x where x.sql_hash_value = sqlarea.hash_value and x.sql_address = sqlarea.address and sql_text not like '%select x.inst_id,x.sid ,x.serial# ,x.username ,x.sql_id ,plan_hash_value%' and sql_text not like '%select :"SYS_B_00"||x.inst_id, :"SYS_B_01"||x.sid, :"SYS_B_02"||x.serial#,%' and x.status='ACTIVE' and x.USERNAME is not null and x.SQL_ADDRESS = sqlarea.ADDRESS and x.SQL_HASH_VALUE = sqlarea.HASH_VALUE order by RUNNING_SINCE desc; set lines 155 col dbtime for 999,999.99 col begin_timestamp for a40 select * from ( select begin_snap, end_snap, timestamp begin_timestamp, inst, a/1000000/60 DBtime from ( select e.snap_id end_snap, lag(e.snap_id) over (order by e.snap_id) begin_snap, lag(s.end_interval_time) over (order by e.snap_id) timestamp, s.instance_number inst, e.value, nvl(value-lag(value) over (order by e.snap_id),0) a from dba_hist_sys_time_model e, DBA_HIST_SNAPSHOT s where s.snap_id = e.snap_id and e.instance_number = s.instance_number and to_char(e.instance_number) like nvl('&instance_number',to_char(e.instance_number)) and stat_name = 'DB time' ) where begin_snap between nvl('&begin_snap_id',0) and nvl('&end_snap_id',99999999) and begin_snap=end_snap-1 order by dbtime desc ) where rownum < 31 / SET MARKUP HTML ON SET ECHO OFF SET FEEDBACK OFF SET PAGESIZE 100 SET LINESIZE 200 SPOOL 63_top_fullscan_high_io.html PROMPT

Top 10 Full Table Scan SQLs (Non-SYS) with High Logical Reads

SELECT * FROM ( SELECT ss.sql_id, u.username, ROUND(ss.buffer_gets_total / DECODE(ss.executions_total, 0, 1, ss.executions_total)) AS avg_buffer_gets, ss.executions_total, ss.buffer_gets_total, CASE WHEN ROUND(ss.buffer_gets_total / DECODE(ss.executions_total, 0, 1, ss.executions_total)) > 100000 THEN 'CRITICAL' WHEN ROUND(ss.buffer_gets_total / DECODE(ss.executions_total, 0, 1, ss.executions_total)) > 50000 THEN 'WARNING' ELSE 'OK' END AS status, st.sql_text FROM dba_hist_sqlstat ss JOIN dba_hist_sqltext st ON ss.sql_id = st.sql_id JOIN dba_users u ON ss.parsing_schema_id = u.user_id WHERE ss.snap_id > ( SELECT MAX(snap_id) - 48 FROM dba_hist_snapshot ) AND u.username NOT IN ('SYS', 'SYSTEM') AND EXISTS ( SELECT 1 FROM dba_hist_sql_plan p WHERE p.sql_id = ss.sql_id AND p.operation = 'TABLE ACCESS' AND p.options = 'FULL' ) ORDER BY ss.buffer_gets_total DESC ) WHERE ROWNUM <= 10; SPOOL OFF; SPOOL OFF; SPOOL OFF; SPOOL OFF; --============================================================================== -- GPI - Gunther Pippèrr -- Desc: Informations about cursor usage in the database -- Date: 08.2013 --============================================================================== set linesize 130 pagesize 300 column user_name format a25 ttitle left "Open Cursor used summary" skip 2 select inst_id , user_name , count(*) from gv$open_cursor where user_name is not null -- and user_name not in ( 'SYS' ) group by rollup (inst_id,user_name) / ttitle left "Open Cursor used by session" skip 2 select inst_id , sid , user_name , count(*) from gv$open_cursor where user_name is not null -- and user_name not in ( 'SYS' ) group by inst_id,user_name,sid order by 4,1,3 / column name format a30 heading "Statistic|Name" column value format 999G999G999G999 heading "Statistic|value" ttitle left "Open Cursor used by session over the statistic" skip 2 select a.value , s.username , s.sid , s.serial# from v$sesstat a , v$statname b , v$session s where a.statistic# = b.statistic# and s.sid=a.sid and b.name = 'opened cursors current' and s.username is not null / ttitle left "Open Cursor Statistic " skip 2 column execute_count format 999G999G999G999G999 heading "SQL Execution" column parse_count format 999G999G999G999G999 heading "Parse Count" column cursor_hits format 999G999G999G999G999 heading "Cursor Hits" column hit_percentage_parse format 99D990 heading "Parse| % Total" column hit_percentage_cursor format 99D990 heading "Cursor Cache | % Total" select inst_id , execute_count , parse_count , round(parse_count/(execute_count/100),3) as hit_percentage_parse , cursor_hits , round(cursor_hits/(execute_count/100),3) as hit_percentage_cursor from ( select name , value , inst_id from gv$sysstat where name in ('session cursor cache hits','parse count (total)','execute count') ) pivot ( max (value) FOR name IN ( 'session cursor cache hits' AS cursor_hits , 'parse count (total)' as parse_count , 'execute count' as execute_count ) ) / prompt ... 11g Syntax if you hid an error on 10g! prompt ... if Cursor Cache % Total is a relatively low percentage prompt ... you should increate the DB Parameter session_cached_cursors ttitle left "Cursor Settings init.ora " skip 2 show parameter cursor ttitle left "Session cached Cursor Usage " skip 2 -- -- see also -- SCRIPT - to Set the 'SESSION_CACHED_CURSORS' and 'OPEN_CURSORS' Parameters Based on Usage (Doc ID 208857.1) -- select a.inst_id , 'session_cached_cursors' parameter , lpad(value, 5) value , decode(value, 0, ' n/a', to_char(100 * used / value, '990') || '%') usage from ( select max(s.value) used , inst_id from v$statname n , gv$sesstat s where n.name = 'session cursor cache count' and s.statistic# = n.statistic# group by inst_id ) a, ( select value,inst_id from gv$parameter where name = 'session_cached_cursors' ) b where a.inst_id=b.inst_id union all select c.inst_id , 'open_cursors' , lpad(value, 5) , to_char(100 * used / value, '990') || '%' from ( select s.inst_id , max((s.value)) used from v$statname n , gv$sesstat s where n.name in ('opened cursors current') and s.statistic# = n.statistic# group by s.inst_id ) c, ( select value,inst_id from gv$parameter where name = 'open_cursors' ) d where c.inst_id=d.inst_id order by 1,2 / ttitle off prompt ... if usage percentage is a near 100% prompt ... you should increate the DB Parameter session_cached_cursors ### 63_top_fullscan_high_io.sql SET MARKUP HTML ON SET ECHO OFF SET FEEDBACK OFF SET PAGESIZE 100 SET LINESIZE 200 SPOOL 63_top_fullscan_high_io.html PROMPT

Top 10 Full Table Scan SQLs (Non-SYS) with High I/O Waits

SELECT * FROM ( SELECT s.sql_id, u.username, ROUND(ss.disk_reads / DECODE(ss.executions, 0, 1, ss.executions)) AS avg_disk_reads, ss.executions, ss.buffer_gets, CASE WHEN ROUND(ss.disk_reads / DECODE(ss.executions, 0, 1, ss.executions)) > 10000 THEN 'CRITICAL' WHEN ROUND(ss.disk_reads / DECODE(ss.executions, 0, 1, ss.executions)) > 5000 THEN 'WARNING' ELSE 'OK' END AS status, st.sql_text FROM dba_hist_sqlstat ss JOIN dba_hist_sqltext st ON ss.sql_id = st.sql_id JOIN dba_users u ON ss.parsing_schema_id = u.user_id WHERE ss.snap_id > ( SELECT MAX(snap_id) - 48 FROM dba_hist_snapshot ) AND u.username NOT IN ('SYS', 'SYSTEM') AND EXISTS ( SELECT 1 FROM dba_hist_sql_plan p WHERE p.sql_id = ss.sql_id AND p.operation = 'TABLE ACCESS' AND p.options = 'FULL' ) ORDER BY ss.disk_reads DESC ) WHERE ROWNUM <= 10; SPOOL OFF; SET LINESIZE 200 SET PAGESIZE 100 COLUMN inst_id FORMAT 99 COLUMN name FORMAT A60 COLUMN value_mb FORMAT 999999999.99 SELECT inst_id, name, ROUND(value / 1024 / 1024, 2) AS value_mb FROM gv$cell_global_statistics WHERE name IN ( 'CLO read retries due to stalling', 'IO bytes sent via Smart Interconnect to cells', 'IO bytes sent via non-Smart Interconnect to cells' ) ORDER BY inst_id, name; SET LINESIZE 200 SET PAGESIZE 100 COLUMN inst_id FORMAT 99 COLUMN event FORMAT A50 COLUMN wait_time_milli FORMAT 999 COLUMN wait_count FORMAT 999999 SELECT inst_id, event, wait_time_milli, wait_count FROM gv$event_histogram WHERE event IN ( 'gc buffer busy acquire', 'gc buffer busy release', 'gc cr block busy' ) AND wait_count > 0 ORDER BY inst_id, event, wait_time_milli; SET ECHO OFF FEEDBACK OFF PAGES 50 LINES 167 TRIMSPOOL ON SET MARKUP HTML ON SPOOL 59_gc_contention_19c.html SELECT inst_id AS "Inst#", event AS "Event", total_waits AS "# Waits", ROUND(time_waited*10) AS "Time (ms)", ROUND((time_waited*10)/DECODE(total_waits, 0, 1, total_waits), 1) AS "Avg Wait (ms)", CASE WHEN ROUND((time_waited*10)/DECODE(total_waits, 0, 1, total_waits), 1) > 5 THEN 'CRITICAL' WHEN ROUND((time_waited*10)/DECODE(total_waits, 0, 1, total_waits), 1) > 2 THEN 'WARNING' ELSE 'OK' END AS "Status" FROM gv$system_event WHERE event IN ('gc buffer busy acquire','gc buffer busy release','gc cr block busy') ORDER BY inst_id, time_waited DESC; SPOOL OFF; 60_interconnect_19c.sql -- 60_interconnect_19c.sql - Monitor RAC interconnect usage and latency SET ECHO OFF FEEDBACK OFF PAGES 100 LINES 200 TRIMSPOOL ON SET MARKUP HTML ON SET ECHO OFF FEEDBACK OFF PAGES 100 LINES 200 TRIMSPOOL ON SET MARKUP HTML ON SPOOL 60_interconnect_19c.html SELECT inst_id AS "Inst#", ROUND( MAX(CASE WHEN name='gc cr block receive time' THEN value END) / GREATEST(MAX(CASE WHEN name='gc cr blocks received' THEN value END), 1) * 10, 2) AS "Avg CR (ms)", ROUND( MAX(CASE WHEN name='gc current block receive time' THEN value END) / GREATEST(MAX(CASE WHEN name='gc current blocks received' THEN value END), 1) * 10, 2) AS "Avg CUR (ms)", CASE WHEN ROUND( MAX(CASE WHEN name='gc cr block receive time' THEN value END) / GREATEST(MAX(CASE WHEN name='gc cr blocks received' THEN value END), 1) * 10, 2) > 5 THEN 'CRITICAL' WHEN ROUND( MAX(CASE WHEN name='gc cr block receive time' THEN value END) / GREATEST(MAX(CASE WHEN name='gc cr blocks received' THEN value END), 1) * 10, 2) > 2 THEN 'WARNING' ELSE 'OK' END AS "Status" FROM gv$sysstat WHERE name IN ( 'gc cr block receive time','gc cr blocks received', 'gc current block receive time','gc current blocks received' ) GROUP BY inst_id ORDER BY inst_id; SPOOL OFF; 61_iops_trend_19c.sql SET ECHO OFF FEEDBACK OFF PAGES 200 LINES 200 TRIMSPOOL ON SET MARKUP HTML ON SPOOL 61_iops_trend_19c.html SELECT TO_CHAR(begin_interval_time, 'YYYY-MM-DD HH24:MI') AS "Snap Time", instance_number, ROUND(SUM(iops), 2) AS "IOPS", CASE WHEN ROUND(SUM(iops), 2) > 10000 THEN 'CRITICAL' WHEN ROUND(SUM(iops), 2) > 5000 THEN 'WARNING' ELSE 'OK' END AS "Status" FROM ( SELECT s.begin_interval_time, t.instance_number, CASE WHEN t.metric_name = 'Physical Read Total IO Requests Per Sec' THEN t.average WHEN t.metric_name = 'Physical Write Total IO Requests Per Sec' THEN t.average WHEN t.metric_name = 'Redo Writes Per Sec' THEN t.average END AS iops FROM dba_hist_sysmetric_summary t JOIN dba_hist_snapshot s ON t.snap_id = s.snap_id AND t.dbid = s.dbid AND t.instance_number = s.instance_number WHERE t.metric_name IN ( 'Physical Read Total IO Requests Per Sec', 'Physical Write Total IO Requests Per Sec', 'Redo Writes Per Sec' ) AND s.begin_interval_time >= SYSDATE - 1 ) GROUP BY TO_CHAR(begin_interval_time, 'YYYY-MM-DD HH24:MI'), instance_number ORDER BY "Snap Time", instance_number; SPOOL OFF; SPOOL OFF; SET ECHO OFF FEEDBACK OFF PAGES 100 LINES 180 TRIMSPOOL ON SET MARKUP HTML ON SPOOL 62_top_waits_19c.html SELECT inst_id AS "Inst#", event AS "Wait Event", ROUND(time_waited/100, 2) AS "Time (s)", total_waits AS "# Waits", ROUND((time_waited*10)/DECODE(total_waits, 0, 1, total_waits), 2) AS "Avg Wait (ms)", CASE WHEN ROUND((time_waited*10)/DECODE(total_waits, 0, 1, total_waits), 2) > 50 THEN 'CRITICAL' WHEN ROUND((time_waited*10)/DECODE(total_waits, 0, 1, total_waits), 2) > 20 THEN 'WARNING' ELSE 'OK' END AS "Status" FROM ( SELECT e.inst_id, e.event, e.time_waited, e.total_waits, RANK() OVER (PARTITION BY e.inst_id ORDER BY e.time_waited DESC) AS rk FROM gv$system_event e WHERE e.event NOT IN ( SELECT name FROM v$event_name WHERE wait_class = 'Idle' ) ) WHERE rk <= 5 ORDER BY inst_id, "Time (s)" DESC; SPOOL OFF; SET LINESIZE 200 SET PAGESIZE 100 COLUMN inst_id FORMAT 99 COLUMN event FORMAT A50 COLUMN wait_count FORMAT 9999999 SELECT inst_id, event, COUNT(*) AS wait_count FROM gv$active_session_history WHERE sample_time > SYSDATE - 5/1440 AND session_state = 'WAITING' GROUP BY inst_id, event ORDER BY inst_id, wait_count DESC; SET LINESIZE 200 SET PAGESIZE 100 COLUMN snap_time FORMAT A20 COLUMN instance_number FORMAT 99 COLUMN iops FORMAT 999999.99 WITH io_stats AS ( SELECT s.snap_id, s.instance_number, TO_CHAR(s.begin_interval_time, 'YYYY-MM-DD HH24:MI') AS snap_time, MAX(CASE WHEN ss.stat_name = 'physical read IO requests' THEN ss.value END) AS read_io, MAX(CASE WHEN ss.stat_name = 'physical write IO requests' THEN ss.value END) AS write_io, s.begin_interval_time, s.end_interval_time FROM dba_hist_sysstat ss JOIN dba_hist_snapshot s ON ss.snap_id = s.snap_id AND ss.instance_number = s.instance_number WHERE ss.stat_name IN ('physical read IO requests', 'physical write IO requests') AND s.begin_interval_time > SYSDATE - 1 GROUP BY s.snap_id, s.instance_number, s.begin_interval_time, s.end_interval_time ), deltas AS ( SELECT snap_time, instance_number, (read_io + write_io) - LAG(read_io + write_io) OVER (PARTITION BY instance_number ORDER BY begin_interval_time) AS total_io, (CAST(end_interval_time AS DATE) - CAST(begin_interval_time AS DATE)) * 24 * 60 * 60 AS elapsed_seconds FROM io_stats ) SELECT snap_time, instance_number, ROUND(total_io / NULLIF(elapsed_seconds, 0), 2) AS iops FROM deltas WHERE total_io IS NOT NULL ORDER BY snap_time DESC, instance_number; SET LINESIZE 200 SET PAGESIZE 100 COLUMN begin_time FORMAT A20 COLUMN instance_number FORMAT 99 COLUMN db_time_mins FORMAT 999999.99 WITH dbtime_deltas AS ( SELECT s.snap_id, s.instance_number, s.begin_interval_time, s.end_interval_time, tm.value - LAG(tm.value) OVER (PARTITION BY s.instance_number ORDER BY s.snap_id) AS db_time FROM dba_hist_snapshot s JOIN dba_hist_sys_time_model tm ON s.snap_id = tm.snap_id AND s.instance_number = tm.instance_number WHERE tm.stat_name = 'DB time' AND s.begin_interval_time > SYSDATE - 1 ), load_data AS ( SELECT begin_interval_time, instance_number, ROUND(db_time / 1e6, 2) AS db_time_mins FROM dbtime_deltas WHERE db_time IS NOT NULL ) SELECT TO_CHAR(begin_interval_time, 'YYYY-MM-DD HH24:MI') AS begin_time, instance_number, db_time_mins FROM load_data ORDER BY db_time_mins DESC FETCH FIRST 30 ROWS ONLY; SET LINESIZE 200 SET PAGESIZE 100 COLUMN begin_time FORMAT A20 COLUMN instance_number FORMAT 99 COLUMN db_time_mins FORMAT 999999.99 WITH dbtime_deltas AS ( SELECT s.snap_id, s.instance_number, s.begin_interval_time, s.end_interval_time, tm.value - LAG(tm.value) OVER (PARTITION BY s.instance_number ORDER BY s.snap_id) AS db_time FROM dba_hist_snapshot s JOIN dba_hist_sys_time_model tm ON s.snap_id = tm.snap_id AND s.instance_number = tm.instance_number WHERE tm.stat_name = 'DB time' AND s.begin_interval_time > SYSDATE - 1 ), load_data AS ( SELECT begin_interval_time, instance_number, ROUND(db_time / 1e6, 2) AS db_time_mins FROM dbtime_deltas WHERE db_time IS NOT NULL ) SELECT TO_CHAR(begin_interval_time, 'YYYY-MM-DD HH24:MI') AS begin_time, instance_number, db_time_mins FROM load_data ORDER BY db_time_mins DESC FETCH FIRST 30 ROWS ONLY; SET LINESIZE 155 COL dbtime FOR 999,999.99 COL begin_timestamp FOR A40 SELECT * FROM ( SELECT begin_snap, end_snap, begin_timestamp, inst, ROUND(dbtime_microsecs / 1e6 / 60, 2) AS dbtime FROM ( SELECT e.snap_id AS end_snap, LAG(e.snap_id) OVER (PARTITION BY e.instance_number ORDER BY e.snap_id) AS begin_snap, LAG(s.end_interval_time) OVER (PARTITION BY e.instance_number ORDER BY e.snap_id) AS begin_timestamp, s.instance_number AS inst, NVL(e.value - LAG(e.value) OVER (PARTITION BY e.instance_number ORDER BY e.snap_id), 0) AS dbtime_microsecs FROM dba_hist_sys_time_model e JOIN dba_hist_snapshot s ON e.snap_id = s.snap_id AND e.instance_number = s.instance_number WHERE e.stat_name = 'DB time' AND TO_CHAR(e.instance_number) LIKE NVL('&instance_number', TO_CHAR(e.instance_number)) ) WHERE begin_snap BETWEEN NVL('&begin_snap_id', 0) AND NVL('&end_snap_id', 99999999) AND begin_snap = end_snap - 1 ORDER BY dbtime DESC ) WHERE ROWNUM < 31; is_rac() { local db_connect="$1" local result result=$(sqlplus -s "$db_connect" < 1 THEN 'RAC' ELSE 'SINGLE' END FROM gv\\$instance; EXIT; EOF ) if [[ "$result" == "RAC" ]]; then return 0 # true: RAC else return 1 # false: Single instance fi } if is_rac "$DB_CONNECT_STRING"; then echo "✅ RAC Database detected" else echo "ℹ️ Single Instance Database" fi COL wait_chain FOR A300 WORD_WRAP COL "%This" FOR A6 PROMPT PROMPT -- Display ASH Wait Chain Signatures script v0.8 by Tanel Poder ( https://tanelpoder.com ) WITH bclass AS (SELECT /*+ INLINE */ class, ROWNUM r from v$waitstat), ash AS (SELECT /*+ INLINE QB_NAME(ash) LEADING(a) USE_HASH(u) SWAP_JOIN_INPUTS(u) */ a.* , CAST(a.sample_time AS DATE) sample_time_s -- round timestamp to 1 sec boundary for matching across RAC nodes , o.* , u.username , CASE WHEN a.session_type = 'BACKGROUND' AND a.program LIKE '%(DBW%)' THEN '(DBWn)' WHEN a.session_type = 'BACKGROUND' OR REGEXP_LIKE(a.program, '.*\([PJ]\d+\)') THEN REGEXP_REPLACE(SUBSTR(a.program,INSTR(a.program,'(')), '\d', 'n') ELSE '('||REGEXP_REPLACE(REGEXP_REPLACE(a.program, '(.*)@(.*)(\(.*\))', '\1'), '\d', 'n')||')' END || ' ' program2 , NVL(a.event||CASE WHEN event like 'enq%' AND session_state = 'WAITING' THEN ' [mode='||BITAND(p1, POWER(2,14)-1)||']' WHEN a.event IN (SELECT name FROM v$event_name WHERE parameter3 = 'class#') THEN ' ['||NVL((SELECT class FROM bclass WHERE r = a.p3),'undo @bclass '||a.p3)||']' ELSE null END,'ON CPU') || ' ' event2 , TO_CHAR(CASE WHEN session_state = 'WAITING' THEN p1 ELSE null END, '0XXXXXXXXXXXXXXX') p1hex , TO_CHAR(CASE WHEN session_state = 'WAITING' THEN p2 ELSE null END, '0XXXXXXXXXXXXXXX') p2hex , TO_CHAR(CASE WHEN session_state = 'WAITING' THEN p3 ELSE null END, '0XXXXXXXXXXXXXXX') p3hex , CASE WHEN BITAND(time_model, POWER(2, 01)) = POWER(2, 01) THEN 'DBTIME ' END ||CASE WHEN BITAND(time_model, POWER(2, 02)) = POWER(2, 02) THEN 'BACKGROUND ' END ||CASE WHEN BITAND(time_model, POWER(2, 03)) = POWER(2, 03) THEN 'CONNECTION_MGMT ' END ||CASE WHEN BITAND(time_model, POWER(2, 04)) = POWER(2, 04) THEN 'PARSE ' END ||CASE WHEN BITAND(time_model, POWER(2, 05)) = POWER(2, 05) THEN 'FAILED_PARSE ' END ||CASE WHEN BITAND(time_model, POWER(2, 06)) = POWER(2, 06) THEN 'NOMEM_PARSE ' END ||CASE WHEN BITAND(time_model, POWER(2, 07)) = POWER(2, 07) THEN 'HARD_PARSE ' END ||CASE WHEN BITAND(time_model, POWER(2, 08)) = POWER(2, 08) THEN 'NO_SHARERS_PARSE ' END ||CASE WHEN BITAND(time_model, POWER(2, 09)) = POWER(2, 09) THEN 'BIND_MISMATCH_PARSE ' END ||CASE WHEN BITAND(time_model, POWER(2, 10)) = POWER(2, 10) THEN 'SQL_EXECUTION ' END ||CASE WHEN BITAND(time_model, POWER(2, 11)) = POWER(2, 11) THEN 'PLSQL_EXECUTION ' END ||CASE WHEN BITAND(time_model, POWER(2, 12)) = POWER(2, 12) THEN 'PLSQL_RPC ' END ||CASE WHEN BITAND(time_model, POWER(2, 13)) = POWER(2, 13) THEN 'PLSQL_COMPILATION ' END ||CASE WHEN BITAND(time_model, POWER(2, 14)) = POWER(2, 14) THEN 'JAVA_EXECUTION ' END ||CASE WHEN BITAND(time_model, POWER(2, 15)) = POWER(2, 15) THEN 'BIND ' END ||CASE WHEN BITAND(time_model, POWER(2, 16)) = POWER(2, 16) THEN 'CURSOR_CLOSE ' END ||CASE WHEN BITAND(time_model, POWER(2, 17)) = POWER(2, 17) THEN 'SEQUENCE_LOAD ' END ||CASE WHEN BITAND(time_model, POWER(2, 18)) = POWER(2, 18) THEN 'INMEMORY_QUERY ' END ||CASE WHEN BITAND(time_model, POWER(2, 19)) = POWER(2, 19) THEN 'INMEMORY_POPULATE ' END ||CASE WHEN BITAND(time_model, POWER(2, 20)) = POWER(2, 20) THEN 'INMEMORY_PREPOPULATE ' END ||CASE WHEN BITAND(time_model, POWER(2, 21)) = POWER(2, 21) THEN 'INMEMORY_REPOPULATE ' END ||CASE WHEN BITAND(time_model, POWER(2, 22)) = POWER(2, 22) THEN 'INMEMORY_TREPOPULATE ' END ||CASE WHEN BITAND(time_model, POWER(2, 23)) = POWER(2, 23) THEN 'TABLESPACE_ENCRYPTION ' END time_model_name FROM gv$active_session_history a , dba_users u , (SELECT object_id,data_object_id,owner,object_name,subobject_name,object_type , owner||'.'||object_name obj , owner||'.'||object_name||' ['||object_type||']' objt FROM dba_objects) o WHERE a.user_id = u.user_id (+) AND a.current_obj# = o.object_id(+) AND sample_time BETWEEN &3 AND &4 ), ash_samples AS (SELECT /*+ INLINE */ DISTINCT sample_time_s FROM ash), ash_data AS (SELECT /*+ INLINE */ * FROM ash), chains AS ( SELECT /*+ INLINE */ d.sample_time_s ts , level lvl , session_id sid , REPLACE(SYS_CONNECT_BY_PATH(&1, '->'), '->', ' -> ')||CASE WHEN CONNECT_BY_ISLEAF = 1 AND d.blocking_session IS NOT NULL THEN ' -> [idle blocker '||d.blocking_inst_id||','||d.blocking_session||','||d.blocking_session_serial#||(SELECT ' ('||s.program||')' FROM gv$session s WHERE (s.inst_id, s.sid , s.serial#) = ((d.blocking_inst_id,d.blocking_session,d.blocking_session_serial#)))||']' ELSE NULL END path -- there's a reason why I'm doing this --, SYS_CONNECT_BY_PATH(&1, ' -> ')||CASE WHEN CONNECT_BY_ISLEAF = 1 THEN '('||d.session_id||')' ELSE NULL END path -- , REPLACE(SYS_CONNECT_BY_PATH(&1, '->'), '->', ' -> ')||CASE WHEN CONNECT_BY_ISLEAF = 1 AND LEVEL > 1 THEN ' [sid='||session_id||' seq#='||TO_CHAR(seq#)||']' ELSE NULL END path -- there's a reason why I'm doing this --, REPLACE(SYS_CONNECT_BY_PATH(&1, '->'), '->', ' -> ') path -- there's a reason why I'm doing this (ORA-30004 :) , CASE WHEN CONNECT_BY_ISLEAF = 1 THEN d.session_id ELSE NULL END sids , CONNECT_BY_ISLEAF isleaf , CONNECT_BY_ISCYCLE iscycle , d.* FROM ash_samples s , ash_data d WHERE s.sample_time_s = d.sample_time_s AND d.sample_time BETWEEN &3 AND &4 CONNECT BY NOCYCLE ( PRIOR d.blocking_session = d.session_id AND PRIOR d.blocking_inst_id = d.inst_id AND PRIOR s.sample_time_s = d.sample_time_s -- Different RAC nodes have sample_id drift (assuming that clocks are synced enough) ) START WITH &2 ) SELECT * FROM ( SELECT LPAD(ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100)||'%',5,' ') "%This" , COUNT(*) seconds , ROUND(COUNT(*) / ((CAST(&4 AS DATE) - CAST(&3 AS DATE)) * 86400), 1) AAS , path wait_chain , TO_CHAR(MIN(sample_time), 'YYYY-MM-DD HH24:MI:SS') first_seen , TO_CHAR(MAX(sample_time), 'YYYY-MM-DD HH24:MI:SS') last_seen , COUNT(DISTINCT sids) num_sids , MIN(sids) , MAX(sids) FROM chains WHERE isleaf = 1 GROUP BY &1 , path ORDER BY COUNT(*) DESC ) WHERE ROWNUM <= 30 /