rem rem Script: get_query_progress.sql rem Author: Jeff Moss rem Dated: November 2005 rem Purpose: Gets the execution plan for a query and shows the work areas rem and longops associated with it...in order to try and show rem where a query is at in it's execution. rem rem Versions tested rem 10.1.0.4 rem rem Notes: rem The script isn't perfect for example, it doesn't cope well with: rem 1. Situations where there is no work area for an operation rem 2. Situations where there are no long ops for an operation rem 3. There is a bug in 10.1.0.4 where the PARENT_ID columns can rem be corrupted - Bug ###, SR 4990863. rem Causes retrieved execution plan to be malformed even when statement runs rem 4. Doesn't deal with some cases where the statement pointed to by V$SESSION is rem not the actual statement being run, e.g. when refreshing a Materialized View. rem rem BUT, at least it's better than nothing. UNDEFINE sid ACCEPT search_sid NUMBER FORMAT 9999999990 PROMPT 'Enter SID: ' COLUMN id HEADING "ID" FORMAT 999 COLUMN operation HEADING "Operation" FORMAT A40 WRAP COLUMN options HEADING "Options" FORMAT A15 WRAP COLUMN object_name HEADING "Object|Name" FORMAT A20 WRAP COLUMN cardinality HEADING "Cardinality" FORMAT 999,999,999,990 COLUMN operation_type HEADING "Operation|Type" FORMAT A15 WRAP COLUMN active_time HEADING "Active|For(s)" FORMAT 999,990 COLUMN WA_Size HEADING "Workarea|Size (Mb)" FORMAT 999,990 COLUMN sid HEADING "SID" FORMAT 99999 COLUMN time_remaining HEADING "Time|Left" FORMAT A7 COLUMN last_execution HEADING "Last|Execution" FORMAT A10 COLUMN message HEADING "Longop|Msg" FORMAT A20 WRAP SET VERIFY OFF SET FEEDBACK OFF SET TIMING OFF SET PAGESIZE 10000 SET LINESIZE 200 SET WRAP OFF clear breaks clear computes break ON id ON operation ON options ON object_name ON CARDINALITY ON operation_type ON active_time ON REPORT COMPUTE SUM OF WA_Size ON REPORT WITH v_session AS ( SELECT /*+ NO_MERGE */ sql_child_number , sql_id FROM v$session WHERE sid = &search_sid ) , v_sql_plan AS ( SELECT sp.child_number , sp.sql_id , sp.parent_id , sp.id , sp.operation , sp.object_name FROM v$sql_plan sp , v_session s WHERE sp.sql_id = s.sql_id AND sp.child_number = s.sql_child_number ORDER BY sp.id ) , get_plan_lines AS ( SELECT /*+ NO_MERGE */ sp_sw_swa.id , sp_sw_swa.parent_id , sp_sw_swa.operation , sp_sw_swa.object_name , sp_sw_swa.operation_type , sp_sw_swa.message , (CASE WHEN sp_sw_swa.active_time > 0 THEN ROUND(sp_sw_swa.active_time / 1000000) ELSE 0 END) active_time , (CASE WHEN sp_sw_swa.work_area_size > 0 THEN ROUND(sp_sw_swa.work_area_size / (1024*1024) ) ELSE 0 END) WA_Size , sp_sw_swa.sid sid , sp_sw_swa.time_remaining FROM v_session s , v$sqlarea sq , (SELECT sp.id , sp.parent_id , sp.sql_id , sp.operation , sp.object_name , sw.operation_type , swa.active_time , swa.work_area_size , swa.sid , sl.time_remaining , sl.message FROM v_sql_plan sp , v$sql_workarea sw , v$sql_workarea_active swa , v$session_longops sl WHERE sp.sql_id = sw.sql_id(+) AND sp.child_number = sw.child_number(+) AND sp.id = sw.operation_id(+) AND sp.sql_id = swa.sql_id(+) AND sp.id = swa.operation_id(+) AND swa.sql_id = sl.sql_id(+) AND swa.sid = sl.sid(+) AND sl.time_remaining(+) != 0 AND DECODE(swa.operation_type,'HASH-JOIN','HASH' ,'BUFFER','SORT' ,'WINDOW (SORT)','SORT' ,'GROUP BY (SORT)','SORT' ,'LOAD WRITE BUFFERS','SORT' ,'XXXX') = UPPER(SUBSTR(sl.opname(+),1,4)) ) sp_sw_swa WHERE s.sql_id = sq.sql_id(+) AND s.sql_id = sp_sw_swa.sql_id(+) ) , get_whole_plan AS ( SELECT id , LPAD(' ',1*(level-1))||operation operation , object_name , operation_type , active_time , NVL(TO_CHAR(time_remaining),'N/A') time_remaining , sid , WA_Size , NVL(message,'No Long Op Running') message FROM get_plan_lines START WITH id = 0 CONNECT BY PRIOR id = parent_id ORDER BY id ) , add_rn AS ( SELECT id , operation , object_name , operation_type , active_time , time_remaining , sid , WA_Size , message , ROW_NUMBER() OVER(PARTITION BY id,sid ORDER BY id) rn FROM get_whole_plan ) SELECT * FROM add_rn WHERE rn = 1 /