================================================================================
RT6 - SQL IN THE CURSOR CACHE
================================================================================
-- RT6.1 Per-execution profile of SQL currently being executed
-- Note : GV$SQL values are cumulative since the cursor was loaded.
SELECT q.inst_id, q.sql_id, q.child_number, q.plan_hash_value, q.executions, q.users_executing,
ROUND(q.elapsed_time/1e6/NULLIF(q.executions,0),2) AS ela_pe_s,
ROUND(q.cpu_time/1e6/NULLIF(q.executions,0),2) AS cpu_pe_s,
ROUND(q.user_io_wait_time/1e6/NULLIF(q.executions,0),2) AS io_pe_s,
ROUND(q.buffer_gets/NULLIF(q.executions,0)) AS gets_pe,
ROUND(q.disk_reads/NULLIF(q.executions,0)) AS reads_pe,
ROUND(q.rows_processed/NULLIF(q.executions,0),1) AS rows_pe,
q.module, q.last_active_time
FROM gv$sql q
WHERE (q.inst_id, q.sql_id, q.child_number) IN
(SELECT inst_id, sql_id, sql_child_number
FROM gv$session
WHERE type = 'USER' AND status = 'ACTIVE' AND sql_id IS NOT NULL)
ORDER BY ela_pe_s DESC NULLS LAST;
-- RT6.2 Top SQL active in the last hour by total elapsed (cumulative stats)
SELECT inst_id, sql_id, plan_hash_value, executions,
ROUND(elapsed_time/1e6) AS ela_s,
ROUND(cpu_time/1e6) AS cpu_s,
ROUND(elapsed_time/1e6/NULLIF(executions,0),2) AS ela_pe_s,
ROUND(buffer_gets/NULLIF(executions,0)) AS gets_pe,
ROUND(disk_reads/NULLIF(executions,0)) AS reads_pe,
last_active_time
FROM gv$sqlstats
WHERE last_active_time > SYSDATE - 1/24
ORDER BY elapsed_time DESC
FETCH FIRST 20 ROWS ONLY;
-- RT6.3 One SQL_ID: all children and their per-execution cost
SELECT inst_id, sql_id, child_number, plan_hash_value, executions, users_executing,
ROUND(elapsed_time/1e6/NULLIF(executions,0),3) AS ela_pe_s,
ROUND(buffer_gets/NULLIF(executions,0)) AS gets_pe,
ROUND(disk_reads/NULLIF(executions,0)) AS reads_pe,
ROUND(rows_processed/NULLIF(executions,0),1) AS rows_pe,
optimizer_cost, is_bind_sensitive, is_bind_aware, is_shareable,
sql_profile, sql_plan_baseline, last_active_time
FROM gv$sql
WHERE sql_id = :sql_id
ORDER BY inst_id, child_number;
-- RT6.4 Plan with predicates and peeked binds (run on the instance holding the cursor)
-- Note : ALLSTATS / A-Rows only exist if STATISTICS_LEVEL=ALL or the
-- GATHER_PLAN_STATISTICS hint was used. For actual rows use RT7.2.
SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(:sql_id, :child_no,
'TYPICAL +PEEKED_BINDS +PREDICATE +OUTLINE'));
-- RT6.5 Captured binds
SELECT inst_id, sql_id, child_number, position, name, datatype_string, last_captured, value_string
FROM gv$sql_bind_capture
WHERE sql_id = :sql_id
ORDER BY inst_id, child_number, position;
-- RT6.6 SQL with many child cursors (cursor-sharing problems)
SELECT inst_id, sql_id, COUNT(*) AS children, SUM(executions) AS execs,
SUBSTR(MAX(sql_text),1,120) AS sql_text
FROM gv$sql
GROUP BY inst_id, sql_id
HAVING COUNT(*) > 20
ORDER BY children DESC
FETCH FIRST 20 ROWS ONLY;
-- RT6.7 Why children were not shared (look for 'Y' columns)
SELECT *
FROM gv$sql_shared_cursor
WHERE sql_id = :sql_id
AND ROWNUM <= 20;
-- RT6.8 Optimizer settings that differ between children of one SQL_ID
SELECT inst_id, name,
COUNT(DISTINCT value) AS distinct_values,
LISTAGG(child_number || '=' || value, ', ') WITHIN GROUP (ORDER BY child_number) AS child_values
FROM gv$sql_optimizer_env
WHERE sql_id = :sql_id
GROUP BY inst_id, name
HAVING COUNT(DISTINCT value) > 1
ORDER BY inst_id, name;
================================================================================
RT7 - SQL MONITOR (TUNING PACK) AND LONGOPS
================================================================================
-- RT7.1 Monitored SQL executing now
SELECT inst_id, sid, session_serial#, sql_id, sql_exec_id, sql_exec_start, status,
username, module, px_servers_allocated,
ROUND(elapsed_time/1e6) AS ela_s,
ROUND(cpu_time/1e6) AS cpu_s,
ROUND(user_io_wait_time/1e6) AS io_s,
ROUND(application_wait_time/1e6) AS app_s,
ROUND(concurrency_wait_time/1e6) AS conc_s,
ROUND(cluster_wait_time/1e6) AS cluster_s,
buffer_gets, disk_reads, physical_read_requests
FROM gv$sql_monitor
WHERE status = 'EXECUTING'
ORDER BY elapsed_time DESC;
-- RT7.2 Actual rows / starts / reads per plan line for one execution
-- Read : E-rows vs A-rows gaps = cardinality problem; huge starts on an
-- index line with few rows returned higher up = excessive probing.
SELECT plan_line_id,
LPAD(' ', plan_depth) || plan_operation || ' ' || plan_options AS operation,
plan_object_owner, plan_object_name,
plan_cardinality AS e_rows,
starts,
output_rows AS a_rows,
physical_read_requests,
ROUND(physical_read_bytes/1048576) AS read_mb,
ROUND(workarea_mem/1048576) AS wa_mem_mb,
ROUND(workarea_tempseg/1048576) AS wa_temp_mb
FROM gv$sql_plan_monitor
WHERE sql_id = :sql_id
AND sql_exec_id = :sql_exec_id
AND inst_id = :inst_id
ORDER BY plan_line_id;
-- RT7.3 Where the time goes inside that execution (ASH by plan line)
SELECT sql_plan_line_id, sql_plan_operation, sql_plan_options,
NVL(event,'ON CPU') AS event, COUNT(*) AS samples
FROM gv$active_session_history
WHERE sql_id = :sql_id
AND sql_exec_id = :sql_exec_id
GROUP BY sql_plan_line_id, sql_plan_operation, sql_plan_options, event
ORDER BY samples DESC;
-- RT7.4 Text SQL Monitor report for one execution
SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR(sql_id => :sql_id,
sql_exec_id => :sql_exec_id,
type => 'TEXT',
report_level => 'ALL')
FROM dual;
-- RT7.5 Long operations in progress (instrumented operations only)
-- Note : an empty result does NOT mean the session is idle.
SELECT l.inst_id, l.sid, l.serial#, s.module, l.opname, l.target, l.sofar, l.totalwork, l.units,
ROUND(l.sofar/NULLIF(l.totalwork,0)*100,1) AS pct_done,
l.elapsed_seconds, l.time_remaining, l.sql_id
FROM gv$session_longops l
JOIN gv$session s ON s.inst_id = l.inst_id AND s.sid = l.sid AND s.serial# = l.serial#
WHERE l.totalwork > 0
AND l.sofar < l.totalwork
ORDER BY l.elapsed_seconds DESC;
================================================================================
RT8 - I/O LATENCY NOW
================================================================================
-- RT8.1 Per-datafile read latency in the last metric interval
-- Read : average_read_time is in centiseconds -> *10 = ms. One file or
-- diskgroup much slower than the rest = storage hotspot.
SELECT f.inst_id, d.tablespace_name, d.file_name,
f.physical_reads,
ROUND(f.average_read_time * 10, 2) AS avg_read_ms,
f.physical_writes,
ROUND(f.average_write_time * 10, 2) AS avg_write_ms,
TO_CHAR(f.begin_time,'HH24:MI:SS') AS from_t,
TO_CHAR(f.end_time,'HH24:MI:SS') AS to_t
FROM gv$filemetric f
JOIN dba_data_files d ON d.file_id = f.file_id
WHERE f.physical_reads > 0
ORDER BY f.physical_reads DESC
FETCH FIRST 25 ROWS ONLY;
-- RT8.2 I/O wait profile by event, last 15 minutes (live ASH)
SELECT event, COUNT(*) AS samples,
COUNT(DISTINCT inst_id || ':' || session_id || ',' || session_serial#) AS sessions,
ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100,1) AS pct
FROM gv$active_session_history
WHERE sample_time > SYSDATE - 15/1440
AND wait_class = 'User I/O'
GROUP BY event
ORDER BY samples DESC;
================================================================================
RT9 - TEMP, PGA, WORKAREAS
================================================================================
-- RT9.1 TEMP consumers (real block size, not assumed 8 KB)
SELECT s.inst_id, s.sid, s.serial#, s.username, s.module, s.sql_id AS current_sql,
u.sql_id AS temp_sql_id, u.tablespace, u.segtype,
ROUND(u.blocks * t.block_size / 1048576) AS temp_mb
FROM gv$tempseg_usage u
JOIN gv$session s
ON s.inst_id = u.inst_id AND s.saddr = u.session_addr
JOIN dba_tablespaces t ON t.tablespace_name = u.tablespace
ORDER BY u.blocks DESC
FETCH FIRST 20 ROWS ONLY;
-- RT9.2 TEMP tablespace headroom
SELECT tablespace_name,
ROUND(tablespace_size/1048576) AS size_mb,
ROUND(allocated_space/1048576) AS allocated_mb,
ROUND(free_space/1048576) AS free_mb
FROM dba_temp_free_space;
-- RT9.3 Active sort/hash workareas (spills in flight)
-- Read : number_passes > 0 or large tempseg_mb = workarea spilling to TEMP.
SELECT inst_id, sid, sql_id, operation_type, policy,
ROUND(actual_mem_used/1048576) AS mem_mb,
ROUND(max_mem_used/1048576) AS max_mem_mb,
number_passes,
ROUND(tempseg_size/1048576) AS tempseg_mb
FROM gv$sql_workarea_active
ORDER BY tempseg_size DESC NULLS LAST, actual_mem_used DESC;
-- RT9.4 PGA overview per instance
SELECT inst_id, name, ROUND(value/1048576) AS mb_or_count
FROM gv$pgastat
WHERE name IN ('aggregate PGA target parameter','total PGA allocated',
'total PGA inuse','maximum PGA allocated','over allocation count')
ORDER BY inst_id, name;
================================================================================
RT10 - UNDO AND OPEN TRANSACTIONS
================================================================================
-- RT10.1 Open transactions by undo used, with owning session
-- Read : large used_ublk on an INACTIVE session = long uncommitted transaction.
SELECT s.inst_id, s.sid, s.serial#, s.username, s.module, s.action, s.status,
s.last_call_et, s.sql_id, s.prev_sql_id,
t.start_time, t.used_ublk, t.used_urec,
ROUND(t.used_ublk * TO_NUMBER(p.value) / 1048576) AS undo_mb,
t.status AS txn_status
FROM gv$transaction t
JOIN gv$session s ON s.inst_id = t.inst_id AND s.taddr = t.addr
JOIN gv$parameter p ON p.inst_id = t.inst_id AND p.name = 'db_block_size'
ORDER BY t.used_ublk DESC;
-- RT10.2 Undo extent status
SELECT tablespace_name, status, ROUND(SUM(bytes)/1048576) AS mb
FROM dba_undo_extents
GROUP BY tablespace_name, status
ORDER BY tablespace_name, status;
================================================================================
RT11 - DRILL INTO ONE SESSION
================================================================================
-- RT11.1 Session identity and OS process
SELECT s.inst_id, s.sid, s.serial#, s.audsid, s.username, s.osuser, s.machine,
s.program, s.module, s.action, s.client_identifier,
p.spid AS os_pid, s.logon_time, s.status, s.last_call_et
FROM gv$session s
JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id
WHERE s.inst_id = :inst_id
AND s.sid = :sid;
-- RT11.2 Session wait totals since logon
SELECT event, wait_class, total_waits,
ROUND(time_waited_micro/1e6,1) AS waited_s,
ROUND(time_waited_micro/1e3/NULLIF(total_waits,0),2) AS avg_ms
FROM gv$session_event
WHERE inst_id = :inst_id
AND sid = :sid
AND wait_class <> 'Idle'
ORDER BY time_waited_micro DESC;
-- RT11.3 Key session statistics since logon
SELECT n.name, st.value
FROM gv$sesstat st
JOIN gv$statname n ON n.inst_id = st.inst_id AND n.statistic# = st.statistic#
WHERE st.inst_id = :inst_id
AND st.sid = :sid
AND n.name IN ('CPU used by this session','session logical reads',
'physical reads','physical read IO requests',
'parse count (hard)','execute count','user commits',
'redo size','session pga memory','session pga memory max')
ORDER BY n.name;
-- RT11.4 What this session did in the last 30 minutes (live ASH)
SELECT sql_id, NVL(event,'ON CPU') AS event, COUNT(*) AS samples,
MIN(sample_time) AS first_seen, MAX(sample_time) AS last_seen
FROM gv$active_session_history
WHERE inst_id = :inst_id
AND session_id = :sid
AND session_serial# = :serial
AND sample_time > SYSDATE - 30/1440
GROUP BY sql_id, event
ORDER BY samples DESC;
================================================================================
RT12 - RAC AND RESOURCE LIMITS
================================================================================
-- RT12.1 Cluster waits in the last 15 minutes by event and object
SELECT h.inst_id, h.event, o.owner, o.object_name, COUNT(*) AS samples
FROM gv$active_session_history h
LEFT JOIN dba_objects o ON o.object_id = h.current_obj#
WHERE h.sample_time > SYSDATE - 15/1440
AND h.wait_class = 'Cluster'
GROUP BY h.inst_id, h.event, o.owner, o.object_name
ORDER BY samples DESC
FETCH FIRST 20 ROWS ONLY;
-- RT12.2 Sessions / processes vs limits
SELECT inst_id, resource_name, current_utilization, max_utilization,
initial_allocation, limit_value
FROM gv$resource_limit
WHERE resource_name IN ('processes','sessions','transactions','parallel_max_servers')
ORDER BY inst_id, resource_name;
================================================================================
QUICK TRIAGE ORDER
================================================================================
1. RT1.1 / RT1.3 -> CPU, I/O, locks or RAC? Where is the load?
2. RT4.1 -> If anyone is blocked, the blocker is the RCA first.
3. RT3.1 / RT3.3 -> Which EBS requests are running / stuck pending?
4. RT2.1 / RT2.3 -> Which SQL and modules dominate the last 15 minutes?
5. RT6.1 / RT7.2 -> Per-exec cost and actual rows for the top SQL.
6. RT8.1 -> Is storage latency abnormal right now?
7. RT9 / RT10 -> TEMP spills, long transactions, undo.
================================================================================
END OF PACK
================================================================================
No comments:
Post a Comment