Finding the slowest SQL execution of the same query
When running the same query multiple times, several questions come to mind:
- Does the query always execute in the same amount of time?
- If some executions are slower, what is the slowest execution time?
- When did the slowest exectution happen?
- What more can I find out about the slowest exectution?
All of this can be answered from data in Active Session History or ASH. The following query finds the maximum, minimum and average execution times in seconds as well as the time of the slowest execution which is given by start time and end time of the slowest exectuiton:
col av for 9999999 col mx for 9999999 col mn for 9999999 select sql_id, count(*), round(min(delta),0) mn, round(avg(delta),0) av, round(max(delta),0) mx, substr(max(times),12) max_run_time from ( select sql_id, sql_exec_id, max(delta) delta , -- lpad sets a fixed width on delta so it can be -- stripped off above with substr -- delta in "times" is just for sorting not displaying lpad(round(max(delta),0),10) || ' ' || to_char(min(start_time),'YY-MM-DD HH24:MI:SS') || ' ' || to_char(max(end_time),'YY-MM-DD HH24:MI:SS') times from ( select sql_id, sql_exec_id, cast(sample_time as date) end_time, cast(sql_exec_start as date) start_time, ((cast(sample_time as date)) - (cast(sql_exec_start as date))) * (3600*24) delta from dba_hist_active_sess_history where sql_exec_id is not null ) group by sql_id,sql_exec_id ) group by sql_id having count(*) > 10 order by mx / SQL_ID COUNT(*) MN AV MX MAX_RUN_TIME ------------- ---------- -------- -------- -------- ----------------------------------- 155vjqzjqp58f 27 0 115 786 11-04-11 07:39:47 11-04-11 07:41:20 7nf5917x3tq5x 113 0 129 791 11-04-11 01:03:19 11-03-02 04:16:09 asg774pz0kqga 11 11 225 799 11-04-14 12:20:10 11-03-02 12:18:58 1kf1jsykb1nk6 529 0 107 800 11-04-09 18:41:28 11-03-01 23:13:56 8rua4c9agcqkb 978 0 73 820 11-03-01 23:13:50 11-03-01 23:13:56 fdagtr1sdk8tn 313 0 242 841 11-04-08 21:30:31 11-04-08 21:30:38 7b5w34atn8q1h 124 0 25 898 11-03-07 20:53:17 11-03-07 20:53:23 9w7mbuv734tfy 11 30 509 954 11-04-14 09:00:55 11-03-02 04:27:33 88qxmg220db9s 23 4 357 1040 11-04-13 22:08:20 11-04-13 02:20:09 83ngzw213v0cs 302 1 207 1122 11-04-11 16:26:32 11-03-07 16:12:11 34cgtc9xkgxny 61 978 1163 1272 11-03-02 10:06:24 11-03-02 10:06:30 g5u58zpg0tuk8 97 1 62 1359 11-04-13 02:49:33 11-04-12 02:23:39 6tkqndn1tzf23 29 7 187 1370 11-04-13 06:56:43 11-03-02 06:56:54 g4wrnvdmf23b1 11 19 458 1397 11-04-14 12:22:28 11-03-02 12:21:19 bpkg6y9wvf717 31 0 189 1427 11-04-13 21:19:51 11-03-02 21:08:00 4d6m2q3ngjcv9 320 3 485 1701 11-04-10 18:00:54 11-03-01 23:10:55 882tp5sbq1tq5 17 39 367 1795 11-04-14 14:00:30 11-03-01 23:04:33 5k7vccwjr5ahd 2653 0 33 1963 11-04-12 09:06:08 11-03-01 23:10:15 44034jty9vnrg 19 2 188 1968 11-03-03 09:17:34 11-03-03 09:17:43 g9n69a23s3wxz 40 6 280 2009 11-04-08 13:47:23 11-03-03 09:37:38 ds8cz0fb8w147 161 13 274 2531 11-04-12 16:10:21 11-03-01 23:11:55 bzyny95313u12 114 0 47 2599 11-03-03 03:06:18 11-03-03 03:06:25 0fvrpk7476b7y 26 0 133 3068 11-03-07 07:57:56 11-03-07 07:58:00 1pjp66rxcj6tg 15 57 768 3106 11-04-09 17:25:21 11-03-07 08:58:26 8r5wuxk1dprhr 39 24 841 3510 11-04-14 14:00:47 11-03-02 09:54:37 0w5uu5kngyyty 21 0 442 3652 11-04-11 08:00:21 11-04-11 09:01:13 0hbv80w9ypy0n 161 0 1184 4089 11-04-12 22:26:09 11-03-02 04:36:15 71fwb4n6a92fv 49 30 677 4481 11-04-10 17:01:17 11-03-01 23:40:45 0bujgc94rg3fj 604 0 25 4929 11-04-08 10:53:34 11-04-08 12:15:43 64dqhdkkw63fd 1083 0 7 7147 11-03-07 04:01:01 11-03-07 06:00:08 990m08w8xav7s 591 0 52 7681 11-04-13 00:39:27 11-04-13 00:39:37 2n5369dsuvn5a 16 303 5727 10472 11-04-14 11:18:11 11-04-14 14:12:43 2spgk3k0f7quz 251 0 546 29607 11-04-12 12:11:47 11-04-12 12:11:48 36pd759xym9tc 12 1391 23862 37934 11-04-13 19:25:49 11-03-01 23:00:12 497wh6n7hu14f 49 0 5498 69438 11-04-12 19:01:17 11-04-13 12:03:54
We can add a histogram of execution spread to the query
col 1 for 99999 col 2 for 99999 col 3 for 9999 col 4 for 999 col 5 for 99 col av for 99999.9 col ct for 99999 col mn for 999 col av for 99999.9 with pivot_data as ( select sql_id, ct, mxdelta mx, mndelta mn, avdelta av, -- high_boundary is set to maxdelta + 1 so that -- nothing ends up in the overflow bucket -- otherwise the max value ends up in the overflow bucket width_bucket(delta,mndelta,mxdelta+1,5) as bucket , substr(times,12) max_run_time from ( select sql_id, delta, count(*) OVER (PARTITION BY sql_id) ct, max(delta) OVER (PARTITION BY sql_id) mxdelta, min(delta) OVER (PARTITION BY sql_id) mndelta, avg(delta) OVER (PARTITION BY sql_id) avdelta, max(times) OVER (PARTITION BY sql_id) times from ( select sql_id, sql_exec_id, max(delta) delta , -- lpad sets a fixed width on delta so it can be -- stripped off above with substr -- delta in "times" is just for sorting not displaying lpad(round(max(delta),0),10) || ' ' || to_char(min(start_time),'YY-MM-DD HH24:MI:SS') || ' ' || to_char(max(end_time),'YY-MM-DD HH24:MI:SS') times from ( select sql_id, sql_exec_id, cast(sample_time as date) end_time, cast(sql_exec_start as date) start_time, ((cast(sample_time as date)) - (cast(sql_exec_start as date))) * (3600*24) delta from dba_hist_active_sess_history where sql_exec_id is not null ) group by sql_id,sql_exec_id ) ) where ct > &min_repeat_executions_filter ) select * from pivot_data PIVOT ( count(*) FOR bucket IN (1,2,3,4,5)) order by mx,av; / SQL_ID CT MX MN AV MAX_RUN_TIME 1 2 3 4 5 ------------- ------ ---------- ---- -------- ----------------------------------- ------ ------ ----- ---- --- 8rua4c9agcqkb 978 820 0 72.7 11-03-01 23:13:50 11-03-01 23:13:56 830 116 21 9 2 fdagtr1sdk8tn 313 841 0 241.8 11-04-08 21:30:31 11-04-08 21:30:38 194 45 0 0 74 7b5w34atn8q1h 124 898 0 24.8 11-03-07 20:53:17 11-03-07 20:53:23 122 0 0 0 2 83ngzw213v0cs 302 1122 1 207.5 11-04-11 16:26:32 11-03-07 16:12:11 200 68 21 6 7 g5u58zpg0tuk8 97 1359 1 62.1 11-04-13 02:49:33 11-04-12 02:23:39 92 3 1 0 1 4d6m2q3ngjcv9 320 1701 3 484.7 11-04-10 18:00:54 11-03-01 23:10:55 92 168 50 9 1 5k7vccwjr5ahd 2653 1963 0 33.4 11-04-12 09:06:08 11-03-01 23:10:15 2623 15 8 4 3 ds8cz0fb8w147 161 2531 13 273.8 11-04-12 16:10:21 11-03-01 23:11:55 136 18 5 1 1 bzyny95313u12 114 2599 0 46.5 11-03-03 03:06:18 11-03-03 03:06:25 113 0 0 0 1 0hbv80w9ypy0n 161 4089 0 1183.9 11-04-12 22:26:09 11-03-02 04:36:15 27 116 9 6 3 71fwb4n6a92fv 49 4481 30 676.9 11-04-10 17:01:17 11-03-01 23:40:45 38 6 2 2 1 0bujgc94rg3fj 604 4929 0 24.7 11-04-08 10:53:34 11-04-08 12:15:43 601 1 1 0 1 64dqhdkkw63fd 1083 7147 0 7.2 11-03-07 04:01:01 11-03-07 06:00:08 1082 0 0 0 1 990m08w8xav7s 591 7681 0 51.8 11-04-13 00:39:27 11-04-13 00:39:37 587 0 0 2 2 2spgk3k0f7quz 251 29607 0 546.1 11-04-12 12:11:47 11-04-12 12:11:48 247 2 0 0 2 497wh6n7hu14f 49 69438 0 5498.2 11-04-12 19:01:17 11-04-13 12:03:54 44 1 0 1 3
Finally add the SQL_EXEC_ID of the longest running execution. This SQL_EXEC_ID can then be used to go look at the events in ASH for that particular execution
col 1 for 99999 col 2 for 99999 col 3 for 9999 col 4 for 999 col 5 for 99 col av for 99999 col ct for 99999 col mn for 999 col av for 99999.9 col longest_sql_exec_id for A10 WITH pivot_data AS ( SELECT sql_id, ct, mxdelta mx, mndelta mn, round(avdelta) av, WIDTH_BUCKET(delta_in_seconds,mndelta,mxdelta+.1,5) AS bucket , SUBSTR(times,12) max_run_time, SUBSTR(longest_sql_exec_id, 12) longest_sql_exec_id FROM ( SELECT sql_id, delta_in_seconds, COUNT(*) OVER (PARTITION BY sql_id) ct, MAX(delta_in_seconds) OVER (PARTITION BY sql_id) mxdelta, MIN(delta_in_seconds) OVER (PARTITION BY sql_id) mndelta, AVG(delta_in_seconds) OVER (PARTITION BY sql_id) avdelta, MAX(times) OVER (PARTITION BY sql_id) times, MAX(longest_sql_exec_id) OVER (PARTITION BY sql_id) longest_sql_exec_id FROM ( SELECT sql_id, sql_exec_id, MAX(delta_in_seconds) delta_in_seconds , LPAD(ROUND(MAX(delta_in_seconds),0),10) || ' ' || TO_CHAR(MIN(start_time),'YY-MM-DD HH24:MI:SS') || ' ' || TO_CHAR(MAX(end_time),'YY-MM-DD HH24:MI:SS') times, LPAD(ROUND(MAX(delta_in_seconds),0),10) || ' ' || TO_CHAR(MAX(sql_exec_id)) longest_sql_exec_id FROM ( SELECT sql_id, sql_exec_id, CAST(sample_time AS DATE) end_time, CAST(sql_exec_start AS DATE) start_time, ((CAST(sample_time AS DATE)) - (CAST(sql_exec_start AS DATE))) * (3600*24) delta_in_seconds FROM dba_hist_active_sess_history WHERE sql_exec_id IS NOT NULL ) GROUP BY sql_id,sql_exec_id ) ) where ct > &min_repeat_executions_filter and mxdelta > &min_elapsed_time ) SELECT * FROM pivot_data PIVOT ( COUNT(*) FOR bucket IN (1,2,3,4,5)) ORDER BY mx DESC,av DESC ; SQL_ID CT MX MN AV MAX_RUN_TIME LONGEST_SQ 1 2 3 4 5 ------------- ------ ---------- ---- -------- ----------------------------------- ---------- ------ ------ ----- ---- --- 2spgk3k0f7quz 251 29607 0 546.0 11-04-12 12:11:47 11-04-12 20:25:14 16781748 247 2 0 0 2 990m08w8xav7s 591 7681 0 52.0 11-04-13 00:39:27 11-04-13 02:47:28 16786685 587 0 0 2 2 64dqhdkkw63fd 1083 7147 0 7.0 11-03-07 04:01:01 11-03-07 06:00:08 16777218 1082 0 0 0 1 0bujgc94rg3fj 604 4929 0 25.0 11-04-08 10:53:34 11-04-08 12:15:43 16814628 601 1 1 0 1 0hbv80w9ypy0n 161 4089 0 1184.0 11-03-02 04:36:10 11-04-12 23:34:18 16777290 27 116 9 6 3 bzyny95313u12 114 2599 0 47.0 11-03-03 03:06:18 11-03-03 03:49:37 16781191 113 0 0 0 1 ds8cz0fb8w147 161 2531 13 274.0 11-03-01 23:11:48 11-04-12 16:10:37 16777285 136 18 5 1 1 5k7vccwjr5ahd 2653 1963 0 33.0 11-03-01 23:10:12 11-04-12 09:06:12 16778244 2623 15 8 4 3 4d6m2q3ngjcv9 320 1701 3 485.0 11-03-01 23:10:53 11-04-10 18:01:26 16777261 92 168 50 9 1 g5u58zpg0tuk8 97 1359 1 62.0 11-04-12 02:23:37 11-04-13 02:51:09 16777217 92 3 1 0 1 34cgtc9xkgxny 61 1272 978 1163.0 11-03-02 10:06:24 11-03-02 10:27:36 16777250 4 4 14 30 9
Hi Kyle,
Below is the output from one of my database:
SQL_ID CT MX MN AV MAX_RUN_TIME LONGEST_SQ 1 2 3 4 5
————- —— ———- —- ——– ———————————– ———- —— —— —– —- —
2ahhqkpm9ywfc 3 6010 430 2438.0 13-03-15 02:50:53 13-09-11 18:07:18 16777216 2 0 0 0 1
Query did not ran for 6 months. SQL_EXEC_ID is not always unique (http://blog.tanelpoder.com/2011/10/24/what-the-heck-is-the-sql-execution-id-sql_exec_id/ Please see Coskan and Tanel comments). In my case, I have only 3 distinct SQL_EXEC_ID for 180 executions.
Thanks,
Vishal
Thanks for the link to Tanel’s stuff. From what Tanel is saying the SQL_EXEC_ID will repeat across database bounces and across wraps of the counter. Nothing suprising there.
It looked like Coskan was saying there were bugs but I didn’t see any confirmation of that – maybe I skimmed the article too fast.
Does make me wonder if it’s worth adding in SQL_START_ID to the above query in your case and seeing if it helps.
like this
col 1 for 99999
col 2 for 99999
col 3 for 9999
col 4 for 999
col 5 for 99
col av for 99999
col ct for 99999
col mn for 999
col av for 99999.9
col MAX_RUN_TIME for a32
col longest_sql_exec_id for A20
WITH pivot_data AS (
SELECT
sql_id,
ct,
mxdelta mx,
mndelta mn,
round(avdelta) av,
WIDTH_BUCKET(delta_in_seconds,mndelta,mxdelta+.1,5) AS bucket ,
SUBSTR(times,12) max_run_time,
SUBSTR(longest_sql_exec_id, 12) longest_sql_exec_id
FROM (
SELECT
sql_id,
delta_in_seconds,
COUNT(*) OVER (PARTITION BY sql_id) ct,
MAX(delta_in_seconds) OVER (PARTITION BY sql_id) mxdelta,
MIN(delta_in_seconds) OVER (PARTITION BY sql_id) mndelta,
AVG(delta_in_seconds) OVER (PARTITION BY sql_id) avdelta,
MAX(times) OVER (PARTITION BY sql_id) times,
MAX(longest_sql_exec_id) OVER (PARTITION BY sql_id) longest_sql_exec_id
FROM (
SELECT
sql_id,
sql_exec_id,
MAX(delta_in_seconds) delta_in_seconds ,
LPAD(ROUND(MAX(delta_in_seconds),0),10) || ‘ ‘ ||
TO_CHAR(MIN(start_time),’YY-MM-DD HH24:MI:SS’) || ‘ ‘ ||
TO_CHAR(MAX(end_time),’YY-MM-DD HH24:MI:SS’) times,
LPAD(ROUND(MAX(delta_in_seconds),0),10) || ‘ ‘ ||
TO_CHAR(MAX(sql_exec_id)) longest_sql_exec_id
FROM ( SELECT
sql_id,
to_char(sql_exec_id)||’_’||to_char(sql_exec_start,’J’) sql_exec_id,
CAST(sample_time AS DATE) end_time,
CAST(sql_exec_start AS DATE) start_time,
((CAST(sample_time AS DATE)) –
(CAST(sql_exec_start AS DATE))) * (3600*24) delta_in_seconds
FROM
dba_hist_active_sess_history
WHERE sql_exec_id IS NOT NULL
)
GROUP BY sql_id,sql_exec_id
)
)
where ct > &min_repeat_executions_filter
and mxdelta > &min_elapsed_time
)
SELECT * FROM pivot_data
PIVOT ( COUNT(*) FOR bucket IN (1,2,3,4,5))
ORDER BY mx DESC,av DESC
;
That was it.
SQL_ID CT MX MN AV MAX_RUN_TIME LONGEST_SQL_EXEC_ID 1 2 3 4 5
————- —— ———- —- ——– ——————————– ——————– —— —— —– —- —
2ahhqkpm9ywfc 173 6010 29 532.0 13-08-20 01:02:41 13-08-20 02:42 16777216_2456525 161 9 0 2 1
:51
Thanks for quick response.
Hi kyle , How do you interpret histogram buckets ? in your example the sqlid 8rua4c9agcqkb has 978 executions and the max elapsed time for that query is 820 seconds and in histogram
We have 5 buckets and the query ran 830 times <= second and 2 times out of 978 runs ran in 5a seconds. ??
SQL_ID CT MX MN AV MAX_RUN_TIME 1 2 3 4 5
————- —— ———- —- ——– ———————————– —— —— —– —- —
8rua4c9agcqkb 978 820 0 72.7 11-03-01 23:13:50 11-03-01 23:13:56 830 116 21 9 2
Thanks
Raj
The histogram buckets 1-5 simply divide the max time into 5 intervals.
Your max time was 820, so your intervals each of a width of 820/5 = 164
bucket 1 : 0 -164 with 830 executions
bucket 2: 165- 328 with 115 executions
bucket 3: 329 – 492 with 21 executions
bucket 4: 493- 656 with 9 executions
bucket 5: 657 – 820 with 2 executions (one of which is the 820 second one)
Thanks kyle for quick response
Hi Kyle :
While this looks good to get the count, max, min time for a query ID.
Is there any way of knowing start time and end time of a particular sql_id :
For example taking your query output / results :
SQL_ID COUNT(*) MN AV MX MAX_RUN_TIME
————- ———- ——– ——– ——– ———————————–
155vjqzjqp58f 27 0 115 786 11-04-11 07:39:47 11-04-11 07:41:20
So :
1) Can i know the start and end times of this SQL_ID which shows as run 27 times.
2) Obviously along with this, other information like I/O , rows-fetched, cpu time, and also the cost.
@Sai: in your example the query has been run 27 times. You could output the start and end for all 27 but that would be a lot of output. The last query above gives the start and end for the longest which is the one I generally find of the most interest.
You could of course add the I/O, CPU and such for each execution. I haven’t looked into it, but I imagine you could also add the rows fetched and the cost as well. Seems do-able.
Hi Kyle,
I am getting count(no.of executions) mismatches.
SQL> select sum(count(*)) from DBA_HIST_ACTIVE_SESS_HISTORY where sql_id=’0aj463w5jz8bw’ group by sql_id,sql_exec_id;
SUM(COUNT(*))
————-
79402
below shows only 4868. I used where ct > &min_repeat_executions_filter (1)
and mxdelta > &min_elapsed_time (0)
SQL_ID CT MX MN AV MAX_RUN_TIME LONGEST_SQ 1 2 3 4 5
————- —— ——– —- ——– ——————————————————————————————————————————————————————————————————————————————————————– ———- —— —— —– —- —
0aj463w5jz8bw 4868 2865 0 156.0 14-12-09 09:26:40 14-12-09 10:14:25 16795025 4475 326 62 0 5
@anthony
If you want to send me an export of your DBA_HIST_ACTIVE_SESS_HISTORY I’ll take a look at it. Your second query is slightly off, though not sure if that could explain the difference.
SQL> USED v$active_session_history in your query,it shows execution count as 7 which is right.
SQL_ID COUNT(*) MN AV MX MAX_RUN_TIME
————- ———- ——– ——– ——– ——————————————-
1gqww8makf6w5 7 2 4 6 14-12-12 13:06:39 14-12-12 13:06:45
— again with DBA_HIST_ACTIVE_SESS_HISTORY in your query, the execution count shows 2
SQL_ID COUNT(*) MN AV MX MAX_RUN_TIME
————- ———- ——– ——– ——– ——————————————-
1gqww8makf6w5 2 5 6 6 14-12-12 13:05:44 14-12-12 13:05:50
SQL> @sqlstat 1gqww8makf6w5 from DBA_HIST_SQLSTAT shows 7 executions (4 and 3 in two snapshot intervals)
INTERVAL SQL_ID PLAN_HASH_VALUE EXECUTIONS ELAPSED_SEC ELAPSED_PER_EXEC_SEC
——————– ————- ————— ———- ———– ——————–
12-12-2014 12:14 1gqww8makf6w5 3724264953 4 9 2
12-12-2014 13:00 1gqww8makf6w5 3724264953 3 17 6
Correct me, if i am wrong. Your query’s execution count is not matching with the actual number of executions.
@khailey
Could you please delete the contents dbname & hostname in the SQL prompt from comment# 11 as it has sensitive info? sorry for the inconvenience.
@khailey
SQL> select sum(count(*)) from DBA_HIST_ACTIVE_SESS_HISTORY where sql_id=’0aj463w5jz8bw’ and sql_exec_id is not null group by sql_id,sql_exec_start,sql_exec_id;
SUM(COUNT(*))
————-
80144
SQL_ID CT MX MN AV MAX_RUN_TIME LONGEST_SQ 1 2 3 4 5
————- —— ———- —- ——– ——————————————————————————————————————————————————————————————————————————————————————– ———- —— —— —– —- —
0aj463w5jz8bw 4906 2865 0 156.0 14-12-09 09:26:40 14-12-09 10:14:25 16795025 4511 328 62 0 5
Still there is a difference.
Hi Kyle,
I guess the algorithm behind flushing 1/10 of the sample to historical tables could be the root cause as why there are differences in the number of executions.A simple test reveals that not all distinct SQL_EXEC_IDs are flushed out to AWR tables.
SQL> select distinct sql_exec_id from V$ACTIVE_SESSION_HISTORY where sql_id=’1gqww8makf6w5′ order by sql_exec_id; –> Actual number of executions
SQL_EXEC_ID
———–
16777216
16777217
16777218
16777219
16777220
16777221
16777222
16777223
16777224
SQL> select distinct sql_exec_id from DBA_HIST_ACTIVE_SESS_HISTORY where sql_id=’1gqww8makf6w5′ order by sql_exec_id;
SQL_EXEC_ID
———–
16777220
16777221
16777223
16777224
I have also observed that the flushing algorithm is not giving weightage to number of samples specific to a sql execution.In my test,as you can see below both sql_exec_ids 16777222 and 16777224 have 5 samples each in ASH.But 16777222 is missing from AWR.
SQL> select sql_exec_id,count(*) from V$ACTIVE_SESSION_HISTORY where sql_id=’1gqww8makf6w5′ group by sql_exec_id;
SQL_EXEC_ID COUNT(*)
———– ———-
16777222 5 <<<
16777221 6
16777223 6
16777220 6
16777217 3
16777224 5 <<<
16777219 2
16777218 3
16777216 3
But your thought process deserves more credit.Keep up the good work that you're doing.
Thanks
Antony
yes, v$active_session_history and dba_hist_active_sess_history are different
but in your comparison you are using dba_hist_active_sess_history for both so the results should be the same
again you can send me an export of dba_hist_active_sess_history and I will look at it.
Comparing on my system they are eactly the same
Hi Kyle,
I sent you (GMAIL) my dba_hist_active_session history for one SQL_ID.The file will have insert statments to a table called DASH.
Thanks again for checking this one.
@Antony,
I think what you want is
select count(distinct sql_exec_id||sql_exec_start) from DASH where sql_id=’0aj463w5jz8bw’;
to get the number of distinct executions for a particular sql_id;
COUNT(DISTINCTSQL_EXEC_ID||SQL_EXEC_START)
——————————————
5105
compares to
SQL_ID CT MX MN AV MAX_RUN_TIME LONGEST_SQL_EXEC_ID 1 2 3 4 5
————- —— ———- —- ——– ———————————– ——————– —— —— —– —- —
0aj463w5jz8bw 5105 85420 856 31997.0 14-10-24 00.00.00 14-10-24 23.43.40 16780545_2456955 1691 1312 1094 575 ###
Thanks Kyle!
Most of the variations in sql execution run time caused by change in execution plan or due to bind variable peeking.looking for the possibilities of drilling down further with a bind values associated with long run.
@anthony – yes adding bind variable capturing would be nice but I don’t think there is a efficient way to capture all the bind variables. AFAIK, other than tracing, one can only capture a some of the bind variables.
I am amazed with your thought process of adding buckets in this sql. Another observation which I came across today while using the SQL is that there are SQLs which might not be completed for ever or killed after n minutes of executions(we have one in our shop for SQL queries from sql developer) but still contributed towards max_run_time.I had to compare the sql_id with executions_delta of DBA_HIST_SQLSTAT by filtering executions_delta>0.
I’ve included the version that we use below. We just tracked down a problem in our java code that was due to dba_hist_active_sess_history.sql_exec_start being NULL. This seems to be very rare. (We execute this query as part of our instrumentation at the end of every performance test and have been doing so since shortly after I saw your blog post.) The NULL screwed up our analysis of the encoded string for max_run_time. We added a WHERE clause to filter out rows that have a NULL value.
Jerry
WITH pivot_data AS
(SELECT sql_id , instance_number , ct , mxdelta mx , mndelta mn , avdelta av ,
width_bucket ( delta_in_seconds,mndelta-.1,mxdelta+.1,5 ) AS bucket ,
SUBSTR( times,12 ) max_run_time ,
SUBSTR( longest_sql_exec_id, 12 ) longest_sql_exec_id ,
SUBSTR( longest_sql_exec_id_action, 12 ) longest_sql_exec_id_action,
SUBSTR( longest_sql_exec_id_client_id, 12 ) longest_sql_exec_id_client_id
FROM
(SELECT sql_id , instance_number , delta_in_seconds ,
COUNT (*) OVER ( PARTITION BY sql_id, instance_number ) ct ,
MAX ( delta_in_seconds ) OVER ( PARTITION BY sql_id, instance_number ) mxdelta ,
MIN ( delta_in_seconds ) OVER ( PARTITION BY sql_id, instance_number ) mndelta ,
AVG ( delta_in_seconds ) OVER ( PARTITION BY sql_id, instance_number ) avdelta ,
MAX ( times ) OVER ( PARTITION BY sql_id, instance_number ) times ,
MAX ( longest_sql_exec_id ) OVER ( PARTITION BY sql_id, instance_number ) longest_sql_exec_id ,
MAX ( longest_sql_exec_id_action ) OVER ( PARTITION BY sql_id, instance_number ) longest_sql_exec_id_action,
MAX ( longest_sql_exec_id_client_id ) OVER ( PARTITION BY sql_id, instance_number ) longest_sql_exec_id_client_id
FROM
(SELECT sql_id , sql_exec_id , instance_number , MAX (delta_in_seconds) delta_in_seconds ,
LPAD( ROUND ( MAX ( delta_in_seconds ) ,0 ) ,10)
|| ‘ ‘
|| TO_CHAR ( MIN ( start_time ) , ‘YYYY-MM-DD HH24:MI:SS’ )
|| ‘$’
|| TO_CHAR ( MAX ( end_time ) , ‘YYYY-MM-DD HH24:MI:SS’ ) times,
LPAD( ROUND ( MAX ( delta_in_seconds ) ,0 ) ,10)
|| ‘ ‘
|| TO_CHAR ( MAX ( sql_exec_id ) ) longest_sql_exec_id,
LPAD( ROUND ( MAX ( delta_in_seconds ) ,0 ) ,10)
|| ‘ ‘
|| TO_CHAR ( MAX ( action ) ) longest_sql_exec_id_action,
LPAD( ROUND ( MAX ( delta_in_seconds ) ,0 ) ,10)
|| ‘ ‘
|| TO_CHAR ( MAX ( client_id ) ) longest_sql_exec_id_client_id
FROM
(SELECT sql_id , sql_exec_id , instance_number , action , client_id ,
CAST ( sample_time AS DATE ) end_time , CAST ( sql_exec_start AS DATE ) start_time,
( ( CAST ( sample_time AS DATE ) ) – ( CAST ( sql_exec_start AS DATE ) ) ) * ( 3600*24 ) delta_in_seconds
FROM dba_hist_active_sess_history
WHERE sql_exec_id IS NOT NULL
AND module = ‘BillingCenter_MKTG’
AND snap_id BETWEEN 375 AND 382
)
GROUP BY sql_id , sql_exec_id, instance_number
)
)
)
SELECT sql_id , instance_number , ct , mx , mn , av , max_run_time ,
longest_sql_exec_id , longest_sql_exec_id_action , longest_sql_exec_id_client_id, “1” , “2” , “3” , “4” , “5”
FROM pivot_data PIVOT ( COUNT (*) FOR bucket IN ( 1,2,3,4,5 ) )
ORDER BY mx DESC , av DESC;