-- ===========================================

-- SQL_ID Deep-Dive: Step-by-Step (Copy-All)

-- Safe (SELECT-only). No time window required.

-- ===========================================


-- Formatting

SET LINESIZE 300

SET PAGESIZE 200

SET TRIMSPOOL ON

SET TAB OFF

SET VERIFY OFF

SET FEEDBACK ON

SET TIMING ON

SET HEADING ON


COLUMN inst_id              FORMAT 99

COLUMN sql_id               FORMAT A13

COLUMN child_number         FORMAT 999

COLUMN plan_hash_value      FORMAT 9999999999

COLUMN sql_plan_hash_value  FORMAT 9999999999

COLUMN last_active_time     FORMAT A19

COLUMN wait_or_class        FORMAT A40

COLUMN op                   FORMAT A45

COLUMN object_name          FORMAT A40

COLUMN snap_time            FORMAT A20

COLUMN name                 FORMAT A35

COLUMN value                FORMAT A40


-- >>>> EDIT THIS (required) <<<<

DEFINE sql_id = 'PUT_SQL_ID_HERE';


-- (Optional) Spool output to a file:

-- SPOOL sqlid_&&sql_id..lst


PROMPT [STEP 1] Cursor Cache: recent executions (if still in memory)

SELECT inst_id,

       sql_id,

       child_number,

       plan_hash_value,

       TO_CHAR(last_active_time,'YYYY-MM-DD HH24:MI:SS') last_active_time,

       executions                                                AS execs,

       ROUND(elapsed_time/1e6,2)                                 AS elapsed_s,

       ROUND(cpu_time/1e6,2)                                     AS cpu_s,

       ROUND(user_io_wait_time/1e6,2)                            AS io_s,

       buffer_gets,

       disk_reads,

       rows_processed                                            AS rows_proc

FROM   gv$sql

WHERE  sql_id='&sql_id'

ORDER  BY last_active_time DESC;


PROMPT [STEP 2] Bind Values (current capture)

SELECT inst_id, name, position, datatype_string, value_string, last_captured

FROM   gv$sql_bind_capture

WHERE  sql_id='&sql_id'

ORDER  BY last_captured DESC, position;


PROMPT [STEP 3] Bind Values (AWR history)

SELECT name, position, datatype_string, value_string, last_captured

FROM   dba_hist_sqlbind

WHERE  sql_id='&sql_id'

ORDER  BY last_captured DESC, position;


PROMPT [STEP 4] AWR Execution History (all snapshots for this SQL_ID)

WITH snaps AS (

  SELECT s.snap_id, s.instance_number, s.dbid, s.begin_interval_time

  FROM   dba_hist_snapshot s

)

SELECT TO_CHAR(s.begin_interval_time,'YYYY-MM-DD HH24:MI') snap_time,

       ss.plan_hash_value,

       ss.executions_delta                                  AS execs,

       ROUND(ss.elapsed_time_delta/1e6,2)                   AS elapsed_s,

       ROUND(ss.cpu_time_delta/1e6,2)                       AS cpu_s,

       ROUND(ss.iowait_delta/1e6,2)                         AS io_s,

       ROUND(ss.cluster_wait_time_delta/1e6,2)              AS gc_s,

       ss.buffer_gets_delta                                 AS buffer_gets,

       ss.disk_reads_delta                                  AS disk_reads,

       ss.rows_processed_delta                              AS rows_proc

FROM   dba_hist_sqlstat ss

JOIN   snaps s

  ON   s.snap_id=ss.snap_id AND s.dbid=ss.dbid AND s.instance_number=ss.instance_number

WHERE  ss.sql_id='&sql_id'

ORDER  BY s.begin_interval_time DESC;


PROMPT [STEP 5] AWR Time by Plan: aggregate per PLAN_HASH_VALUE

SELECT ss.plan_hash_value,

       ROUND(SUM(ss.elapsed_time_delta)/1e6,1)            AS elapsed_s,

       ROUND(SUM(ss.cpu_time_delta)/1e6,1)                AS cpu_s,

       ROUND(SUM(ss.iowait_delta)/1e6,1)                  AS io_wait_s,

       ROUND(SUM(ss.cluster_wait_time_delta)/1e6,1)       AS gc_wait_s,

       SUM(ss.buffer_gets_delta)                           AS buffer_gets,

       SUM(ss.disk_reads_delta)                            AS disk_reads,

       SUM(ss.rows_processed_delta)                        AS rows_proc

FROM   dba_hist_sqlstat ss

WHERE  ss.sql_id='&sql_id'

GROUP  BY ss.plan_hash_value

ORDER  BY elapsed_s DESC;


PROMPT [STEP 6] ASH Wait Profile (entire ASH history for this SQL_ID)

SELECT NVL(event, wait_class) AS wait_or_class,

       COUNT(*)               AS samples,

       ROUND(100*RATIO_TO_REPORT(COUNT(*)) OVER (),1) AS pct

FROM   dba_hist_active_sess_history

WHERE  sql_id='&sql_id'

GROUP  BY NVL(event, wait_class)

ORDER  BY samples DESC FETCH FIRST 20 ROWS ONLY;


PROMPT [STEP 7] ASH Hot Plan Lines (use SQL_PLAN_HASH_VALUE)

SELECT sql_plan_hash_value,

       sql_plan_line_id,

       sql_plan_operation||' '||sql_plan_options AS op,

       COUNT(*)                                  AS samples

FROM   dba_hist_active_sess_history

WHERE  sql_id='&sql_id'

GROUP  BY sql_plan_hash_value, sql_plan_line_id, sql_plan_operation, sql_plan_options

ORDER  BY samples DESC FETCH FIRST 25 ROWS ONLY;


PROMPT [STEP 8] RAC: Samples by Instance (distribution across nodes)

SELECT instance_number, COUNT(*) AS samples

FROM   dba_hist_active_sess_history

WHERE  sql_id='&sql_id'

GROUP  BY instance_number

ORDER  BY samples DESC;


PROMPT [STEP 9] RAC: Top Objects during Cluster (GC) waits

SELECT NVL(o.owner||'.'||o.object_name,'-') AS object_name,

       COUNT(*) AS samples

FROM   dba_hist_active_sess_history a

LEFT   JOIN dba_objects o ON a.current_obj#=o.object_id

WHERE  a.sql_id='&sql_id'

AND    a.wait_class='Cluster'

GROUP  BY NVL(o.owner||'.'||o.object_name,'-')

ORDER  BY samples DESC FETCH FIRST 15 ROWS ONLY;


PROMPT [STEP 10] TEMP/PGA Spill Indicators

-- Total TEMP allocated across AWR history for this SQL_ID

SELECT ROUND(SUM(temp_space_allocated_delta)/1024/1024/1024,3) AS temp_gb

FROM   dba_hist_sqlstat

WHERE  sql_id='&sql_id';


-- Current PGA snapshot (runtime; may require privileges)

SELECT name, value

FROM   v$pgastat

WHERE  name IN ('total PGA allocated','PGA cache hit percentage');


PROMPT [STEP 11] I/O Latency (during min..max snaps where this SQL appeared)

WITH r AS (

  SELECT MIN(snap_id) b, MAX(snap_id) e

  FROM   dba_hist_sqlstat

  WHERE  sql_id='&sql_id'

)

SELECT f.filetype_name,

       ROUND(f.readtim / DECODE(NULLIF(f.phyrds,0),0,1,f.phyrds),3)   AS ms_per_read,

       ROUND(f.writetim/ DECODE(NULLIF(f.phywrts,0),0,1,f.phywrts),3) AS ms_per_write

FROM   dba_hist_filestatxs f, r

WHERE  f.snap_id BETWEEN r.b AND r.e

GROUP  BY f.filetype_name, f.readtim, f.phyrds, f.writetim, f.phywrts

ORDER  BY ms_per_read DESC;


PROMPT [STEP 12] Plan Inventory (current cache + historical)

-- Current (if in cache)

SELECT DISTINCT inst_id, plan_hash_value

FROM   gv$sql

WHERE  sql_id='&sql_id'

ORDER  BY inst_id;


-- Historical plans seen in AWR

SELECT DISTINCT plan_hash_value, COUNT(*) AS occurrences

FROM   dba_hist_sql_plan

WHERE  sql_id='&sql_id'

GROUP  BY plan_hash_value

ORDER  BY occurrences DESC;


-- Current plan with actuals (if cached recently)

SELECT *

FROM   gv$sql_plan_statistics_all

WHERE  sql_id='&sql_id'

ORDER  BY inst_id, plan_hash_value, id;


PROMPT [STEP 13 - OPTIONAL] Object Stats Freshness (set DEFINE owner before running)

-- To use this step, first run: DEFINE owner = 'OWNER_SCHEMA';

-- Then execute the query below.

-- SELECT owner, table_name, last_analyzed, stale_stats

-- FROM   dba_tab_statistics

-- WHERE  owner = '&owner'

--   AND  table_name IN (

--     SELECT DISTINCT o.object_name

--     FROM   dba_objects o

--     WHERE  o.object_id IN (

--       SELECT DISTINCT current_obj#

--       FROM   dba_hist_active_sess_history

--       WHERE  sql_id='&sql_id'

--     )

--   )

-- ORDER  BY last_analyzed DESC;


PROMPT [STEP 14] Key Optimizer/Parallel/PGA Params (snapshot for env diff)

SELECT name, value

FROM   v$parameter

WHERE  name IN (

  'optimizer_features_enable','optimizer_mode','cursor_sharing',

  'parallel_degree_policy','parallel_min_time_threshold',

  'pga_aggregate_target','pga_aggregate_limit'

)

ORDER  BY name;


-- (Optional) Real-time ASH if statement is currently running:

-- SELECT NVL(event,wait_class) wait_or_class, COUNT(*) samples

-- FROM   gv$active_session_history

-- WHERE  sql_id='&sql_id'

-- GROUP  BY NVL(event,wait_class)

-- ORDER  BY samples DESC;


-- SPOOL OFF

-- ===== End of script =====

Popular posts from this blog