select s1.username || '@' || s1.machine
|| ' ( SID=' || s1.sid || ' ) is blocking '
|| s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' AS blocking_status
from v$lock l1, v$session s1, v$lock l2, v$session s2
where s1.sid=l1.sid and s2.sid=l2.sid
and l1.BLOCK=1 and l2.request > 0
and l1.id1 = l2.id1
id1, id2, lmode, request, type
from v$lock
where (id1, id2, type) in
(select id1, id2, type from v$lock where request>0)
order by id1, request;
select blocking_session, sid, wait_class,
seconds_in_wait
from v$session
where blocking_session is not NULL
order by blocking_session;
decode(ash.session_state, 'WAITING' ,ash.event, ash.session_state) STATE,
ash.sql_id,
ash.blocking_session BLOCKER
from v$active_session_history ash, dba_users du
where du.user_id = ash.user_id;
o.owner, o.object_name, o.object_type
from v$locked_object l, dba_objects o
where l.object_id = o.object_id
order by o.object_id, 1 desc;
MAPPING A RESOURCE-INTENSIVE PROCESS TO A DATABASE PROCESS
ps -e -o pcpu,pid,user,tty,args | sort -n -k 1 -r | head
ps -e -o pmem,pid,user,tty,args | sort -n -k 1 -r | head
SELECT
'USERNAME : ' || s.username || CHR(10) ||
'SCHEMA : ' || s.schemaname || CHR(10) ||
'OSUSER : ' || s.osuser || CHR(10) ||
'MODUEL : ' || s.program || CHR(10) ||
'ACTION : ' || s.schemaname || CHR(10) ||
'CLIENT_INFO : ' || s.osuser || CHR(10) ||
'PROGRAM : ' || s.program || CHR(10) ||
'SPID : ' || p.spid || CHR(10) ||
'SID : ' || s.sid || CHR(10) ||
'SERIAL# : ' || s.serial# || CHR(10) ||
'KILL STRING : ' || '''' || s.sid || ',' || s.serial# || '''' || CHR(10) ||
'MACHINE : ' || s.machine || CHR(10) ||
'TYPE : ' || s.type || CHR(10) ||
'TERMINAL : ' || s.terminal || CHR(10) ||
'SQL ID : ' || q.sql_id || CHR(10) ||
'CHILD_NUM : ' || q.child_number || CHR(10) ||
'SQL TEXT : ' || q.sql_text
FROM v$session s
,v$process p
,v$sql q
WHERE s.paddr = p.addr
AND p.spid = '&PID_FROM_OS'
AND s.sql_id = q.sql_id(+)
MONITORING LONG RUNNING SQL STATEMENTS
SELECT username, target, sofar blocks_read, totalwork total_blocks,
round(time_remaining/60) minutes
FROM v$session_longops
IF YOU WANT TO DISPLAY CURRENT DATABASE SESSIONS THAT ARE WAITING FOR I/O RESOURCES ,YOU CAN QUERY THE DATA DICTIONARY AS FOLLOWS
SELECT a.username,a.sql_id,b.object_name,b.object_type,a.event
FROM v$session a
,dba_objects b
,v$event_name c
WHERE b.object_id=a.row_wait_obj#
AND a.event=c.name
AND c.wait_class='User I/O' ;
RUNNING A DATABASE HEALTH CHECK
You can get a list of all the health checks you can run by querying the following query.
select name from v$hm_check where internal='N';
Once you decide on the type of check ,specify the name of the check in the DBMS_HM package' s RUN_CHECK
begin
dbms_hm.run_check('Dictionary Integrity Check','testrun1');
end;
/
You can view a health check's findings using the DBMS_HM Package.
set long 10000000
set longchunksize 1000
set pagesize 1000
set linesize 512
select dbms_hm.get_run_report('testrun1') from dual;
IDENTIFYING RESOURCE-CONSUMING SQL STATEMENTS THAT ARE CURRENTLY EXECUTING
SELECT sql_text,disk_reads FROM
(SELECT sql_text,buffer_gets,disk_reads,sorts,cpu_time/10000000 cpu,rows_processed ,elapsed_time
FROM gv$sqlstats
ORDER BY disk_reads DESC)
WHERE rownum <=10;
SELECT sql_text,elapased_time FROM
(SELECT sql_text,buffer_gets,disk_reads,sorts,cpu_time/10000000 cpu,rows_processed ,elapsed_time
FROM gv$sqlstats
ORDER BY elapsed_time DESC)
WHERE rownum <=5;
SELECT sql_text,cpu FROM
(SELECT sql_text,buffer_gets,disk_reads,sorts,cpu_time/10000000 cpu,rows_processed ,elapsed_time
FROM v$sqlstats
ORDER BY cpu_time DESC)
WHERE rownum <=5;
SELECT sql_text,buffer_gets FROM
(SELECT sql_text,buffer_gets,disk_reads,sorts,cpu_time/10000000 cpu,rows_processed ,elapsed_time
FROM v$sqlstats
ORDER BY buffer_gets DESC)
WHERE rownum <=5;
SEEING EXECUTION STATISTICS FOR CURRENTLY RUNNING SQL
SELECT sql_text from v$sql_monitor WHERE status='EXECUTING';
SELECT sid,buffer_gets,disk_reads,round(cpu_time/1000000,1) cpu_seconds
FROM v$sql_monitor
WHERE SID='&sessionsid'
AND status='EXECUTING';
THE V$SQL_MONITOR VIEWS CONTAINS CURRENTLY RUNNING SQL STATMENTS , AS WELL AS RECENTLY RUN SQL STATEMENTS.
SELECT * FROM (
SELECT sid,SESSION_SERIAL#,buffer_gets,disk_reads,round(cpu_time/1000000,1) cpu_seconds
FROM v$sql_monitor
ORDER BY cpu_time desc)
WHERE rownum<=5;
IF YOU WANTED TO SEE ALL EXECUTIONS FOR A GIVEN QUERY (BASED ON SQL_ID ) ,WE CAN GET THAT INFORMATION BY QUERYING ON THE THREE NECESSARY COLUMNS TO DRILL TO A GIVEN
SELECT * FROM (
SELECT sql_id,to_char(sql_exec_start,'yyyy-mm-dd:hh24:mi:ss') sql_exec_start ,
sql_exec_id,sum(buffer_gets) buffer_gets,sum(disk_reads) disk_reads,round(cpu_time/1000000,1) cpu_seconds
FROM v$sql_monitor
WHERE sql_id ='&sql_id'
GROUP BY sql_id,sql_exec_start,sql_exex_id
ORDER BY 6 desc)
WHERE rownum<=5;
FOR PARALLEL SESSIONS CURRENTLY RUNNING
SELECT inst_id,SID,sql_id,to_char(sql_exec_start,'yyyy-mm-dd:hh24:mi:ss') sql_exec_start ,
sql_exec_id,px_server# px#,buffer_gets,disk_reads,round(cpu_time/1000000,1) cpu_seconds,round(elapsed_time/1000000,1) elapsed_seconds
FROM gv$sql_monitor
WHERE status='EXECUTING'
ORDER BY elapsed_seconds;
SELECT SID,sql_id,to_char(sql_exec_start,'yyyy-mm-dd:hh24:mi:ss') sql_exec_start ,
sql_exec_id,px_server# px#,buffer_gets,disk_reads,round(cpu_time/1000000,1) cpu_seconds,round(elapsed_time/1000000,1) elapsed_seconds
FROM gv$sql_monitor
WHERE status='EXECUTING'
ORDER BY sql_id;
set long 100000
SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR(sql_id=>'<sql_id>',type=>'html') FROM DUAL;
SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR(sql_id=>'<sql_id>',type=>'text') FROM DUAL;
COMPARING SQL PERFORMANCE AFTER A SYSTEM CHANGE
variable g_task varchar2(100)
EXEC :g_task :=DBMS_SQLPA.CREATE_ANALYSIS_TASK(sql_text=>'sql text paste here');
alter session set optimizer_features_enable='11.2.0.3';
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name=>:g_task ,execution_type=>'test execute',execution_name=>'before_change');
alter session set optimizer_features_enable='12.1.0.1.1';
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name=>:g_task ,execution_type=>'test execute',execution_name=>'after_change');
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name=>:g_task ,execution_type=>'COMPARE PERFORMANCE',execution_name=>'compare change',execution_params=>dbms_advisor.arglist('comparision_metric','buffer_gets'));
set long 1000000 longchunksize 100000 linesize 1000
spool compare_report.txt
SELECT DBMS_SQLPA.REPORT_ANALYSIS_TASK:g_task,'TEXT','CHANGED_PLANS','ALL') from dual;
select snap_id,instance_number,end_interval_time from dba_hist_snapshot order by snap_id;
SELECT sql_id,substr(sql_text,1,50) sql_text ,disk_reads,cpu_time,elapsed_time from
table(DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY(begin_snap_id,End_snap_id,null,null,'disk_reads',null,null,null,10))
order by disk_reads DESC;
SELECT sql_id,substr(sql_text,1,50) sql_text ,disk_reads,cpu_time,elapsed_time,parsing_schema_name from
table(
DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY(
begin_snap=>,
end_snap=>,
basic_filter=>'parsing_schema_name<>"SYS"',
ranking_measure1=>'buffer_gets',
result_limit=>10))
order by disk_reads DESC;
IDENTIFYING RESOURCE - CONSUMING SQL STATEMENTS THAT HAVE EXECUTED IN THE PAST
SELECT * FROM (
SELECT sql_id, sum(disk_reads_delta) disk_reads_delta,
sum(disk_reads_total) disk_reads_total,
sum(executions_delta) execs_delta,
sum(executions_total) execs_total
FROM dba_hist_sqlstat
GROUP BY sql_id
ORDER BY 2 desc)
WHERE rownum <= 5;
SELECT sql_text FROM dba_hist_sqltext
WHERE sql_id = '7wjb00vsk8btp ';
SELECT id, operation || ' ' || options operation, object_name, cost, bytes
FROM dba_hist_sql_plan
WHERE sql_id = '7wjb00vsk8btp '
ORDER BY 1;
YOU CAN EXECUTE THE FOLLOWING QUERY TO FIGURE OUT HOW MANY BLOCKS FOR EACH SEGMENT ARE CURRENTLY IN THE BUFFER CACHE :
from dba_objects o, v$bh v
where o.data_object_id = v.objd
and o.owner !='SYS'
group by o.object_name
order by count(*);
MINIMIZING SYSTEM CONTENTION
Issue the following query to find out the relative percentage of wait times and actual CPU processing in the database :
select metric_name, value
from v$sysmetric
where metric_name in ('Database CPU Time Ratio',
'Database Wait Time Ratio') and
intsize_csec =
u.username,
s.sql_text,
sum(ash.wait_time +
ash.time_waited) ttl_wait_time
from v$active_session_history ash,
v$sqlarea s,
dba_users u
where ash.sample_time between sysdate - 60/2880 and sysdate
and ash.sql_id = s.sql_id
and ash.user_id = u.user_id
group by ash.user_id,s.sql_text, u.username
order by ttl_wait_time
ANALYZING WAIT EVENTS
select event,count(*) from v$session_wait group by event;
select event,state,seconds_in_wait siw from v$session_wait where sid= <sid number> ;
EXAMINING WAIT EVENTS BY CLASS
The following query shows the different types of wait classes and the wait events associated with each wait class :
select wait_class, name
from v$event_name
where name LIKE 'enq%'
and wait_class <> 'Other'
order by wait_class
To view the current waits grouped into various wait classes , Issue the following query :
select wait_class, sum(time_waited), sum(time_waited)/sum(total_waits)
sum_waits
from v$system_wait_class
group by wait_class
order by 3 desc;
To view the current waits grouped into various wait classes by average waits , Issue the following query :
select sea.event, sea.total_waits, sea.time_waited, sea.average_wait
from v$system_event sea, v$event_name enb, v$system_wait_class swc
where sea.event_id=enb.event_id
and enb.wait_class#=swc.wait_class#
and swc.wait_class in ('Application','Concurrency')
order by average_wait desc
To get at the session whose performance is being affected by the contention for the row lock , drill down to the session level using the following query :
select se.sid, se.event, se.total_waits, se.time_waited, se.average_wait
from v$session_event se, v$session ss
where time_waited > 0
and se.sid=ss.sid
and ss.username is not NULL
and se.event='enq: TX - row lock contention';
BUFFER BUSY WAITS
Your database is experiencing a high number of buffer busy waits , Issue the following query :
select row_wait_obj#
from v$session
where event = 'buffer busy waits';
select owner, object_name, subobject_name, object_type
from dba_objects
where sid in (SELECT sid FROM v$session_wait WHERE event = 'buffer
busy waits');
SELECT sql_text FROM v$sqlarea WHERE sql_id = <sql_id>;
READ BY OTHER SESSION WAIT EVENTS
select p1 "file#",p2 "block#",p3 "class#" from v$session_wait where event='read by other session';
select relative_fno, owner, segment_name, segment_type
from dba_extents
where file_id = &file
and &block between block_id
and block_id + blocks - 1;
select row_wait_obj#
from v$session
where event = 'buffer busy waits';
select owner, object_name, subobject_name, object_type
from dba_objects
where data_object_id = &row_wait_obj;
DIRECT PATH READ WAIT EVENTS
from dba_extents
where file_id = &file
and &block between block_id
and block_id + blocks - 1;
select ct.table_name, co.column_name, co.position column_position
from user_constraints ct, user_cons_columns co
where ct.constraint_name = co.constraint_name
and ct.constraint_type = 'R'
minus
select ui.table_name, uic.column_name, uic.column_position
from user_indexes ui, user_ind_columns uic
where ui.index_name = uic.index_name
)
order by table_name, column_position;
sum(wait_time +
time_waited) total_wait_time
from v$active_session_history
where sample_time between
sysdate –15/1440 and sysdate
group by event
order by total_wait_time desc;
sum(a.wait_time +
a.time_waited) total_wait_time
from v$active_session_history a,
v$session s
where a.sample_time between sysdate – 15/1440 and sysdate
and a.session_id=s.sid
group by s.sid, s.username
order by total_wait_time desc;
select a.user_id,u.username,s.sql_text,
sum(a.wait_time + a.time_waited) total_wait_time
from v$active_session_history a,
v$sqlarea s,
dba_users u
where a.sample_time between sysdate – 15/1440 and sysdate
and a.sql_id = s.sql_id
and a.user_id = u.user_id
group by a.user_id,s.sql_text, u.username
order by 4;
from v$system_event e
where e.wait_class <> 'Idle' AND time_waited > 0
union
select 'Time Model', stat_name NAME,
round ((value / 1000000), 2) time_secs
from v$sys_time_model
where stat_name NOT IN ('background elapsed time', 'background cpu time')
order by 3 desc;
- we need to first start the profiler using DBMS_PROFILER.START_PROFILER,
- then we can execute the our pl/sql procedure we want monitored
- and at last we need to simply call DBMS_PROFILER.STOP_PROFILER to stop the profiler.
Make sure the user that needs to run the profiler has the correct privileges on the DBMS_PROFILER package.
GRANT EXECUTE ON dbms_profiler TO test;Next we connect to the test user and create a dummy procedure to profile.
CONN test/test@service
CREATE OR REPLACE PROCEDURE do_something (p_times IN NUMBER) AS
l_dummy NUMBER;
BEGIN
FOR i IN 1 .. p_times LOOP
SELECT l_dummy + 1
INTO l_dummy
FROM dual;
END LOOP;
END;
/Next we start the profiler, run our procedure and stop the profiler.
DECLARE
l_result BINARY_INTEGER;
BEGIN
l_result := DBMS_PROFILER.start_profiler(run_comment => 'do_something: ' || SYSDATE);
do_something(p_times => 100);
l_result := DBMS_PROFILER.stop_profiler;
END;
/With the profile complete we can analyze the data to see which bits of the process took the most time, with all times presented in nanoseconds. First we check out which runs we have.
SET LINESIZE 200
SET TRIMOUT ON
COLUMN runid FORMAT 99999
COLUMN run_comment FORMAT A50
SELECT runid,
run_date,
run_comment,
run_total_time
FROM plsql_profiler_runs
ORDER BY runid;
RUNID RUN_DATE RUN_COMMENT RUN_TOTAL_TIME
----- --------- ---------------------------------- --------------
1 21-AUG-03 do_something: 21-AUG-2003 14:51:54 131072000We then use the appropriate RUNID value in the following query.
COLUMN runid FORMAT 99999
COLUMN unit_number FORMAT 99999
COLUMN unit_type FORMAT A20
COLUMN unit_owner FORMAT A20
SELECT u.runid,
u.unit_number,
u.unit_type,
u.unit_owner,
u.unit_name,
d.line#,
d.total_occur,
d.total_time,
d.min_time,
d.max_time
FROM plsql_profiler_units u
JOIN plsql_profiler_data d ON u.runid = d.runid AND u.unit_number = d.unit_number
WHERE u.runid = 1
ORDER BY u.unit_number, d.line#;
RUNID UNIT_NU UNIT_TYPE UNIT_OWNER UNIT_NAME LINE# TOTAL_OCCUR TOTAL_TIME MIN_TIME MAX_TIME
----- ------- --------------- ----------- ------------ ----- ----------- ---------- -------- --------
1 1 ANONYMOUS BLOCK <anonymous> <anonymous> 4 1 0 0 0
1 1 ANONYMOUS BLOCK <anonymous> <anonymous> 5 1 0 0 0
1 1 ANONYMOUS BLOCK <anonymous> <anonymous> 6 1 0 0 0
1 2 PROCEDURE MY_SCHEMA DO_SOMETHING 4 101 0 0 0
1 2 PROCEDURE MY_SCHEMA DO_SOMETHING 5 100 17408000 0 2048000
5 rows selected.The results of this query show that line 4 of the DO_SOMETHING procedure ran 101 times but took very little time, while line 5 ran 100 times and took proportionately more time. We can check the line numbers of the source using the following query.
SELECT line || ' : ' || text
FROM all_source
WHERE owner = 'MY_SCHEMA'
AND type = 'PROCEDURE'
AND name = 'DO_SOMETHING';
LINE||':'||TEXT
---------------------------------------------------
1 : PROCEDURE do_something (p_times IN NUMBER) AS
2 : l_dummy NUMBER;
3 : BEGIN
4 : FOR i IN 1 .. p_times LOOP
5 : SELECT l_dummy + 1
6 : INTO l_dummy
7 : FROM dual;
8 : END LOOP;
9 : END;As expected, the query took proportionately more time than the procedural loop. Assuming this were a real procedure we could use the DBMS_TRACE or the SQL trace facilities to investigate the problem area further.
For further information see:
Description of the DBMS_MONITOR package
DBMS_MONITOR can be used to trace sessions or make traces with larger scope.
First let’s have a look to the available procedures of DBMS_MONITOR. Each procedure exists twice, one to enable the trace and one to disable it.
The CLIENT_ID_TRACE procedure
Description
This procedure is used to enable tracing using a Client Identifier.
This means that all sessions using the same Client Identifier will be traced at the same time. This type of tracing is useful when you have to make a trace for an application using an application pool to connect to the database.
The trace will persist after a database restart and you’ll have to explicitly disable it.
Syntaxe
DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE(
client_id IN VARCHAR2,
waits IN BOOLEAN DEFAULT TRUE,
binds IN BOOLEAN DEFAULT FALSE,
plan_stat IN VARCHAR2 DEFAULT NULL);Exemple
set the identifier in the session you want to trace:
SQL> exec DBMS_SESSION.SET_IDENTIFIER('this is a test');
PL/SQL procedure successfully completed.Then enable the trace for the client identifier, execute the following command in another session:
SQL> exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('this is a test',true,true);
PL/SQL procedure successfully completed.To see if the trace is enabled, you can query the dba_enabled_trace view :
SQL> select TRACE_TYPE,PRIMARY_ID,WAITS,BINDS,PLAN_STATS from dba_enabled_traces;
TRACE_TYPE PRIMARY_ID WAITS BINDS PLAN_STATS
--------------------- ---------------------------------------------------------------- ----- ----- ----------
CLIENT_ID this is a test TRUE TRUE FIRST_EXECYou can choose to get the waits, binds ans plan_stats using the parameters.
Don’t forget to disable the trace when done :
SQL> exec DBMS_MONITOR.CLIENT_ID_TRACE_DISABLE('this is a test');
PL/SQL procedure successfully completed.The DATABASE_TRACE procedure
Description
This procedure can be used to enable the trace for the whole database or for a specific instance in case RAC is used.
Syntaxe
DBMS_MONITOR.DATABASE_TRACE_ENABLE(
waits IN BOOLEAN DEFAULT TRUE,
binds IN BOOLEAN DEFAULT FALSE,
instance_name IN VARCHAR2 DEFAULT NULL,
plan_stat IN VARCHAR2 DEFAULT NULL);Exemple
To activate the trace:
exec dbms_monitor.database_trace_enable(waits=>true,binds=>TRUE);
PL/SQL procedure successfully completed.To see if the trace is activated :
SQL> select TRACE_TYPE,PRIMARY_ID,WAITS,BINDS,PLAN_STATS from dba_enabled_traces;
TRACE_TYPE PRIMARY_ID WAITS BINDS PLAN_STATS
--------------------- ---------------------------------------------------------------- ----- ----- ----------
DATABASE TRUE TRUE FIRST_EXECThen disable the trace when done :
SQL> exec dbms_monitor.database_trace_disable;
PL/SQL procedure successfully completed.The SERV_MOD_ACT_TRACE procedure
Description
This procedure can be used to trace a particular application. It is possible to filter more finely application specifying the type of action you want to trace.
Syntaxe
dbms_monitor.serv_mod_act_trace_enable(
service_name IN VARCHAR2,
module_name IN VARCHAR2 DEFAULT ANY_MODULE,
action_name IN VARCHAR2 DEFAULT ANY_ACTION,
waits IN BOOLEAN DEFAULT TRUE,
binds IN BOOLEAN DEFAULT FALSE,
instance_name IN VARCHAR2 DEFAULT NULL,
plan_stat IN VARCHAR2 DEFAULT NULL);Exemple
Consider you want to trace every user using SQL*PLUS, you can use this command :
exec dbms_monitor.serv_mod_act_trace_enable('SYS$USERS', 'SQL*Plus', dbms_monitor.all_actions, TRUE, TRUE);to see if trace is enabled :
SQL> select TRACE_TYPE,PRIMARY_ID,QUALIFIER_ID1,QUALIFIER_ID2,WAITS,BINDS from dba_enabled_traces;
TRACE_TYPE PRIMARY_ID QUALIFIER_ID1 QUALIFIER_ID2 WAITS BINDS
--------------------- ---------------------------------------------------------------- ------------------------------------------------ -------------------------------- ----- -----
SERVICE_MODULE SYS$USERS SQL*Plus TRUE TRUEto disable it :
SQL> exec dbms_monitor.serv_mod_act_trace_disable('SYS$USERS', 'SQL*Plus', dbms_monitor.all_actions);
PL/SQL procedure successfully completed.The SESSION_TRACE Procedure
Description
The SESSION_TRACE procedure is used to trace a specific session using the SID and SERIAL# columns of the v$session view. Like the other procedures you can use parameters to collect binds and waits.
Syntaxe
DBMS_MONITOR.SESSION_TRACE_ENABLE(
session_id IN BINARY_INTEGER DEFAULT NULL,
serial_num IN BINARY_INTEGER DEFAULT NULL,
waits IN BOOLEAN DEFAULT TRUE,
binds IN BOOLEAN DEFAULT FALSE,
plan_stat IN VARCHAR2 DEFAULT NULL);Example
Activate the trace :
SQL> exec DBMS_MONITOR.SESSION_TRACE_ENABLE(5,14,true,true);
PL/SQL procedure successfully completed.to disable the trace :
SQL> exec DBMS_MONITOR.SESSION_TRACE_DISABLE(5,14);
PL/SQL procedure successfully completed.This trace will not be visible in the database_enabled_trace view and will not persist after a database restart.
Using TRCSESS to aggregate your trace files
When you use a client_id trace, or procedure which can generate more than one trace file you will have to aggregate the files in order to analyze them all at the same time. This is the purpose of the TRCSESS utility.
Syntaxe
trcsess [output=output_file_name]
[session=session_id]
[clientid=client_id]
[service=service_name]
[action=action_name]
[module=module_name]
[trace_files]Example
If I need to aggregate the traces I made for the client_id ‘this is a test’, I’ll use the following syntaxe
trcsess output=mytracefile.trc clientid='this is a test' *.trcOne my file mytracefile.trc has been generated I can use TKPROF utility to analyze it :
tkprof mytracefile.trc mytraceoutput.logYou can refer to this well explained oracle documentation to learn more about application tracing.
DBMS_SQL_MONITOR package provides information about Real-time SQL Monitoring and Real-time Database Operation Monitoring.The DBMS_SQL_MONITOR package provides information about Real-time SQL Monitoring and Real-time Database Operation Monitoring. These features provide automatic monitoring of SQL statements, PL/SQL blocks, or composite database operations that are considered expensive. A simple database operation is a single SQL statement or PL/SQL procedure or function. A composite database operation is activity between two defined points in time in a database session. The monitored data is collected in V$SQL_MONITOR and V$SQL_PLAN_MONITOR.
The following subprograms begin and end monitoring of a composite database operation:
The following subprograms report on monitoring data collected in V$SQL_MONITOR and V$SQL_PLAN_MONITOR:
DBMS_SQLTUNE
DBMS_SQLTUNE package is the interface for tuning SQL on demand. The related package DBMS_AUTO_SQLTUNE package provides the interface for SQL Tuning Advisor run as an automated task.set lines 220
set pages 500
set long 200000
set longchunksize 200000
set trimspool on
set serveroutput on
col owner format a20
col table_name format a35
col partition_name format a30
col stale_stats format a8
col last_analyzed format a22
col stattype_locked format a15
col timestamp format a20
col sql_id format a15
col parsing_schema_name format a20
col sql_text format a120
col trigger_name format a35
col triggering_event format a20
col trigger_type format a20
col status format a10
col stats_update_time format a35
col stale_percent format a20
col incremental format a12
col method_opt format a40
col cascade_pref format a20
prompt
prompt ============================================================
prompt 1. INPUT
prompt ============================================================
prompt Enter OWNER and TABLE_NAME when prompted
prompt
define OWNER='&1'
define TABLE_NAME='&2'
prompt
prompt ============================================================
prompt 2. Flush monitoring info so DBA_TAB_MODIFICATIONS is current
prompt ============================================================
exec dbms_stats.flush_database_monitoring_info;
prompt
prompt ============================================================
prompt 3. Current table stats status
prompt ============================================================
select owner,
table_name,
num_rows,
blocks,
stale_stats,
to_char(last_analyzed,'DD-MON-YYYY HH24:MI:SS') last_analyzed,
stattype_locked
from dba_tab_statistics
where owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
and partition_name is null;
prompt
prompt ============================================================
prompt 4. Current modification counters Oracle is using
prompt ============================================================
select table_owner,
table_name,
nvl(inserts,0) inserts,
nvl(updates,0) updates,
nvl(deletes,0) deletes,
nvl(inserts,0)+nvl(updates,0)+nvl(deletes,0) total_modifications,
to_char(timestamp,'DD-MON-YYYY HH24:MI:SS') timestamp,
truncated
from dba_tab_modifications
where table_owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME');
prompt
prompt ============================================================
prompt 5. Why Oracle marked it stale or not stale
prompt ============================================================
select s.owner,
s.table_name,
s.num_rows,
nvl(m.inserts,0) inserts,
nvl(m.updates,0) updates,
nvl(m.deletes,0) deletes,
nvl(m.inserts,0)+nvl(m.updates,0)+nvl(m.deletes,0) total_modifications,
round(
(nvl(m.inserts,0)+nvl(m.updates,0)+nvl(m.deletes,0))
/ nullif(s.num_rows,0) * 100, 2
) modification_pct,
dbms_stats.get_prefs('STALE_PERCENT', s.owner, s.table_name) stale_percent,
case
when (
(nvl(m.inserts,0)+nvl(m.updates,0)+nvl(m.deletes,0))
/ nullif(s.num_rows,0) * 100
) >= to_number(dbms_stats.get_prefs('STALE_PERCENT', s.owner, s.table_name))
then 'ABOVE THRESHOLD -> STALE EXPECTED'
else 'BELOW THRESHOLD -> STALE NOT EXPECTED'
end stale_reason,
s.stale_stats,
to_char(s.last_analyzed,'DD-MON-YYYY HH24:MI:SS') last_analyzed
from dba_tab_statistics s
left join dba_tab_modifications m
on m.table_owner = s.owner
and m.table_name = s.table_name
where s.owner = upper('&OWNER')
and s.table_name = upper('&TABLE_NAME')
and s.partition_name is null;
prompt
prompt ============================================================
prompt 6. Partition-level stale check if table is partitioned
prompt ============================================================
select partition_name,
num_rows,
stale_stats,
to_char(last_analyzed,'DD-MON-YYYY HH24:MI:SS') last_analyzed
from dba_tab_statistics
where owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
and object_type = 'TABLE PARTITION'
order by partition_position;
prompt
prompt ============================================================
prompt 7. Partition-level modification counters if partitioned
prompt ============================================================
select table_owner,
table_name,
partition_name,
nvl(inserts,0) inserts,
nvl(updates,0) updates,
nvl(deletes,0) deletes,
nvl(inserts,0)+nvl(updates,0)+nvl(deletes,0) total_modifications,
to_char(timestamp,'DD-MON-YYYY HH24:MI:SS') timestamp
from dba_tab_modifications
where table_owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
order by partition_name;
prompt
prompt ============================================================
prompt 8. Stats preferences affecting stale behavior
prompt ============================================================
select dbms_stats.get_prefs('STALE_PERCENT', upper('&OWNER'), upper('&TABLE_NAME')) stale_percent,
dbms_stats.get_prefs('INCREMENTAL', upper('&OWNER'), upper('&TABLE_NAME')) incremental,
dbms_stats.get_prefs('METHOD_OPT', upper('&OWNER'), upper('&TABLE_NAME')) method_opt,
dbms_stats.get_prefs('CASCADE', upper('&OWNER'), upper('&TABLE_NAME')) cascade_pref
from dual;
prompt
prompt ============================================================
prompt 9. Stats history - when stats were refreshed
prompt ============================================================
select owner,
table_name,
to_char(stats_update_time,'DD-MON-YYYY HH24:MI:SS TZH:TZM') stats_update_time
from dba_tab_stats_history
where owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
order by stats_update_time desc;
prompt
prompt ============================================================
prompt 10. DML SQL currently in shared pool touching the table
prompt command_type: 2=INSERT 6=UPDATE 7=DELETE
prompt ============================================================
select sql_id,
parsing_schema_name,
command_type,
executions,
rows_processed,
buffer_gets,
disk_reads,
last_active_time,
substr(sql_text,1,1200) sql_text
from v$sql
where upper(sql_text) like '%' || upper('&TABLE_NAME') || '%'
and command_type in (2,6,7)
order by last_active_time desc;
prompt
prompt ============================================================
prompt 11. Historical DML from AWR touching the table
prompt command_type: 2=INSERT 6=UPDATE 7=DELETE
prompt ============================================================
select st.sql_id,
st.command_type,
st.parsing_schema_name,
substr(st.sql_text,1,1200) sql_text
from dba_hist_sqltext st
where upper(st.sql_text) like '%' || upper('&TABLE_NAME') || '%'
and st.command_type in (2,6,7)
order by st.sql_id;
prompt
prompt ============================================================
prompt 12. Historical execution counts for DML SQL from AWR
prompt ============================================================
select sn.begin_interval_time,
sn.end_interval_time,
ss.sql_id,
ss.plan_hash_value,
ss.executions_delta,
ss.rows_processed_delta,
round(ss.elapsed_time_delta/1e6,2) elapsed_sec,
round(ss.cpu_time_delta/1e6,2) cpu_sec,
ss.buffer_gets_delta,
ss.disk_reads_delta
from dba_hist_sqlstat ss
join dba_hist_snapshot sn
on sn.dbid = ss.dbid
and sn.instance_number = ss.instance_number
and sn.snap_id = ss.snap_id
where ss.sql_id in (
select distinct st.sql_id
from dba_hist_sqltext st
where upper(st.sql_text) like '%' || upper('&TABLE_NAME') || '%'
and st.command_type in (2,6,7)
)
order by sn.begin_interval_time, ss.sql_id;
prompt
prompt ============================================================
prompt 13. Triggers on the table
prompt These may explain extra updates from database perspective
prompt ============================================================
select owner,
trigger_name,
triggering_event,
trigger_type,
status
from dba_triggers
where table_owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
order by trigger_name;
prompt
prompt ============================================================
prompt 14. Trigger body
prompt ============================================================
select trigger_name,
trigger_body
from dba_triggers
where table_owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
order by trigger_name;
prompt
prompt ============================================================
prompt 15. Indexes on the table
prompt Helps explain whether repeated updates also maintain many indexes
prompt ============================================================
select index_name,
column_name,
column_position
from dba_ind_columns
where table_owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
order by index_name, column_position;
prompt
prompt ============================================================
prompt 16. Summary statement for RCA
prompt ============================================================
select 'Table ' || s.owner || '.' || s.table_name ||
' has NUM_ROWS=' || s.num_rows ||
', INSERTS=' || nvl(m.inserts,0) ||
', UPDATES=' || nvl(m.updates,0) ||
', DELETES=' || nvl(m.deletes,0) ||
', TOTAL_MODS=' || (nvl(m.inserts,0)+nvl(m.updates,0)+nvl(m.deletes,0)) ||
', MOD_PCT=' || round(
(nvl(m.inserts,0)+nvl(m.updates,0)+nvl(m.deletes,0))
/ nullif(s.num_rows,0) * 100, 2
) || '%' ||
', STALE_PERCENT=' || dbms_stats.get_prefs('STALE_PERCENT', s.owner, s.table_name) ||
', STALE_STATS=' || s.stale_stats
as summary_line
from dba_tab_statistics s
left join dba_tab_modifications m
on m.table_owner = s.owner
and m.table_name = s.table_name
where s.owner = upper('&OWNER')
and s.table_name = upper('&TABLE_NAME')
and s.partition_name is null;
============================Oracle Support Provided Query========
set lines 200
set pages 500
set trimspool on
set long 100000
col owner format a20
col table_name format a30
col partition_name format a30
col sql_id format a15
col parsing_schema_name format a20
col sql_text format a80
prompt
prompt ============================================================
prompt 1. Flush modification tracking
prompt ============================================================
exec dbms_stats.flush_database_monitoring_info;
prompt
prompt ============================================================
prompt 2. Table statistics status
prompt ============================================================
select owner,
table_name,
num_rows,
blocks,
stale_stats,
last_analyzed,
stattype_locked
from dba_tab_statistics
where owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
and partition_name is null;
prompt
prompt ============================================================
prompt 3. Table modification counts
prompt ============================================================
select table_owner,
table_name,
inserts,
updates,
deletes,
timestamp,
truncated
from dba_tab_modifications
where table_owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME');
prompt
prompt ============================================================
prompt 4. Modification % vs NUM_ROWS
prompt ============================================================
select s.owner,
s.table_name,
s.num_rows,
nvl(m.inserts,0) inserts,
nvl(m.updates,0) updates,
nvl(m.deletes,0) deletes,
nvl(m.inserts,0) + nvl(m.updates,0) + nvl(m.deletes,0) total_modifications,
round(
((nvl(m.inserts,0) + nvl(m.updates,0) + nvl(m.deletes,0))
/ nullif(s.num_rows,0)) * 100, 2
) modification_pct,
s.stale_stats,
s.last_analyzed
from dba_tab_statistics s
left join dba_tab_modifications m
on m.table_owner = s.owner
and m.table_name = s.table_name
where s.owner = upper('&OWNER')
and s.table_name = upper('&TABLE_NAME')
and s.partition_name is null;
prompt
prompt ============================================================
prompt 5. Partition-level stats (if partitioned)
prompt ============================================================
select partition_name,
num_rows,
stale_stats,
last_analyzed
from dba_tab_statistics
where owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
and object_type = 'TABLE PARTITION'
order by partition_position;
prompt
prompt ============================================================
prompt 6. Partition-level modifications
prompt ============================================================
select table_owner,
table_name,
partition_name,
inserts,
updates,
deletes,
timestamp
from dba_tab_modifications
where table_owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
order by partition_name;
prompt
prompt ============================================================
prompt 7. Stats preferences
prompt ============================================================
select dbms_stats.get_prefs('STALE_PERCENT', upper('&OWNER'), upper('&TABLE_NAME')) stale_percent,
dbms_stats.get_prefs('INCREMENTAL', upper('&OWNER'), upper('&TABLE_NAME')) incremental,
dbms_stats.get_prefs('METHOD_OPT', upper('&OWNER'), upper('&TABLE_NAME')) method_opt,
dbms_stats.get_prefs('CASCADE', upper('&OWNER'), upper('&TABLE_NAME')) cascade_pref
from dual;
prompt
prompt ============================================================
prompt 8. Stats history
prompt ============================================================
select owner,
table_name,
stats_update_time
from dba_tab_stats_history
where owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME')
order by stats_update_time desc;
prompt
prompt ============================================================
prompt 9. DML SQLs touching the table
prompt ============================================================
select sql_id,
parsing_schema_name,
command_type,
executions,
rows_processed,
buffer_gets,
disk_reads,
substr(sql_text,1,100) sql_text
from v$sql
where upper(sql_text) like '%' || upper('&TABLE_NAME') || '%'
and command_type in (2,6,7)
order by last_active_time desc fetch first 50 rows only;
prompt
prompt ============================================================
prompt 10. High execution SQL on table
prompt ============================================================
select sql_id,
plan_hash_value,
parsing_schema_name,
executions,
round(elapsed_time/1e6,2) elapsed_sec,
round(cpu_time/1e6,2) cpu_sec,
buffer_gets,
rows_processed,
substr(sql_text,1,100) sql_text
from v$sql
where upper(sql_text) like '%' || upper('&TABLE_NAME') || '%'
order by executions desc fetch first 30 rows only;
prompt
prompt ============================================================
prompt 11. Triggers on table
prompt ============================================================
select owner,
trigger_name,
triggering_event,
trigger_type,
status
from dba_triggers
where table_owner = upper('&OWNER')
and table_name = upper('&TABLE_NAME');
prompt
prompt ============================================================
prompt 12. Materialized view logs
prompt ============================================================
select log_owner,
master,
log_table,
rowids,
primary_key,
sequence,
include_new_values
from dba_mview_logs
where log_owner = upper('&OWNER')
and master = upper('&TABLE_NAME');
prompt
prompt ============================================================
prompt 13. SQL plan details (enter SQL_ID)
prompt ============================================================
select sql_id,
child_number,
plan_hash_value,
executions,
round(elapsed_time/1e6,2) elapsed_sec,
round(cpu_time/1e6,2) cpu_sec,
buffer_gets,
disk_reads,
rows_processed,
is_bind_sensitive,
is_bind_aware
from v$sql
where sql_id = '&SQL_ID'
order by child_number;
prompt
prompt ============================================================
prompt 14. AWR historical SQL stats
prompt ============================================================
select snap_id,
plan_hash_value,
executions_delta,
round(elapsed_time_delta/1e6,2) elapsed_sec,
round(cpu_time_delta/1e6,2) cpu_sec,
buffer_gets_delta,
disk_reads_delta,
rows_processed_delta
from dba_hist_sqlstat
where sql_id = '&SQL_ID'
order by snap_id;
prompt
prompt ============================================================
prompt 15. Execution plan (last execution)
prompt ============================================================
select *
from table(dbms_xplan.display_cursor('&SQL_ID', null, 'ALLSTATS LAST +PEEKED_BINDS'));
prompt
prompt ============================================================
prompt 16. System stats (commit / parse activity)
prompt ============================================================
select name, value
from v$sysstat
where name in (
'user commits',
'user rollbacks',
'execute count',
'parse count (total)',
'parse count (hard)'
);
prompt
prompt ============================================================
prompt SCRIPT COMPLETED
prompt ============================================================
No comments:
Post a Comment