Obtaining and Interpreting Execution Plans using DBMS_XPLAN

Download Report

Transcript Obtaining and Interpreting Execution Plans using DBMS_XPLAN

Obtaining and Interpreting
Execution Plans using
DBMS_XPLAN
David Kurtz
Go-Faster Consultancy Ltd.
[email protected]
www.go-faster.co.uk
Who Am I?
• Oracle Database Specialist
– Independent consultant
• System Performance
tuning
• Book
– www.psftdba.com
– PeopleSoft ERP
– Oracle RDBMS
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
2
Resources
• If you can’t hear me say so now.
• Please feel free to ask questions as we go
along.
• The presentation is available from
• Conference website
• www.go-faster.co.uk
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
3
My Motivation
• Performance problems are instinctively
routed to the DBA
• SQL Trace can locate a database problem
• Execution plan will show you what Oracle
is doing.
• Many problems are caused by ‘poor SQL’
• I often have to rewrite the SQL.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
4
Your Motivation
• How to ask your DBA the right questions.
• How to answer some of those questions
yourself
• How to find out how the database is
executing a problematic SQL statement
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
5
Caveat
• I cannot, in one session, cover everything
you need to know.
• But I can give you enough to get started on
your own.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
6
DBA’s Chief Weapons in the
Performance Fight with Development
• Surprise and Fear
– “Surprise! Surprise! The application runs
slowly”
– “I’m afraid I can’t do anything about it. It’s a
problem with the application code.”
• It doesn’t have to be like this.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
7
Agenda
• SQL Trace
• Execution Plans
–
–
–
–
Explain Plan For
DBMS_XPLAN
AWR
Licensing
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
8
What is SQL trace?
• Oracle shadow process writes a file on the
database server
• Trace file contains
–
–
–
–
User and recursive SQL statements
Execution plan, physical & logical reads
Timing information
Wait and bind information (optional)
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
9
What’s the advantage of SQL Trace?
• You know how long each statement took to
execute
– Not just an estimate of how long
• The execution plan is what really happened
• You can find out how long each line of an
execution plan took to execute
– So you know where in the plan the problem is
located.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
10
What’s the problem with SQL Trace?
• If you’re not the DBA:
– The trace file is on the database server
• udump/bdump directories
– It is usually only readable by members of the
DBA group.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
11
What’s the problem with SQL Trace?
• Reactive
– Run process with trace and respond to what
happened.
• And sometimes
– You don’t get the execution plan because the
plan is only written to the trace file when the
cursor is closed.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
12
Alternatives to Trace
• Explain Plan For
• DBMS_XPLAN
• Assumption:
– You know which SQL statement is your
problem!
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
13
Example: Two HR tables
• PS_NAMES
Name
----------------------EMPLID*
NAME_TYPE
EFFDT
EFF_STATUS
COUNTRY_NM_FORMAT
NAME
…
DBMS_XPLAN
Null?
-------NOT NULL
NOT NULL
NOT NULL
NOT NULL
NOT NULL
NOT NULL
• PS_DEPT_TBL
Type
-----------VARCHAR2(11)
VARCHAR2(3)
DATE
VARCHAR2(1)
VARCHAR2(3)
VARCHAR2(50)
Name
----------------------SETID*
DEPTID*
EFFDT*
EFF_STATUS
DESCR
DESCRSHORT
…
Null?
-------NOT NULL
NOT NULL
NOT NULL
NOT NULL
NOT NULL
NOT NULL
UKOUG2008 ©www.go-faster.co.uk
Type
-----------VARCHAR2(5)
VARCHAR2(10)
DATE
VARCHAR2(1)
VARCHAR2(30)
VARCHAR2(10)
14
A sample SQL
SELECT
d.setid, d.deptid, d.descr,
n.emplid, n.name
FROM
ps_dept_tbl d, ps_names n
WHERE
d.effdt = (
SELECT
MAX(d1.effdt)
FROM
ps_dept_tbl d1
WHERE
d1.setid = d.setid
AND
d1.deptid = d.deptid
AND
d1.effdt <= SYSDATE)
AND
d.eff_status = 'A'
AND
n.emplid = d.manager_id
/
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
15
Explain Plan For
• Writes to plan_table table
– This is the way we used to do it up to Oracle 8i
EXPLAIN PLAN
SET statement_id = 'TST‘
INTO plan_table
FOR
<SQL>
/
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
16
Explain Plan For
• Then you had to query the plan table
SELECT id, parent_id,
lpad(' ', 2*(level-1))||operation||'
'||options||' '||object_name||' '||
decode(id, 0, 'Cost = '||position) query_plan
FROM plan_table
START WITH id = 0
AND statement_id = 'TST'
CONNECT BY prior id = parent_id
AND statement_id = 'TST'
;
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
17
Explain Plan For
• And you get an execution plan with a cost
ID
P Query Plan
--- --- -----------------------------------------0
SELECT STATEMENT
Cost = 13
1
0
NESTED LOOPS
2
1
HASH JOIN
3
2
TABLE ACCESS FULL PS_DEPT_TBL
4
2
VIEW VW_SQ_1
5
4
HASH GROUP BY
6
5
INDEX FAST FULL SCAN PS1DEPT_TBL
7
1
TABLE ACCESS BY INDEX ROWID PS_NAMES
8
7
INDEX RANGE SCAN PS_NAMES
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
18
Explain Plan For
• Then you had to query the plan table
SELECT id, parent_id,
lpad(' ', 2*(level-1))||operation||' '||options||'
'||object_name||' '||
decode(id, 0, 'Cost = '||position) query_plan
FROM plan_table
START WITH id = 0
AND statement_id = 'TST'
CONNECT BY prior id = parent_id
AND statement_id = 'TST'
;
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
19
DBMS_XPLAN
• Oracle supplied package procedure
– Documented in PL/SQL Package and Types
Reference manual.
•
•
•
•
•
DISPLAY – 9i
DISPLAY_CURSOR – 10g
DISPLAY_AWR -10g
DISPLAY_SQLSET – 10g
DISPLAY_SQL_PLAN_BASELINE – 11g
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
20
DBMS_XPLAN.DISPLAY
• Displays contents of the plan table
– Most recently explained statement
– Or a named statement
• Available in Oracle 9i
– No licence restrictions
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
21
DBMS_XPLAN.DISPLAY
• Usage
DBMS_XPLAN.DISPLAY
( table_name
IN VARCHAR2
DEFAULT 'PLAN_TABLE'
, statement_id IN VARCHAR2 DEFAULT NULL
, format
IN VARCHAR2 DEFAULT 'TYPICAL'
, filter_preds IN VARCHAR2 DEFAULT NULL);
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
22
DBMS_XPLAN.DISPLAY
• Formats
– BASIC: basic execution plan, no metrics
– TYPICAL: default. Most of the relavent information
– SERIAL: like typical, but without any parallel
execution information
– ALL: like typical but also include projection, alias and
remote SQL.
– ADVANCED: like all but also includes the OUTLINE
• Not in the Oracle 10g documentation, but it works on 10g
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
23
DBMS_XPLAN.DISPLAY
SELECT * FROM
table(dbms_xplan.display());
• Autotrace in SQL*Plus 10 now uses
dbms_xplan.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
24
select * from
table( dbms_xplan.display(
null, null, 'TYPICAL'));
Plan hash value: 454993881
-------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
2 |
176 |
13 (16)| 00:00:01 |
|
1 | NESTED LOOPS
|
|
2 |
176 |
13 (16)| 00:00:01 |
|* 2 |
HASH JOIN
|
|
1 |
65 |
11 (19)| 00:00:01 |
|* 3 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
330 | 14850 |
6
(0)| 00:00:01 |
|
4 |
VIEW
| VW_SQ_1
|
660 | 13200 |
4 (25)| 00:00:01 |
|
5 |
HASH GROUP BY
|
|
660 | 13860 |
4 (25)| 00:00:01 |
|* 6 |
INDEX FAST FULL SCAN
| PS1DEPT_TBL |
660 | 13860 |
3
(0)| 00:00:01 |
|
7 |
TABLE ACCESS BY INDEX ROWID| PS_NAMES
|
2 |
46 |
2
(0)| 00:00:01 |
|* 8 |
INDEX RANGE SCAN
| PS_NAMES
|
2 |
|
1
(0)| 00:00:01 |
-------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access("D"."EFFDT"="VW_COL_1" AND SYS_OP_DESCEND("D"."EFFDT")=SYS_OP_DESCEND(
"VW_COL_1") AND "SETID"="D"."SETID" AND "DEPTID"="D"."DEPTID")
3 - filter("D"."EFF_STATUS"='A')
6 - filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT"))<=SYSDATE@! AND
SYS_OP_DESCEND("EFFDT")>=SYS_OP_DESCEND(SYSDATE@!))
8 - access("N"."EMPLID"="D"."MANAGER_ID")
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
25
More Formats
• `ROWS - if relevant, shows the number of rows estimated by the
optimizer
• BYTES - if relevant, shows the number of bytes estimated by the
optimizer
• COST - if relevant, shows optimizer cost information
• PARTITION - if relevant, shows partition pruning information
• PARALLEL - if relevant, shows PX information (distribution method
and table queue information)
• PREDICATE - if relevant, shows the predicate section
• PROJECTION -if relevant, shows the projection section
• ALIAS - if relevant, shows the "Query Block Name / Object Alias"
section
• REMOTE - if relevant, shows the information for distributed query
(for example, remote from serial distribution and remote SQL)
• NOTE - if relevant, shows the note section of the explain plan
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
26
table( dbms_xplan.display(
null, null, 'TYPICAL,-BYTES'));
select * from
Plan hash value: 454993881
-----------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Cost (%CPU)| Time
|
-----------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
2 |
13 (16)| 00:00:01 |
|
1 | NESTED LOOPS
|
|
2 |
13 (16)| 00:00:01 |
|* 2 |
HASH JOIN
|
|
1 |
11 (19)| 00:00:01 |
|* 3 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
330 |
6
(0)| 00:00:01 |
|
4 |
VIEW
| VW_SQ_1
|
660 |
4 (25)| 00:00:01 |
|
5 |
HASH GROUP BY
|
|
660 |
4 (25)| 00:00:01 |
|* 6 |
INDEX FAST FULL SCAN
| PS1DEPT_TBL |
660 |
3
(0)| 00:00:01 |
|
7 |
TABLE ACCESS BY INDEX ROWID| PS_NAMES
|
2 |
2
(0)| 00:00:01 |
|* 8 |
INDEX RANGE SCAN
| PS_NAMES
|
2 |
1
(0)| 00:00:01 |
-----------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access("D"."EFFDT"="VW_COL_1" AND SYS_OP_DESCEND("D"."EFFDT")=SYS_OP_DESCEND(
"VW_COL_1") AND "SETID"="D"."SETID" AND "DEPTID"="D"."DEPTID")
3 - filter("D"."EFF_STATUS"='A')
6 - filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT"))<=SYSDATE@! AND
SYS_OP_DESCEND("EFFDT")>=SYS_OP_DESCEND(SYSDATE@!))
8 - access("N"."EMPLID"="D"."MANAGER_ID")
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
27
select * from
table( dbms_xplan.display(
null, null, ‘ALL'));
• Additional Information
Query Block Name / Object Alias (identified by operation id):
------------------------------------------------------------1
3
4
5
6
7
8
-
SEL$C772B8D1
SEL$C772B8D1
SEL$683B0107
SEL$683B0107
SEL$683B0107
SEL$C772B8D1
SEL$C772B8D1
DBMS_XPLAN
/ D@SEL$1
/ VW_SQ_1@SEL$7511BFD2
/ D1@SEL$2
/ N@SEL$1
/ N@SEL$1
UKOUG2008 ©www.go-faster.co.uk
28
Specify Query Block Names
SELECT /*+QB_NAME(MAIN_QUERY)*/
d.setid, d.deptid, d.descr, n.emplid, n.name
FROM
ps_dept_Tbl d, ps_names n
WHERE d.effdt = (
SELECT /*+QB_NAME(DEPT_SUBQUERY)*/ MAX(d1.effdt)
FROM
ps_dept_tbl d1
WHERE d1.setid = d.setid
AND
d1.deptid = d.deptid
AND
d1.effdt <= SYSDATE
)
AND
d.eff_status = 'A'
AND
n.emplid = d.manager_id
/
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
29
select * from
table( dbms_xplan.display(
null, null, ‘ALL'));
• Additional Information
Query Block Name / Object Alias (identified by operation id):
------------------------------------------------------------1
3
4
5
6
7
8
-
SEL$3787FDDA
SEL$3787FDDA
SEL$71F31171
SEL$71F31171
SEL$71F31171
SEL$3787FDDA
SEL$3787FDDA
DBMS_XPLAN
/ D@MAIN_QUERY
/ VW_SQ_1@SEL$4A7F38AA
/ D1@DEPT_SUBQUERY
/ N@MAIN_QUERY
/ N@MAIN_QUERY
UKOUG2008 ©www.go-faster.co.uk
30
select * from
table( dbms_xplan.display(
null, null, ‘ALL'));
• Additional Information
Column Projection Information (identified by operation id):
----------------------------------------------------------1 - (#keys=0) "D"."SETID"[VARCHAR2,5], "D"."DEPTID"[VARCHAR2,10],
"D"."DESCR"[VARCHAR2,30], "N"."EMPLID"[VARCHAR2,11], "N"."NAME"[VARCHAR2,50]
2 - (#keys=4) "D"."SETID"[VARCHAR2,5], "D"."DEPTID"[VARCHAR2,10],
"D"."DESCR"[VARCHAR2,30], "D"."MANAGER_ID"[VARCHAR2,11]
3 - "D"."SETID"[VARCHAR2,5], "D"."DEPTID"[VARCHAR2,10], "D"."EFFDT"[DATE,7],
"D"."DESCR"[VARCHAR2,30], "D"."MANAGER_ID"[VARCHAR2,11]
4 - "VW_COL_1"[DATE,7], "SETID"[VARCHAR2,5], "DEPTID"[VARCHAR2,10]
5 - (#keys=2) "D1"."SETID"[VARCHAR2,5], "D1"."DEPTID"[VARCHAR2,10],
MAX(SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT")))[7]
6 - "D1"."SETID"[VARCHAR2,5], "D1"."DEPTID"[VARCHAR2,10],
SYS_OP_DESCEND("EFFDT")[RAW,12]
7 - "N"."EMPLID"[VARCHAR2,11], "N"."NAME"[VARCHAR2,50]
8 - "N".ROWID[ROWID,10], "N"."EMPLID"[VARCHAR2,11]
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
31
select * from
table( dbms_xplan.display(
null, null, ‘ADVANCED'));
• An outline is a set of hints
Outline Data
------------/*+
BEGIN_OUTLINE_DATA
INDEX(@"SEL$2" "D1"@"SEL$2" "PS_DEPT_TBL")
USE_HASH(@"SEL$1" "N"@"SEL$1")
LEADING(@"SEL$1" "D"@"SEL$1" "N"@"SEL$1")
INDEX_FFS(@"SEL$1" "N"@"SEL$1" "PS0NAMES")
FULL(@"SEL$1" "D"@"SEL$1")
OUTLINE(@"SEL$1")
OUTLINE(@"SEL$2")
OUTLINE_LEAF(@"SEL$1")
OUTLINE_LEAF(@"SEL$2")
ALL_ROWS
OPTIMIZER_FEATURES_ENABLE('10.2.0.1')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
*/
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
32
DBMS_XPLAN.DISPLAY
• Filter Predicates
– Applied to the plan table
– Simply get a partial execution plan
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
33
table(
dbms_xplan.display(null, null, null,
'object_name like ''%DEPT%'''));
select * from
Plan hash value: 454993881
---------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
|
---------------------------------------------------------------------------------------|* 3 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
330 | 14850 |
6
(0)| 00:00:01 |
|* 6 |
INDEX FAST FULL SCAN| PS1DEPT_TBL |
660 | 13860 |
3
(0)| 00:00:01 |
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------3 - filter("D"."EFF_STATUS"='A')
6 - filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("EFFDT"))<=SYSDATE@! AND
SYS_OP_DESCEND("EFFDT")>=SYS_OP_DESCEND(SYSDATE@!))
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
34
SQL Developer Explain Plan
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
35
DBMS_XPLAN.DISPLAY
• Rolled-up cost of each operation
– Estimate of time (converted from cost to time)
– Number of rows returned from each operation.
• Remember this is an prediction of what will
happen based upon the CBO statistics and
not reality.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
36
The problem with EXPLAIN PLAN
• It is the execution plan now in this session
with the statistics and environment in force
now.
• It may be what will happen next time the
statement is executed, but it may not be
what happened last time.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
37
DBMS_XPLAN.DISPLAY_CURSOR
• Displays the execution plan of a cursor in
the library cache
– Based upon view
V$SQL_PLAN_STATISTICS_ALL
– A SQL Statement might have multiple
execution plans
• So it is what happened – sort of
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
38
DBMS_XPLAN.DISPLAY_CURSOR
• Usage
DBMS_XPLAN.DISPLAY_CURSOR(
sql_id
IN VARCHAR2 DEFAULT NULL,
child_number IN NUMBER
DEFAULT NULL,
format
IN VARCHAR2 DEFAULT 'TYPICAL');
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
39
DBMS_XPLAN.DISPLAY_CURSOR
• Get SQL ID
–
–
–
–
V$SQL
V$SQLAREA
V$OPEN_CURSOR
V$SESSION
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
40
table(
dbms_xplan.display_cursor(
'bh01rt8q2820q'));
select * from
PLAN_TABLE_OUTPUT
------------------------------------------------------SQL_ID bh01rt8q2820q, child number 0
------------------------------------SELECT d.setid, d.deptid, d.descr, n.emplid, n.name
FROM ps_dept_Tbl d, ps_names n WHERE d.effdt = (
SELECT MAX(d1.effdt) FROM ps_dept_tbl d1 WHERE
d1.setid = d.setid AND d1.deptid = d.deptid AND
d1.effdt <= SYSDATE ) AND d.eff_status ='A' AND
n.emplid = d.manager_id
…
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
41
table(
dbms_xplan.display_cursor(
'bh01rt8q2820q'));
select * from
Plan hash value: 454993881
-------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
|
|
13 (100)|
|
|
1 | NESTED LOOPS
|
|
2 |
176 |
13 (16)| 00:00:01 |
|* 2 |
HASH JOIN
|
|
1 |
65 |
11 (19)| 00:00:01 |
|* 3 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
330 | 14850 |
6
(0)| 00:00:01 |
|
4 |
VIEW
| VW_SQ_1
|
660 | 13200 |
4 (25)| 00:00:01 |
|
5 |
HASH GROUP BY
|
|
660 | 13860 |
4 (25)| 00:00:01 |
|* 6 |
INDEX FAST FULL SCAN
| PS1DEPT_TBL |
660 | 13860 |
3
(0)| 00:00:01 |
|
7 |
TABLE ACCESS BY INDEX ROWID| PS_NAMES
|
2 |
46 |
2
(0)| 00:00:01 |
|* 8 |
INDEX RANGE SCAN
| PS_NAMES
|
2 |
|
1
(0)| 00:00:01 |
-------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access("D"."EFFDT"="VW_COL_1" AND SYS_OP_DESCEND("D"."EFFDT")=SYS_OP_DESCEND(
"VW_COL_1") AND "SETID"="D"."SETID" AND "DEPTID"="D"."DEPTID")
3 - filter("D"."EFF_STATUS"='A')
6 - filter((SYS_OP_UNDESCEND("D1"."SYS_NC00051$")<=SYSDATE@! AND
"D1"."SYS_NC00051$">=SYS_OP_DESCEND(SYSDATE@!)))
8 - access("N"."EMPLID"="D"."MANAGER_ID")
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
42
DBMS_XPLAN.DISPLAY_CURSOR
• The execution plan is the one that was used
to execute the statement
– But the costs and metrics are still based upon
the CBO statistics
– There may be a discrepancy between estimated
and actual cost of operations in the plan
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
43
Descending and Function-Based
Indexes
SELECT uic.index_name, uic.column_name,
uic.descend, uie.column_expression
FROM
user_ind_Columns uic
,
user_ind_expressions uie
WHERE uic.column_name = 'SYS_NC00051$'
AND
uic.index_name = 'PS1DEPT_TBL'
AND
uie.index_name = uic.index_name
AND
uie.table_name = uic.table_name
/
INDEX_NAME
COLUMN_NAME DESCEND COLUMN_EXPRESSION
------------ ------------ ------- ----------------PS1DEPT_TBL SYS_NC00051$ DESC
"EFFDT"
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
44
Extra Format Options
• IOSTAT: assumes basic statistics are
collected when SQL executed
• MEMSTATS: if PGA management enable
display memory management stats
• ALLSTATS: IOSTATS and MEMSTATS
• LAST: last execution only
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
45
Collecting Execution Statistics
• Hint one statement
/*+ gather_plan_statistics */
• Set for session
ALTER SESSION
SET statistics_level = 'ALL'
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
46
select * from
table(dbms_xplan.display_cursor(
'fz3qdn0z07n8n',null,'IOSTATS'));
SQL_ID fz3qdn0z07n8n, child number 0
------------------------------------SELECT /*+ gather_plan_statistics */ d.setid, d.deptid, d.descr, n.emplid, n.name FROM ps_dept_Tbl d
ps_names n WHERE d.effdt = ( SELECT MAX(d1.effdt) FROM ps_dept_tbl d1 WHERE d1.setid = d.setid
AND d1.deptid = d.deptid AND d1.effdt <= SYSDATE ) AND d.eff_status = 'A' AND n.emplid = d.manager
Plan hash value: 454993881
---------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Starts | E-Rows | A-Rows |
A-Time
| Buffers
---------------------------------------------------------------------------------------------------|
1 | NESTED LOOPS
|
|
1 |
2 |
65 |00:00:00.01 |
793
|* 2 |
HASH JOIN
|
|
1 |
1 |
618 |00:00:00.01 |
40
|* 3 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
1 |
330 |
658 |00:00:00.01 |
23
|
4 |
VIEW
| VW_SQ_1
|
1 |
660 |
620 |00:00:00.01 |
17
|
5 |
HASH GROUP BY
|
|
1 |
660 |
620 |00:00:00.01 |
17
|* 6 |
INDEX FAST FULL SCAN
| PS1DEPT_TBL |
1 |
660 |
660 |00:00:00.01 |
17
|
7 |
TABLE ACCESS BY INDEX ROWID| PS_NAMES
|
618 |
2 |
65 |00:00:00.01 |
753
|* 8 |
INDEX RANGE SCAN
| PS_NAMES
|
618 |
2 |
65 |00:00:00.01 |
691
----------------------------------------------------------------------------------------------------
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
|
|
|
|
|
|
|
|
|
47
select * from
table(dbms_xplan.display_cursor(
'fz3qdn0z07n8n',null,'MEMSTATS'));
SQL_ID fz3qdn0z07n8n, child number 0
------------------------------------SELECT /*+ gather_plan_statistics */ d.setid, d.deptid, d.descr, n.emplid, n.name FROM ps_dept_Tbl d
ps_names n WHERE d.effdt = ( SELECT MAX(d1.effdt) FROM ps_dept_tbl d1 WHERE d1.setid = d.setid
AND d1.deptid = d.deptid AND d1.effdt <= SYSDATE ) AND d.eff_status = 'A' AND n.emplid = d.manager
Plan hash value: 454993881
---------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Starts | E-Rows | A-Rows |
A-Time
| OMem |
---------------------------------------------------------------------------------------------------|
1 | NESTED LOOPS
|
|
1 |
2 |
65 |00:00:00.01 |
|
|* 2 |
HASH JOIN
|
|
1 |
1 |
618 |00:00:00.01 |
746K|
|* 3 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
1 |
330 |
658 |00:00:00.01 |
|
|
4 |
VIEW
| VW_SQ_1
|
1 |
660 |
620 |00:00:00.01 |
|
|
5 |
HASH GROUP BY
|
|
1 |
660 |
620 |00:00:00.01 |
|
|* 6 |
INDEX FAST FULL SCAN
| PS1DEPT_TBL |
1 |
660 |
660 |00:00:00.01 |
|
|
7 |
TABLE ACCESS BY INDEX ROWID| PS_NAMES
|
618 |
2 |
65 |00:00:00.01 |
|
|* 8 |
INDEX RANGE SCAN
| PS_NAMES
|
618 |
2 |
65 |00:00:00.01 |
|
----------------------------------------------------------------------------------------------------
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
1Mem |
|
746K|
|
|
|
|
|
|
O/1/M
|
1/0/0|
|
|
|
48
MEMSTATS Columns
• 0Mem : The estimated amount of memory
needed for an optimal execution
• 1Mem : The estimated amount of memory
needed for one-pass execution.
• 0/1/M : Then number of times the execution
was performed in optimal/onepass/multipass mode.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
49
DBMS_XPLAN.DISPLAY_AWR
• Displays the execution plan of a cursor
stored in the Automatic Workload
Repository (AWR)
• Extracts information from AWR tables
– DBA_HIST_SQL_PLAN
– DBA_HIST_SQLTEXT
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
50
DBMS_XPLAN.DISPLAY_AWR
• AWR is the replacement to Statspack
– It is licensed as a part of Diagnostic Pack
– Therefore, use of this function is similarly
licensed.
• Statspack doesn’t report SQL_IDs
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
51
Statspack and DBMS_XPLAN
select * from table( dbms_xplan.display(
'stats$sql_plan',null, 'all',
'hash_value = 740558870 and
snap_id=4200'))
• If you use 10g STATSPACK, use
hash_value, not plan_hash_value
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
52
DBMS_XPLAN.DISPLAY_AWR
• Usage
DBMS_XPLAN.DISPLAY_AWR(
sql_id
IN VARCHAR2,
plan_hash_value IN NUMBER DEFAULT NULL,
db_id
IN NUMBER DEFAULT NULL,
format
IN VARCHAR2 DEFAULT TYPICAL);
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
53
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
54
table(
dbms_xplan.display_awr(
'bh01rt8q2820q'));
select * from
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------SQL_ID bh01rt8q2820q
-------------------SELECT d.setid, d.deptid, d.descr, n.emplid, n.name FROM ps_dept_Tbl d, ps_names n
WHERE d.effdt = ( SELECT MAX(d1.effdt) FROM ps_dept_tbl d1 WHERE d1.setid =
d.setid AND d1.deptid = d.deptid AND d1.effdt <= SYSDATE ) AND d.eff_status =
'A' AND n.emplid = d.manager_id
Plan hash value: 454993881
-------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
|
|
13 (100)|
|
|
1 | NESTED LOOPS
|
|
2 |
176 |
13 (16)| 00:00:01 |
|
2 |
HASH JOIN
|
|
1 |
65 |
11 (19)| 00:00:01 |
|
3 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
330 | 14850 |
6
(0)| 00:00:01 |
|
4 |
VIEW
| VW_SQ_1
|
660 | 13200 |
4 (25)| 00:00:01 |
|
5 |
HASH GROUP BY
|
|
660 | 13860 |
4 (25)| 00:00:01 |
|
6 |
INDEX FAST FULL SCAN
| PS1DEPT_TBL |
660 | 13860 |
3
(0)| 00:00:01 |
|
7 |
TABLE ACCESS BY INDEX ROWID| PS_NAMES
|
2 |
46 |
2
(0)| 00:00:01 |
|
8 |
INDEX RANGE SCAN
| PS_NAMES
|
2 |
|
1
(0)| 00:00:01 |
--------------------------------------------------------------------------------------------
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
55
Multiple Execution plans
SQL_ID bxu9sk3q91trn
-------------------INSERT INTO TMP_ACTSEARCH1 (ACTIVITY_PK) SELECT ACT.ACTIVITY_PK FROM
TBL_TMX_ACTIVITY ACT WHERE CONTAINS(ACT.ACTIVITYDESC, :B1 ) > 0
Plan hash value: 2274164979
-------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------------------|
0 | INSERT STATEMENT |
|
|
|
379K(100)|
|
|
1 | TABLE ACCESS FULL| TBL_TMX_ACTIVITY |
1 |
74 |
379K (8)| 00:00:30 |
-------------------------------------------------------------------------------------SQL_ID bxu9sk3q91trn
-------------------INSERT INTO TMP_ACTSEARCH1 (ACTIVITY_PK) SELECT ACT.ACTIVITY_PK FROM
TBL_TMX_ACTIVITY ACT WHERE CONTAINS(ACT.ACTIVITYDESC, :B1 ) > 0
Plan hash value: 4216380757
-------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------------------|
0 | INSERT STATEMENT
|
|
|
|
1 (100)|
|
1 | TABLE ACCESS BY INDEX ROWID| TBL_TMX_ACTIVITY |
1 |
73 |
0
(0)|
|
2 |
DOMAIN INDEX
| FT_TABLE_RAJLCU1R |
|
|
0
(0)|
--------------------------------------------------------------------------------------
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
56
DBMS_XPLAN.DISPLAY_SQLSET
• Displays execution plan of a statement in a
tuning set.
– It is licensed as a part of Diagnostic Pack or
Tuning Pack
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
57
DBMS_XPLAN.DISPLAY_SQLSET
• Usage
DBMS_XPLAN.DISPLAY_SQLSET(
sqlset_name
IN VARCHAR2,
sql_id
IN VARCHAR2,
plan_hash_value IN NUMBER NULL,
format
IN VARCHAR2 'TYPICAL',
sqlset_owner
IN VARCHAR2 NULL)
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
58
DBMS_XPLAN.
DISPLAY_SQL_PLAN_BASELINE
• New in Oracle 11g
• Displays execution plan of a statement in a
SQL base line.
– It is licensed as a part of Tuning Pack(?)
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
59
DBMS_XPLAN.
DISPLAY_SQL_PLAN_BASELINE
• Usage
DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE (
sql_handle
IN VARCHAR2 := NULL,
plan_name
IN VARCHAR2 := NULL,
format
IN VARCHAR2 := 'TYPICAL')
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
60
What is Wrong with this plan?
---------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Starts | E-Rows | Cost (%CPU)| A-Rows |
A-Time
---------------------------------------------------------------------------------------------------|
1 | NESTED LOOPS
|
|
1 |
2 |
13 (16)|
65 |00:00:00.06
|* 2 |
HASH JOIN
|
|
1 |
1 |
11 (19)|
618 |00:00:00.04
|* 3 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
1 |
330 |
6
(0)|
658 |00:00:00.01
|
4 |
VIEW
| VW_SQ_1
|
1 |
660 |
4 (25)|
620 |00:00:00.02
|
5 |
HASH GROUP BY
|
|
1 |
660 |
4 (25)|
620 |00:00:00.01
|* 6 |
INDEX FAST FULL SCAN
| PS1DEPT_TBL |
1 |
660 |
3
(0)|
660 |00:00:00.01
|
7 |
TABLE ACCESS BY INDEX ROWID| PS_NAMES
|
618 |
2 |
2
(0)|
65 |00:00:00.02
|* 8 |
INDEX RANGE SCAN
| PS_NAMES
|
618 |
2 |
1
(0)|
65 |00:00:00.01
----------------------------------------------------------------------------------------------------
| Buffers |
|
|
|
|
|
|
|
|
793 |
40 |
17 |
17 |
691
Predicate Information (identified by operation id):
--------------------------------------------------2 - access("D"."EFFDT"="VW_COL_1" AND SYS_OP_DESCEND("D"."EFFDT")=SYS_OP_DESCEND(
"VW_COL_1") AND "SETID"="D"."SETID" AND "DEPTID"="D"."DEPTID")
3 - filter("D"."EFF_STATUS"='A')
6 - filter((SYS_OP_UNDESCEND("D1"."SYS_NC00051$")<=SYSDATE@! AND
"D1"."SYS_NC00051$">=SYS_OP_DESCEND(SYSDATE@!)))
8 - access("N"."EMPLID"="D"."MANAGER_ID")
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
61
Skewed distribution of Data
SELECT eff_status, count(*)
FROM
ps_dept_tbl
GROUP BY eff_status
EFF
COUNT(*)
--- ---------I
2
A
658
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
62
Collect Stats with Histograms
• This is the default option in 10g
begin
sys.dbms_stats.gather_table_stats
(ownname=>'SYSADM'
,tabname=>'PS_DEPT_TBL'
,estimate_percent=>DBMS_STATS.AUTO_SAMPLE_SIZE
,method_opt=>'FOR ALL COLUMNS SIZE AUTO'
,cascade=>TRUE);
end;
/
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
63
Any Better?
---------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Starts | E-Rows | Cost (%CPU)| A-Rows |
A-Time
---------------------------------------------------------------------------------------------------|
1 | NESTED LOOPS
|
|
1 |
11 |
21 (10)|
65 |00:00:00.06
|* 2 |
HASH JOIN
|
|
1 |
5 |
11 (19)|
618 |00:00:00.04
|
3 |
VIEW
| VW_SQ_1
|
1 |
660 |
4 (25)|
620 |00:00:00.01
|
4 |
HASH GROUP BY
|
|
1 |
660 |
4 (25)|
620 |00:00:00.01
|* 5 |
INDEX FAST FULL SCAN
| PS1DEPT_TBL |
1 |
660 |
3
(0)|
660 |00:00:00.01
|* 6 |
TABLE ACCESS FULL
| PS_DEPT_TBL |
1 |
658 |
6
(0)|
658 |00:00:00.01
|
7 |
TABLE ACCESS BY INDEX ROWID| PS_NAMES
|
618 |
2 |
2
(0)|
65 |00:00:00.02
|* 8 |
INDEX RANGE SCAN
| PS_NAMES
|
618 |
2 |
1
(0)|
65 |00:00:00.01
----------------------------------------------------------------------------------------------------
| Buffers |
|
|
|
|
|
|
|
|
823
70
17
17
691
Predicate Information (identified by operation id):
--------------------------------------------------2 - access("D"."EFFDT"="VW_COL_1" AND SYS_OP_DESCEND("D"."EFFDT")=SYS_OP_DESCEND("VW_COL_1"
) AND "SETID"="D"."SETID" AND "DEPTID"="D"."DEPTID")
5 - filter((SYS_OP_UNDESCEND("D1"."SYS_NC00051$")<=SYSDATE@! AND
"D1"."SYS_NC00051$">=SYS_OP_DESCEND(SYSDATE@!)))
6 - filter("D"."EFF_STATUS"='A')
8 - access("N"."EMPLID"="D"."MANAGER_ID")
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
64
|
|
|
|
The data is skewed
• 37 setids
• 435 departments
• 37 distinct managers
• 1.06 rows per setid & deptid
• 19 distinct effective dates.
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
65
Acknowledgements
• 10g/11g DBMS_XPLAN
– Carol Dacko, University of Michigan
• Collaborate 08 Conference presentation
– Blog to be launched soon
• Rob van Wijk
– http://rwijk.blogspot.com/2008/03/dbmsxplandi
splaycursor.html
DBMS_XPLAN
UKOUG2008 ©www.go-faster.co.uk
78
Questions?
Obtaining and Interpreting
Execution Plans using
DBMS_XPLAN
David Kurtz
Go-Faster Consultancy Ltd.
[email protected]
www.go-faster.co.uk