Obtaining and Interpreting Execution Plans Using Dbms - Xplan: David Kurtz
Obtaining and Interpreting Execution Plans Using Dbms - Xplan: David Kurtz
[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
• SQL Trace
• Execution Plans
– Explain Plan For
– DBMS_XPLAN
– AWR
– Licensing
• 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
• Assumption:
– You know which SQL statement is your
problem!
EXPLAIN PLAN
SET statement_id = 'TST‘
INTO plan_table
FOR
<SQL>
/
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
• Available in Oracle 9i
– No licence restrictions
• 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);
SELECT * FROM
table(dbms_xplan.display());
--------------------------------------------------------------------------------------------
| 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 |
--------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
| 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 |
------------------------------------------------------------------------------------
• 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
• 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
• 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]
/*+
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
*/
• Filter Predicates
– Applied to the plan table
– Simply get a partial execution plan
----------------------------------------------------------------------------------------
| 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 |
----------------------------------------------------------------------------------------
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@!))
• Usage
DBMS_XPLAN.DISPLAY_CURSOR(
sql_id IN VARCHAR2 DEFAULT NULL,
child_number IN NUMBER DEFAULT NULL,
format IN VARCHAR2 DEFAULT 'TYPICAL');
• Get SQL ID
– V$SQL
– V$SQLAREA
– V$OPEN_CURSOR
– V$SESSION
--------------------------------------------------------------------------------------------
| 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 |
--------------------------------------------------------------------------------------------
/*+ gather_plan_statistics */
ALTER SESSION
SET statistics_level = 'ALL'
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
----------------------------------------------------------------------------------------------------
| 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 |
----------------------------------------------------------------------------------------------------
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
----------------------------------------------------------------------------------------------------
| 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 | | | |
----------------------------------------------------------------------------------------------------
• 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);
--------------------------------------------------------------------------------------------
| 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 |
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
| 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
--------------------------------------------------------------------------------------
| 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)|
--------------------------------------------------------------------------------------
• 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)
• Usage
DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE (
sql_handle IN VARCHAR2 := NULL,
plan_name IN VARCHAR2 := NULL,
format IN VARCHAR2 := 'TYPICAL')
EFF COUNT(*)
--- ----------
I 2
A 658
end;
/
• 37 setids
• 435 departments
• 37 distinct managers
• 10g/11g DBMS_XPLAN
– Carol Dacko, University of Michigan
• Collaborate 08 Conference presentation
– Blog to be launched soon
[email protected]
www.go-faster.co.uk