0% found this document useful (0 votes)
157 views68 pages

Obtaining and Interpreting Execution Plans Using Dbms - Xplan: David Kurtz

Uploaded by

kruemeL1969
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
157 views68 pages

Obtaining and Interpreting Execution Plans Using Dbms - Xplan: David Kurtz

Uploaded by

kruemeL1969
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 68

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 • Book
– Independent consultant
– www.psftdba.com
• System Performance
tuning
– PeopleSoft ERP
– Oracle RDBMS

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 2


o.uk
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.c 3


o.uk
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.c 4


o.uk
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.c 5


o.uk
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.c 6


o.uk
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.c 7


o.uk
Agenda

• SQL Trace
• Execution Plans
– Explain Plan For
– DBMS_XPLAN
– AWR
– Licensing

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 8


o.uk
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.c 9


o.uk
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.c 10


o.uk
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.c 11


o.uk
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.c 12
o.uk
Alternatives to Trace

• Explain Plan For


• DBMS_XPLAN

• Assumption:
– You know which SQL statement is your
problem!

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 13


o.uk
Example: Two HR tables
• PS_NAMES • PS_DEPT_TBL
Name Null? Type Name Null? Type
----------------------- -------- ------------ ----------------------- -------- ------------
EMPLID* NOT NULL VARCHAR2(11) SETID* NOT NULL VARCHAR2(5)
NAME_TYPE NOT NULL VARCHAR2(3) DEPTID* NOT NULL VARCHAR2(10)
EFFDT NOT NULL DATE EFFDT* NOT NULL DATE
EFF_STATUS NOT NULL VARCHAR2(1) EFF_STATUS NOT NULL VARCHAR2(1)
COUNTRY_NM_FORMAT NOT NULL VARCHAR2(3) DESCR NOT NULL VARCHAR2(30)
NAME NOT NULL VARCHAR2(50) DESCRSHORT NOT NULL VARCHAR2(10)
… …

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 14


o.uk
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.c 15


o.uk
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.c 16


o.uk
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.c 17


o.uk
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.c 18


o.uk
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.c 19


o.uk
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.c 20


o.uk
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.c 21


o.uk
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.c 22


o.uk
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.c 23


o.uk
DBMS_XPLAN.DISPLAY

SELECT * FROM
table(dbms_xplan.display());

• Autotrace in SQL*Plus 10 now uses


dbms_xplan.

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 24


o.uk
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.c 25


o.uk
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.c 26


o.uk
select * from
table( dbms_xplan.display( null,
null, 'TYPICAL,-BYTES'));
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.c 27


o.uk
select * from
table( dbms_xplan.display( null,
null, ‘ALL'));

• Additional Information
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

1 - SEL$C772B8D1
3 - SEL$C772B8D1 / D@SEL$1
4 - SEL$683B0107 / VW_SQ_1@SEL$7511BFD2
5 - SEL$683B0107
6 - SEL$683B0107 / D1@SEL$2
7 - SEL$C772B8D1 / N@SEL$1
8 - SEL$C772B8D1 / N@SEL$1

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 28


o.uk
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.c 29


o.uk
select * from
table( dbms_xplan.display( null,
null, ‘ALL'));

• Additional Information
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

1 - SEL$3787FDDA
3 - SEL$3787FDDA / D@MAIN_QUERY
4 - SEL$71F31171 / VW_SQ_1@SEL$4A7F38AA
5 - SEL$71F31171
6 - SEL$71F31171 / D1@DEPT_SUBQUERY
7 - SEL$3787FDDA / N@MAIN_QUERY
8 - SEL$3787FDDA / N@MAIN_QUERY

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 30


o.uk
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.c 31


o.uk
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.c 32


o.uk
DBMS_XPLAN.DISPLAY

• Filter Predicates
– Applied to the plan table
– Simply get a partial execution plan

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 33


o.uk
select * from
table( dbms_xplan.display(null, null,
null, 'object_name like ''%DEPT
%'''));
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.c 34


o.uk
SQL Developer Explain Plan

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 35


o.uk
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.c 36


o.uk
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.c 37


o.uk
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.c 38


o.uk
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.c 39


o.uk
DBMS_XPLAN.DISPLAY_CURSOR

• Get SQL ID
– V$SQL
– V$SQLAREA
– V$OPEN_CURSOR
– V$SESSION

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 40


o.uk
select * from
table( dbms_xplan.display_cursor( '
bh01rt8q2820q'));
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.c 41


o.uk
select * from
table( dbms_xplan.display_cursor( '
bh01rt8q2820q'));
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.c 42


o.uk
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.c 43


o.uk
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.c 44


o.uk
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.c 45


o.uk
Collecting Execution Statistics
• Hint one statement

/*+ gather_plan_statistics */

• Set for session

ALTER SESSION
SET statistics_level = 'ALL'

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 46


o.uk
select * from

table(dbms_xplan.display_cursor( 'fz3
qdn0z07n8n',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.c 47


o.uk
select * from

table(dbms_xplan.display_cursor( 'fz3
qdn0z07n8n',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 | 1Mem | O/1/M
----------------------------------------------------------------------------------------------------
| 1 | NESTED LOOPS | | 1 | 2 | 65 |00:00:00.01 | | | |
|* 2 | HASH JOIN | | 1 | 1 | 618 |00:00:00.01 | 746K| 746K| 1/0/0|
|* 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.c 48


o.uk
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/one-
pass/multipass mode.

DBMS_XPLAN UKOUG2008 ©www.go-faster.c 49


o.uk
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.c 50


o.uk
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.c 51


o.uk
Statspack and DBMS_XPLAN
select * from
table( dbms_xplan.display( 'stats$sql_p
lan',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.c 52


o.uk
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.c 53


o.uk
DBMS_XPLAN UKOUG2008 ©www.go-faster.c 54
o.uk
select * from
table( dbms_xplan.display_awr( 'bh0
1rt8q2820q'));
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.c 55


o.uk
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.c 56


o.uk
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.c 57


o.uk
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.c 58


o.uk
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.c 59


o.uk
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.c 60


o.uk
What is Wrong with this plan?
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------
| 1 | NESTED LOOPS | | 1 | 2 | 13 (16)| 65 |00:00:00.06 | 793 |
|* 2 | HASH JOIN | | 1 | 1 | 11 (19)| 618 |00:00:00.04 | 40 |
|* 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 | 17 |
| 5 | HASH GROUP BY | | 1 | 660 | 4 (25)| 620 |00:00:00.01 | 17 |
|* 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 | 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.c 61


o.uk
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.c 62


o.uk
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.c 63


o.uk
Any Better?
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------
| 1 | NESTED LOOPS | | 1 | 11 | 21 (10)| 65 |00:00:00.06 | 823 |
|* 2 | HASH JOIN | | 1 | 5 | 11 (19)| 618 |00:00:00.04 | 70 |
| 3 | VIEW | VW_SQ_1 | 1 | 660 | 4 (25)| 620 |00:00:00.01 | 17 |
| 4 | HASH GROUP BY | | 1 | 660 | 4 (25)| 620 |00:00:00.01 | 17 |
|* 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 | 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.c 64


o.uk
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.c 65


o.uk
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.c 78


o.uk
Questions?
Obtaining and Interpreting
Execution Plans using
DBMS_XPLAN
David Kurtz
Go-Faster Consultancy Ltd.

[email protected]
www.go-faster.co.uk

You might also like