-
Notifications
You must be signed in to change notification settings - Fork 334
Expand file tree
/
Copy pathsqlflame.sql
More file actions
100 lines (89 loc) · 3.82 KB
/
sqlflame.sql
File metadata and controls
100 lines (89 loc) · 3.82 KB
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
-- Copyright 2018 Tanel Poder. All rights reserved. More info at https://tanelpoder.com
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
--------------------------------------------------------------------------------
--
-- Name: sqlflame.sql
--
-- Purpose: Demo script for displaying execution plan profile as a flame chart
--
-- Usage: @sqlflame.sql <sqlid> <child#>
-- Note that you'll need to download Brendan Gregg's flamegraph.pl
-- https://github.com/brendangregg/FlameGraph and make sure that it's
-- in your PATH (or edit this script to use it from a hardcoded location)
--
-- Note that you'll have to replace HOST OPEN with HOST START in the
-- end of this file if you're using sqlplus client on Windows
--
-- Author: Tanel Poder - https://tanelpoder.com
--
-- Examples: https://tanelpoder.com/posts/visualizing-sql-plan-execution-time-with-flamegraphs/
-- https://tanelpoder.com/posts/sql-plan-flamegraph-loop-row-counts/
--
-- Other: This is an early version mostly meant as a proof of concept for
-- illustrating that a modern RDBMS SQL execution plan profile
-- can be treated just like any code profile (FlameGraphs were
-- initially used for process stack profiling)
--
-- This script currently relies on the V$SQL_PLAN_STATISTICS_ALL source
-- so you'll need to run your query with statistics_level=all or
-- with the GATHER_PLAN_STATISTICS hint.
--
-- Credits: Brendan Gregg invented and popularized FlameGraphs, if you want to
-- understand their logic better, read the articles at:
-- http://www.brendangregg.com/flamegraphs.html
--
--------------------------------------------------------------------------------
SET HEADING OFF LINESIZE 32767 PAGESIZE 0 TRIMSPOOL ON TRIMOUT ON LONG 9999999 VERIFY OFF LONGCHUNKSIZE 100000 FEEDBACK OFF APPINFO OFF
PROMPT
PROMPT -- SQLFlame 0.4 by Tanel Poder ( https://tanelpoder.com )
SET TERMOUT OFF
WITH sq AS (
SELECT /*+ MATERIALIZE */
sp.id, sp.parent_id, sp.operation, sp.options
, sp.object_owner, sp.object_name, ss.last_elapsed_time, ss.elapsed_time, ss.last_starts, ss.last_output_rows
FROM v$sql_plan_statistics_all ss INNER JOIN
v$sql_plan sp
ON (
sp.sql_id=ss.sql_id
AND sp.child_number=ss.child_number
AND sp.address=ss.address
AND sp.id=ss.id
)
AND sp.sql_id='&1'
AND sp.child_number=&2
), deltas AS (
SELECT par.id, par.elapsed_time - SUM(chi.elapsed_time) self_elapsed_time
FROM sq par LEFT OUTER JOIN
sq chi
ON chi.parent_id = par.id
GROUP BY par.id, par.elapsed_time
), combined AS (
SELECT sq.id, sq.parent_id, sq.operation, sq.options
, sq.object_owner, sq.object_name, sq.last_elapsed_time, sq.elapsed_time, sq.last_starts, sq.last_output_rows
, NVL(deltas.self_elapsed_time, sq.elapsed_time) self_elapsed_time
FROM
sq, deltas
WHERE
sq.id = deltas.id
)
SELECT
'0 - SELECT STATEMENT'||TRIM(SYS_CONNECT_BY_PATH(id||' - '||operation||NVL2(options,' '||options,NULL)
||NVL2(object_owner||object_name, ' ['||object_owner||'.'||object_name||']', NULL)
||' starts='||last_starts|| ' rows='||last_output_rows, ';'))||' '||TRIM(ROUND(self_elapsed_time/1000))
FROM
combined
CONNECT BY
parent_id = PRIOR id
START WITH parent_id = 0
ORDER BY
id ASC
.
spool sqlflame_stacks.txt
/
spool off
SET TERMOUT ON HEADING ON PAGESIZE 5000 LINESIZE 999 FEEDBACK ON
HOST flamegraph.pl --countname=Milliseconds --title="sql_id=&1" sqlflame_stacks.txt > sqlflame_&1..svg
-- Windows
-- HOST START sqlflame_&1..svg
-- MacOS
HOST OPEN sqlflame_&1..svg