-
Notifications
You must be signed in to change notification settings - Fork 316
/
Copy pathwaitprof.sql
127 lines (121 loc) · 6.05 KB
/
waitprof.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- File name: waitprof.sql ( Session Wait Profiler )
-- Purpose: Sample V$SESSION_WAIT at high frequency and show resulting
-- session wait event and parameter profile by session
--
-- Author: Tanel Poder
-- Copyright: (c) http://www.tanelpoder.com
--
-- Usage: @waitprof <print|noprint> <sid> <e[123s]> <#samples>
--
-- <print|noprint>
-- - whether to print P2,P3,SEQ# values or not
--
-- <sid> - session ID of session to sample
--
-- <[e123s]> - sample grouping
-- e - group by event name
-- 1 - group by P1 of v$session_wait event
-- 2 - group by P2
-- 3 - group by P3
-- s - group by SEQ#
--
-- <#samples> - how many samples to take (a modern CPU can take
-- tens of thousands to low hundreds of k samples
-- per second)
--
-- Examples:
-- @waitprof noprint 350 e 1000000 -- take million samples, group by event only
-- @waitprof print 350 e123 500000 -- take 500k samples, group by event,p1,p2,p3
-- @waitprof print 350 e3 1000000 -- take million samples, group by event,p3
-- @waitprof print 350 es 1000000 -- take million samples, group by event,seq#
--
-- Other:
-- The sampling relies on NESTED LOOP join method and having
-- V$SESSION_WAIT as the inner (probed) table. Note that on 9i
-- you may need to run this script as SYS as it looks like otherwise
-- the global USE_NL hint is not propagated down to X$ base tables
--
-- If sampling always reports a single distinct event even though
-- many different events (or parameter values) are expected then
-- the execution plan used is not right.
--
--------------------------------------------------------------------------------
DEF _swp_print=&1
DEF _swp_sid=&2
DEF _swp_p123=&3
DEF _swp_samples=&4
col sw_event head EVENT for a35 truncate
col sw_p1transl head P1TRANSL for a42
col sw_sid head SID for 999999
col swp_p1 head P1 for a26 word_wrap
col swp_p2 head P2 for a16 word_wrap &_swp_print
col swp_p3 head P3 for a16 word_wrap &_swp_print
col swp_seq# head SEQ# &_swp_print
col pct_total_samples head "% Total|Time" format 999.99
col waitprof_total_ms head "Total Event|Time ms" format 9999999.999
col dist_events head Distinct|Events
col average_samples head Average|Samples
col waitprof_avg_ms head "Avg time|ms/Event" format 99999.999
prompt
prompt -- WaitProf 1.04 by Tanel Poder ( http://www.tanelpoder.com )
WITH
t1 AS (SELECT hsecs FROM v$timer),
samples AS (
SELECT /*+ ORDERED NO_MERGE USE_NL(sw.gv$session_wait.s) */
s.sid sw_sid,
CASE WHEN sw.state = 'WAITING' THEN 'WAITING' ELSE 'WORKING' END AS state,
CASE WHEN sw.state = 'WAITING' THEN event ELSE 'On CPU / runqueue' END AS sw_event,
CASE WHEN sw.state = 'WAITING' AND '&_swp_p123' LIKE '%1%' THEN sw.p1text || '= ' || CASE WHEN (LOWER(sw.p1text) LIKE '%addr%' OR sw.p1 >= 536870912) THEN RAWTOHEX(sw.p1raw) ELSE TO_CHAR(sw.p1) END ELSE NULL END swp_p1,
CASE WHEN sw.state = 'WAITING' AND '&_swp_p123' LIKE '%2%' THEN sw.p2text || '= ' || CASE WHEN (LOWER(sw.p2text) LIKE '%addr%' OR sw.p2 >= 536870912) THEN RAWTOHEX(sw.p2raw) ELSE TO_CHAR(sw.p2) END ELSE NULL END swp_p2,
CASE WHEN sw.state = 'WAITING' AND '&_swp_p123' LIKE '%3%' THEN sw.p3text || '= ' || CASE WHEN (LOWER(sw.p3text) LIKE '%addr%' OR sw.p3 >= 536870912) THEN RAWTOHEX(sw.p3raw) ELSE TO_CHAR(sw.p3) END ELSE NULL END swp_p3,
CASE WHEN LOWER('&_swp_p123') LIKE '%s%' THEN sw.seq# ELSE NULL END seq#,
COUNT(*) total_samples,
COUNT(DISTINCT seq#) dist_events,
TRUNC(COUNT(*)/COUNT(DISTINCT seq#)) average_samples
FROM
( SELECT /*+ NO_MERGE */ TO_NUMBER(&_swp_sid) sid FROM
(SELECT rownum r FROM dual CONNECT BY ROWNUM <= 1000) a,
(SELECT rownum r FROM dual CONNECT BY ROWNUM <= 1000) b,
(SELECT rownum r FROM dual CONNECT BY ROWNUM <= 1000) c
WHERE ROWNUM <= &_swp_samples
) s,
v$session_wait sw
WHERE
s.sid = sw.sid
GROUP BY
s.sid,
CASE WHEN sw.state = 'WAITING' THEN 'WAITING' ELSE 'WORKING' END,
CASE WHEN sw.state = 'WAITING' THEN event ELSE 'On CPU / runqueue' END,
CASE WHEN sw.state = 'WAITING' AND '&_swp_p123' LIKE '%1%' THEN sw.p1text || '= ' || CASE WHEN (LOWER(sw.p1text) LIKE '%addr%' OR sw.p1 >= 536870912) THEN RAWTOHEX(sw.p1raw) ELSE TO_CHAR(sw.p1) END ELSE NULL END,
CASE WHEN sw.state = 'WAITING' AND '&_swp_p123' LIKE '%2%' THEN sw.p2text || '= ' || CASE WHEN (LOWER(sw.p2text) LIKE '%addr%' OR sw.p2 >= 536870912) THEN RAWTOHEX(sw.p2raw) ELSE TO_CHAR(sw.p2) END ELSE NULL END,
CASE WHEN sw.state = 'WAITING' AND '&_swp_p123' LIKE '%3%' THEN sw.p3text || '= ' || CASE WHEN (LOWER(sw.p3text) LIKE '%addr%' OR sw.p3 >= 536870912) THEN RAWTOHEX(sw.p3raw) ELSE TO_CHAR(sw.p3) END ELSE NULL END,
CASE WHEN LOWER('&_swp_p123') LIKE '%s%' THEN sw.seq# ELSE NULL END
ORDER BY
CASE WHEN LOWER('&_swp_p123') LIKE '%s%' THEN -seq# ELSE total_samples END DESC
),
t2 AS (SELECT hsecs FROM v$timer)
SELECT /*+ ORDERED */
s.sw_sid,
s.state,
s.sw_event,
s.swp_p1,
s.swp_p2,
s.swp_p3,
s.seq# swp_seq#,
s.total_samples / &_swp_samples * 100 pct_total_samples,
(t2.hsecs - t1.hsecs) * 10 * s.total_samples / &_swp_samples waitprof_total_ms,
s.dist_events,
-- s.average_samples,
(t2.hsecs - t1.hsecs) * 10 * s.total_samples / dist_events / &_swp_samples waitprof_avg_ms
FROM
t1,
samples s,
t2
/
--UNDEF _swp_sid=&1
--UNDEF _swp_p123=&2
--UNDEF _swp_samples=&3