Determining Session-Level CPU Usage:
SQL>
SELECT sid, s.value "Total CPU Used by this Session"
FROM
V$SESSTAT S
WHERE
S..statistic# = 12
ORDER BY
S,value DESC;
SID Total
CPU Used by this Session
-----
------------------------------
496 27623
542 21325
111 20814
731 17089
424 15228
What Is
the CPU Time Used For?
It would
be a mistake to treat all CPU time as equal. CPU time is generally understood
as the
processor
time taken to perform various tasks, such as the following:
• Loading
SQL statements into the library cache
•
Searching the shared pool for parsed versions of SQL statements
• Parsing
the SQL statements
• Querying
the data dictionary
• Reading
data from the buffer cache
•
Traversing index trees to fetch index keys
The total
CPU time used by an instance (or a session) can be viewed as the sum of the
following
components:
total CPU
time = parsing CPU usage + recursive CPU usage + other CPU usage
Decomposition of Total CPU Usage:
SQL>
SELECT name,value FROM V$SYSSTAT
WHERE NAME
IN ('CPU used by this session',
'recursive
cpu usage',
'parse
time cpu');
NAME VALUE
-------------------------------------
recursive
cpu usage 4713085
CPU used
by this session 98196187
parse time
cpu 132947
3 rows
selected.
Parse Time CPU Usage:
The first
query tells you that the total CPU usage in your instance is 49159124:
SQL>
SELECT name, value FROM V$SYSSTAT
2* WHERE
name LIKE '%CPU%';
NAME VALUE
--------------------------------------------
CPU used
when call started 13220745
CPU used
by this session 49159124
2 rows
selected.
SQL>
The next query shows that the parse
time CPU usage is 96431, which is an insignificant proportion
of total
CPU usage in your database:
SQL> SELECT name, value FROM
V$SYSSTAT
WHERE name LIKE '%parse%';
NAME VALUE
-------------------------------------
parse time cpu 96431
parse time elapsed 295451
parse count (total) 3147900
parse count (hard) 29139
4 rows selected.
SQL>
Determining Parse Time CPU Usage
SQL> SELECT a.value " Tot_CPU_Used_This_Session",
b.value "Total_Parse_Count",
c.value "Hard_Parse_Count",
d.value "Parse_Time_CPU"
FROM v$sysstat a,
v$sysstat b,
v$sysstat c,
v$sysstat d
WHERE a.name = 'CPU used by this
session'
AND b.name = 'parse count (total)'
AND c.name = 'parse count (hard)'
AND d.name = 'parse time cpu';
Tot_CPU_Used Total_Parse_Count
Hard_Parse_Count Parse_Time_CPU
This_Session
------------------------------
-----------------------------------
2240 53286
281 1486
Recursive
CPU Usage
Recursive CPU usage is mostly for data
dictionary lookups and for executing PL/SQL programs.
Thus, if your application uses a high
number of packages and procedures, you’ll see a significant
amount of recursive CPU usage.
In the following example, there’s no
need for alarm, because the percentage of recursive CPU
usage is only about 5 percent of total
CPU usage:
SQL> SELECT name, value FROM
V$SYSSTAT
WHERE name IN ('CPU used by this
session',
'recursive cpu usage');
NAME VALUE
------------------------------------------------
-------
recursive cpu usage 4286925
CPU used by this session 84219625
2 rows selected.
SQL>
$ sar -d 10 5
HP-UX finance1 B.11.00 A 9000/800
07/03/05
17:27:13 device %busy avque r+w/s
blks/s avwait avserv
17:27:23 c2t6d0 100 61.40 37 245 4.71
10.43
c5t6d0 20.38 0.50 28 208 4.92 9.54
c2t6d0 100 61.40 38 273 4.55 9.49
c5t6d0 18.28 0.50 27 233 4.46 7.93
c0t1d0
0.10 0.50 4 33 4.99 0.81
Determining I/O Distribution in the Database
SQL> SELECT d.name,
f.phyrds reads,
f.phywrts wrts,
(f.readtim / decode(f.phyrds,0,-1,f.phyrds))
readtime,
(f.writetim / decode(f.phywrts,0,-1,phywrts))
writetime
FROM
v$datafile d,
v$filestat f
WHERE
d.file# = f.file#
ORDER BY
d.name;
NAME READS WRTS READTIME WRITETIME
----------------------------- -----
---- ---------- ----------
/pa01/oradata/pa/lol_i_17.dbf 23 9
.608695652 .222222222
/pa01/oradata/pa/lol_i_18.dbf
18 7 .277777778 0
The V$SYSMETRIC view
displays the system metric values for the
most current time
interval. The following query using the V$SYSMETRIC view reveals a database
instance where waits are
taking more time than the instance CPU usage time:
SQL> SELECT
METRIC_NAME, VALUE
FROM V$SYSMETRIC
WHERE METRIC_NAME IN
('Database CPU Time Ratio',
'Database Wait Time
Ratio') AND
INTSIZE_CSEC =
(select max(INTSIZE_CSEC)
from V$SYSMETRIC);
METRIC_NAME VALUE
------------------------------------------------
Database Wait Time Ratio
72
Database
CPU Time Ratio 28
Determining Total Waits and Percentage Waits by
Wait Class
SQL> SELECT WAIT_CLASS,
TOTAL_WAITS,
round(100 * (TOT_WAITS / SUM_WAITS),2)
PCT_TOTWAITS,
ROUND((TIME_WAITED / 100),2)
TOT_TIME_WAITED,
round(100 * (TOT_TIME_WAITED /
SUM_TIME),2) PCT_TIME
FROM
(select WAIT_CLASS,
TOT_WAITS,
TOT_TIME_WAITED
FROM V$SYSTEM_WAIT_CLASS
WHERE WAIT_CLASS != 'Idle'),
(select sum(TOT_WAITS) SUM_WAITS,
sum(TOT_TIME_WAITED) SUM_TIME
from V$SYSTEM_WAIT_CLASS
where WAIT_CLASS != 'Idle')
ORDER BY PCT_TIME DESC;
WAIT_CLASS TOTAL_WAITS PCT_TOT_WAITS
TOT_TIME_WAITED PCT_TIME
------------- -----------
------------- --------------- --------
User I/O 6649535191 45.07 46305770.5
84.42
Other 394490128 2.67 5375324.17 9.8
Concurrency 78768788 .53 1626254.9
2.96
Network 7546925506 51.15 547128.66 1
Application 2012092 .01 449945.5 .82
Commit 15526036 .11 351043.3 .64
Configuration 12898465 .09 116029.85
.21
System I/O 53005529 .36 78783.64 .14
Administrative 25 0 7.6 0
Scheduler 1925 0 .15 0
10 rows selected.
SQL>
Using the V$SYSTEM_EVENT View to View Wait Events
SQL> SELECT event, time_waited,
average_wait
FROM V$SYSTEM_EVENT
GROUP BY event, time_waited,
average_wait
ORDER BY time_waited DESC;
EVENT TIME_WAITED AVERAGE_WAIT
------------------------------------------------------------------
rdbms ipc message 24483121 216.71465
SQL*Net message from client 18622096
106.19049
PX Idle Wait 12485418 205.01844
pmon timer 3120909 306.93440
smon timer 3093214 29459.18100
PL/SQL lock timer 3024203 1536.68852
db file sequential read 831831 .25480
db file scattered read 107253 .90554
free buffer waits 52955 43.08787
log file parallel write 19958 2.02639
latch free 5884 1.47505
...
58 rows
selected
Instance-Wide Waits Sorted by Total Wait Time
SQL> SELECT event,
total_waits,time_waited
FROM V$SYSTEM_EVENT
WHERE event NOT IN
('pmon timer','smon timer','rdbms ipc
reply','parallel deque
wait’,'virtual
circuit','%SQL*Net%','client message','NULL event')
ORDER BY time_waited DESC;
EVENT TOTAL_WAITS TIME_WAITED
------------------------------------------------------------------
db file sequential read 35051309
15965640
latch free 1373973 1913357
db file scattered read 2958367 1840810
enqueue 2837 370871
buffer busy waits 444743 252664
log file
parallel write 146221 123435
SQL> SELECT sid, blocking_session,
username,
event, seconds_in_wait siw
FROM V$SESSION
WHERE blocking_session_status =
'VALID';
SID BLOCKING_SESS USERNAME EVENT SIW
---- ------------- --------
----------------------------- -----
1218 1527 UCR_USER enq: TX - row lock
contention 23
1400 1400
APPOWNER latch free 0
The V$SESSION_WAIT_HISTORY view holds
information about the last ten wait events for each
active session. The other wait-related
views, such as the V$SESSION and the V$SESSION_WAIT,
show you only the wait information for
the most recent wait. This may be a short wait, thus escaping
your scrutiny. Here’s a sample query
using the V$SESSION_WAIT_HISTORY view:
SQL> SELECT seq#, event, wait_time,
p1, p2, p3
FROM V$SESSION_WAIT_HISTORY
WHERE sid = 988
ORDER BY seq#;
SEQ# EVENT WAIT_TIME P1 P2 P3
---- ----------------------- ---------
----- ----- ------___
1 db file sequential read 0 52 21944
2 db file sequential read 0 50 19262
3 latch: shared pool 0 1.3835E+19 198
0
4 db file sequential read 0 205 21605
5 db file sequential read 4 52 13924
6 db file sequential read 1 49 29222
7 db file sequential read 2 52 14591
8 db file sequential read 2 52 12723
9 db file sequential read 0 205 11883
10 db file sequential read 0 205 21604
10 rows selected.
SQL>
Objects
with the Highest Waits
The following query identifies the
objects causing the most waits and the type of events the objects
waited for during the last 15 minutes:
SQL> SELECT o.object_name,
o.object_type, a.event,
SUM(a.wait_time +
a.time_waited) total_wait_time
FROM v$active_session_history a,
dba_objects o
WHERE a.sample_time between sysdate -
30/2880 and sysdate
AND a.current_obj# = o.object_id
GROUP BY o.object_name, o.object_type,
a.event
ORDER BY total_wait_time;
OBJECT_NAME OBJECT_TYPE EVENT
TOTAL_WAIT_TIME
-------------------
--------------------------------------------------
UC_ADDRESS TABLE SQL*Net message to
client 2
PERS_PHONES TABLE db file sequential
read 8836
PAY_FK_I INDEX db file sequential read
9587
UC_STAGING TABLE log file sync 23633
PERSONNEL
TABLE db file sequential read 43612
Most
Important Wait Events
The following query lists the most
important wait events in your database in the last 15 minutes:
SQL> SELECT a.event,
SUM(a.wait_time +
a.time_waited) total_wait_time
FROM v$active_session_history a
WHERE a.sample_time between
sysdate - 30/2880 and sysdate
GROUP BY a.event
ORDER BY total_wait_time DESC;
EVENT TOTAL_WAIT_TIME
---------------------------------------------------------
wait for SGA component shrink
878774247
smon timer 300006992
PL/SQL lock timer 210117722
SQL*Net message from client 21588571
db file scattered read 1062608
db file sequential read 105271
log file sync 13019
latch free 274
SQL*Net more data to client 35
null event 6
17 rows selected.
SQL>
Users with
the Most Waits
The following query lists the users
with the highest wait times within the last 15 minutes:
SQL> SELECT s.sid, s.username,
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 -
30/2880 and sysdate
AND a.session_id=s.sid
GROUP BY s.sid, s.username
ORDER BY total_wait_time DESC;
SID USERNAME TOTAL_WAIT_TIME
----------
------------------------------ -----------------
1696 SYSOWNER 165104515
885 SYSOWNER 21575902
1087 BLONDI 5019123
1318 UCRSL 569723
1334 REBLOOM 376354
1489 FRAME 395
15 rows
selected.
Identifying
SQL with the Highest Waits
Using the following query, you can
identify the SQL that’s waiting the most in your instance.
The sample
time covers the last 15 minutes.
SQL> SELECT
a.user_id,d.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 d
WHERE a.sample_time between sysdate -
30/2880 and sysdate
AND a.sql_id = s.sql_id
AND a.user_id = d.user_id
GROUP BY a.user_id,s.sql_text,
d.username;
USER_ID USERNAME SQL_TEXT
TOTAL_WAIT_TIME
---------- --------
------------------------------ ----------------
0 SYS
BEGIN dbms_stats...; END; 9024233
Wait
Classes and the Wait-Related Views
The V$SESSION_WAIT view shows the
events and resources that active sessions are waiting for.
Using the V$SESSION_WAIT view, you can
also see what types of wait classes your session waits
belong to. Here’s an example:
SQL> SELECT wait_class, event, sid,
state, wait_time, seconds_in_wait
FROM v$session_wait
ORDER BY wait_class, event, sid;
WAIT_CLASS EVENT SID STATE WAIT_TIM
SEC_IN_WAIT
---------- --------------------
---------- ----------------------- --
Application enq: TX - 269 WAITING 0 73
row lock contention
Idle Queue Monitor Wait 270 WAITING 0
40
Idle SQL*Net message from client 265
WAITING 0 73
Idle jobq slave wait 259 WAITING 0
8485
Idle pmon timer 280 WAITING 0 73
Idle rdbms ipc message 267 WAITING 0
184770
Idle wakeup time manager 268 WAITING 0
40
Network SQL*Net message to client 272
WAITED SHORT TIME 1
SQL>
The V$SYSTEM_WAIT_CLASS
view gives you a breakdown of waits by wait classes, as
shown here:
SQL> SELECT wait_class,
time_waited
FROM v$system_wait_class
ORDER BY time_waited DESC;
WAIT_CLASS TIME_WAITED
-----------------------------------------------
Idle 1.0770E+11
User I/O 4728148400
Other 548221433
Concurrency 167154949
Network 56271499
Application 46336445
Commit 35742104
Configuration 11667683
System I/O 8045920
Administrative 760
Scheduler 16
11 rows selected.
SQL>
The V$SESSION_WAIT_CLASS
view shows the total time spent in each type of wait class by an
individual session. Here’s
an example:
SQL> SELECT wait_class,
time_waited
FROM v$session_wait_class
WHERE sid = 1053
ORDER BY time_waited DESC;
WAIT_CLASS TIME_WAITED
------------------------------------------
Idle 21190
User I/O 8487
Other 70
Concurrency 13
Application 0
Network 0
6 rows selected.
SQL>
The V$WAITCLASSMETRIC view
shows metric values of wait classes for the most recent
60-second interval. The
view keeps information for up to one hour. Here’s an example of using
the query:
SQL> SELECT
WAIT_CLASS#, WAIT_CLASS_ID
dbtime_in_wait,time_waited,wait_count
FROM v$waitclassmetric
ORDER BY time_waited DESC;
WAIT_CLASS# DBTIME_IN_WAIT
TIME_WAITED WAIT_COUNT
----------- --------------
----------- ----------
6 2723168908 170497 51249
0 1893977003 5832 58
8 1740759767 717 1351
5 3386400367 11 68
7 2000153315 8 52906
9 4108307767 6 99
1 4217450380 0 4
2 3290255840 0 0
3 4166625743 0 0
11 3871361733 0 0
10 2396326234 0 0
4 3875070507 0 0
12 rows selected.
SQL>
Collecting
Detailed Wait Event Information
Selecting
data from V$ dynamic performance views and interpreting them meaningfully isn’t
always so
easy to do. Because the views are dynamic, the information that they contain is
constantly
changing
as Oracle updates the underlying tables for each wait event. Also, the
wait-related
dynamic
performance views you just examined don’t provide crucial data such as bind
variable
information.
For a more detailed level of wait information, you can use one of the methods
described
in the following sections.
Method
1:Using the Oracle Event 10046 to Trace SQL Code
You can get all kinds of bind variable
information by using a special trace called the 10046 Trace,
which is much more advanced than the
SQL Trace.. The use of this trace
causes an output file to be written to
the trace directory. You can set the 10046 Trace in many ways
by specifying various levels, and each
higher level provides you with more detailed information.
(Level 12 is used in the following
case as an example only—it may give you much more information
than necessary. Level 4 gives you
detailed bind value information, and Level 8 gives you wait
information.)
ou can use the ALTER SESSION statement
as follows:
SQL> ALTER SESSION SET EVENTS
'10046 trace name context forever level 12';
Session altered.
SQL>
You can also incorporate the following
line in your init.ora file:
event = 10046 trace name context
forever, level 12
Method
2:Using the Oradebug Utility to Perform the Trace
You can use the oradebug utility as
shown in the following example:
SQL> ORADEBUG SETMYPID
Statement processed.
SQL> ORADEBUG EVENT 10046 TRACE
NAME CONTEXT FOREVER LEVEL 8;
Statement processed.
SQL>
In this example, SETMYPID indicates
that you want to trace the current session. If you want a
different session to be traced, you
replace this with SETOSPID <Process Id>.
Method
3:Using the DBMS_SYSTEM Package to Set the Trace
Use the SET_EV procedure of the
DBMS_SYSTEM package so you can set tracing on in any session,
as shown in the following example:
SQL> EXECUTE SYS.DBMS_SYSTEM.SET_EV
(9,271,10046,12,'');
PL/SQL procedure successfully
completed.
SQL>
Method
4:Using the DBMS_MONITOR Package
The DBMS_MONITOR package provides you
with an easy way to collect extended session trace
information. You enable tracing of a
user’s session using the DBMS_MONITOR.SESSION_
TRACE_ENABLE package. Here’s the
structure of the procedure:
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)
If you set the waits parameter to TRUE,
the trace will contain wait information. Similarly, setting
the binds parameter to TRUE will
provide bind information for the session being traced.
If you don’t set the SESSION_ID parameter
or set it to NULL, your own session will be traced.
Here’s how you trace your session
using the DBMS_MONITOR package:
SQL>
EXECUTE dbms_monitor.session_trace_enable (waits=>TRUE, binds=>TRUE);
Determining the Latch Hit Ratio
SQL> SELECT a.name "Latch
Name",
a.gets "Gets (Wait)",
a.misses "Misses (Wait)",
(1 - (misses / gets)) * 100 "Latch
Hit Ratio %"
FROM V$LATCH a
WHERE a.gets != 0
UNION
SELECT a.name "Latch Name",
a.gets "Gets (Wait)",
a.misses "Misses (Wait)",
100 "Latch Hit Ratio"
FROM V$LATCH a
WHERE a.gets = 0
ORDER BY
1;