Module 4 Database SQL Tuning
Section 3 Application Performance
Explain Plan Basics
The Explain Plan Utility and the Execution Plan
Why Execution Plans Are Important Execution Plan Format Sample Execution Tree
1
The Explain Plan Utility and the Execution Plan
SQL Statement
Explain Plan Utility
plan_table
Explain Report
Execution Plan
Other Tools:OEM
SQL StudioPrecise
SQL TRACETKPROF, etc..
2
Why is the Explain Plan Utility Important? An execution plan shows how Oracle is going to
process a statement. This helps tune statements = Better Performance Builds SQL tuning skills = $$$ Builds Application tuning skills = $$$ When used by developers early in the development
cycle, can uncover data model, index, and performance issues before its too late!
3
Explain Report SQL
SELECT LPAD(' ',2*(LEVEL-1))||operation “OPERATION”
,options “OPTIONS”
,DECODE(TO_CHAR(id),'0','COST = ' ||
NVL(TO_CHAR(position),'n/a'), object_name)“OBJECT NAME”
,id ||'-'|| NVL(parent_id, 0)||'-'||
NVL(position, 0) “ORDER”
,SUBSTR(optimizer,1,6) “OPT”
FROM plan_table
START WITH id = 0
AND statement_id = 'X'
CONNECT BY PRIOR id = parent_id
AND statement_id = 'X';
4
Execution Plan Example
SELECT cust_no ,cust_address ,cust_last_name ,cust_first_name
FROM customer
WHERE cust_phone = '3035551234';
OPERATION OPTIONS OBJECT NAME ORDER OPT
----------------------- ------------ ----------------- ------- -----
SELECT STATEMENT COST = n/a 0-0-0 RULE
TABLE ACCESS BY ROWID CUSTOMER 1-0-1
INDEX RANGE SCAN IX_CUST_PHONE 2-1-1
5
Execution Tree Example
1TABLE ACCESS
BY ROWIDON CUSTOMER
2INDEX
RANGE SCANON IX_CUST_PHONE
6
OPERATIONS
ROW OPERATION SET OPERATION
7
ROW OPERATION
EXECUTED ON ONE ROW AT A TIME. THE USER CAN SEE THE FIRST
RESULT BEFORE THE LAST ROW IS FETCHED.
8
SET OPERATION
EXECUTED ON A RESULT SET OF ROWS.
THE USER CANNOT SEE THE FIRST RESULT UNTIL ALL ROWS ARE FETCHED AND PROCESSED.
9
SQL OPERATIONS
AND-EQUAL: ROW OPERATION CONCATENATION: ROW OPERATION CONNECT BY: ROW OPERATION COUNT: ROW OPERATION COUNT STOPKEY: ROW OPERATION FILTER: ROW OPERATION FOR UPDATE: SET OPERATION INDEX RANGE SCAN: ROW OPERATION
10
SQL OPERATIONS
INDEX UNIQUE SCAN: ROW OPERATION INTERSECTION: SET OPERATION MERGE JOIN: SET OPERATION MINUS: SET OPERATION NESTED LOOPS: ROW OPERATION OUTER JOIN: SET OPERATION OR ROW
OPERATION PROJECTION: ROW OPERATION REMOTE: ROW OPERATION OR SET OPERATION VIEW: SET OPERATION
11
SQL OPERATIONS
SEQUENCE: ROW OPERATION SORT AGGREGATE: SET OPERATION SORT GROUP BY: SET OPERATION SORT JOIN: SET OPERATION SORT ORDER BY: SET OPERATION SORT UNIQUE: SET OPERATION TABLE ACCESS BY ROWID: ROW OPERATION TABLE ACCESS FULL: ROW OPERATION UNION: SET OPERATION
12
ORACLE OPTIMIZER MODES
RULE-BASED COST-BASED
13
ORACLE HINTS (Some of them) RULE ALL_ROWS FIRST_ROWS AND-EQUAL FULL HASH INDEX INDEX_ASC INDEX_DESC
14
ORACLE HINTS Continued
NO_MERGE ORDERED ROWID USE_HASH USE_NL USE_MERGE USE_STAR
15
RULE
Rule hint tells the optimizer to use the rule-based optimization for the query. All other hints within the query will be ignored.
16
All_ROWS
All_Rows hint optimizes the query for the best throughput- that is, to minimize the time it takes for all rows returned by the query.
17
FIRST_ROWS
First_Rows hint optimizes the query for the shortest response time to return the first row from the query.
18
AND-EQUAL
And-Equal hint tells the optimizer to perform an And-Equal operation on the indexes listed within the hint.
19
FULL
Full hint will perform a Full table scan. This hint might be used, if one knows the index scan used by the query would be a poor choice given the data distribution. 20
INDEX
If a single index is used in the hint, that index will be used.
If multiple indexes are used in the hint, the optimizer will choose which indexes to use.
If only table name is used in the hint, then the optimizer will choose an index or indexes to use for that table.
21
INDEX-ASC
This hint is same as the Index hint.
22
INDEX_DESC
INDEX_DESC hint tells the optimizer to scan an index in the descending order of the indexed values.
23
NO_MERGE
This hint is available as of Oracle 7.3, which tells the optimizer not to merge a view’s SQL syntax with the syntax of a query that uses the view. 24
ORDERED
This hint will influence the order in which the tables are joined.
25
USE_NL
This hint tells the optimizer to perform a nested loop join, using the specified table as the driving table in the join.
26
USE-MERGE
This hint tells the optimizer to use a merge join between specified tables.
27
USE_STAR
This hint is available as of Oracle 7.3, tells the optimizer to use a composite key/star query execution path when resolving a join. These hints are typically used in data warehousing applications, which have a master table with small detail tables. 28
Access Path and Operation Examples Data Model for Examples Access Paths:
Table Access Full Table Access By ROWID Index Unique Scan Index Range Scan
Operations: And-Equal Nested Loops
29
Data Model For ExamplesCUSTOMER*cust_no cust_last_name cust_first_name cust_phone cust_address cust_zip
ORDER_HDR*order_no order_status order_create_dt order_desc order_cust_no order_amt
ux_customer
ix_cust_phone
ix_cust_zip
ux_order_hdr
ix_order_status
ix_order_cust_no
30
Access Path:Table Access Full
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_address FROM customer;
31
Access Path:Table Access Full
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_address FROM customer;
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS FULL CUSTOMER 1-0-1
32
Access Path:Table Access Full
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_address FROM customer;
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS FULL CUSTOMER 1-0-1
1TABLE ACCESS
FULLON CUSTOMER
33
Access Path:Table Access By ROWID
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE ROWID = CHARTOROWID( :host );
34
Access Path:Table Access By ROWID
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE ROWID = CHARTOROWID( :host );
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1
35
Access Path:Table Access By ROWID
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE ROWID = CHARTOROWID( :host );
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1
1TABLE ACCESS
BY ROWIDON CUSTOMER
36
SELECT cust_last_name ,cust_first_name ,cust_address FROM customerWHERE cust_no = :host;
Access Path:Index Unique Scan
37
SELECT cust_last_name ,cust_first_name ,cust_address FROM customerWHERE cust_no = :host;
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1 INDEX UNIQUE SCAN UX_CUSTOMER 2-1-1
Access Path:Index Unique Scan
38
SELECT cust_last_name ,cust_first_name ,cust_address FROM customerWHERE cust_no = :host;
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1 INDEX UNIQUE SCAN UX_CUSTOMER 2-1-1
Access Path:Index Unique Scan
1TABLE ACCESS
BY ROWIDON CUSTOMER
2INDEX
UNIQUE SCANON UX_CUSTOMER
39
SELECT cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = '3035551234';
Access Path:Index Range Scan
40
SELECT cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = '3035551234';
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1 INDEX RANGE SCAN IX_CUST_PHONE 2-1-1
Access Path:Index Range Scan
41
SELECT cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = '3035551234';
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1 INDEX RANGE SCAN IX_CUST_PHONE 2-1-1
Access Path:Index Range Scan
1TABLE ACCESS
BY ROWIDON CUSTOMER
2INDEX
RANGE SCANON IX_CUST_PHONE
42
And-Equal Operation
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = :host1AND cust_zip = :host2;
43
And-Equal Operation
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = :host1AND cust_zip = :host2;
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1 AND-EQUAL 2-1-1 INDEX RANGE SCAN IX_CUST_PHONE 3-2-1 INDEX RANGE SCAN IX_CUST_ZIP 4-2-2
44
And-Equal Operation
SELECT cust_no ,cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = :host1AND cust_zip = :host2;
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1 AND-EQUAL 2-1-1 INDEX RANGE SCAN IX_CUST_PHONE 3-2-1 INDEX RANGE SCAN IX_CUST_ZIP 4-2-2
1TABLE ACCESS
BY ROWIDON CUSTOMER
2AND-EQUAL
3INDEX
RANGE SCANON IX_CUST_PHONE
4INDEX
RANGE SCANON IX_CUST_ZIP
45
Nested Loop OperationSELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM customer a ,order_hdr bWHERE cust_phone = :host1AND b.order_cust_no = a.cust_noAND b.order_status = 'OPEN';
46
Nested Loop OperationSELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM customer a ,order_hdr bWHERE cust_phone = :host1AND b.order_cust_no = a.cust_noAND b.order_status = 'OPEN';
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE NESTED LOOPS 1-0-1 TABLE ACCESS BY ROWID ORDER_HDR 2-1-1 INDEX RANGE SCAN IX_ORDER_STATUS 3-2-1 TABLE ACCESS BY ROWID CUSTOMER 4-1-2 INDEX UNIQUE SCAN UX_CUSTOMER 5-4-1
47
Nested Loop OperationSELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM customer a ,order_hdr bWHERE cust_phone = :host1AND b.order_cust_no = a.cust_noAND b.order_status = 'OPEN';
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE NESTED LOOPS 1-0-1 TABLE ACCESS BY ROWID ORDER_HDR 2-1-1 INDEX RANGE SCAN IX_ORDER_STATUS 3-2-1 TABLE ACCESS BY ROWID CUSTOMER 4-1-2 INDEX UNIQUE SCAN UX_CUSTOMER 5-4-1
1NESTED LOOPS
2TABLE ACCESS
BY ROWIDON ORDER_HDR
4TABLE ACCESS
BY ROWIDON CUSTOMER
3INDEX
RANGE SCANON IX_ORDER_STATUS
5INDEX
UNIQUE SCANON UX_CUSTOMER
48
Tuning Examples
Index Suppression Table Order in FROM Clause
49
SELECT cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = '3035551234'AND cust_zip + 0 = :host1;
Index Suppression
50
SELECT cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = '3035551234'AND cust_zip + 0 = :host1;
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1 INDEX RANGE SCAN IX_CUST_PHONE 2-1-1
Index Suppression
51
SELECT cust_last_name ,cust_first_name ,cust_addressFROM customerWHERE cust_phone = '3035551234'AND cust_zip + 0 = :host1;
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE TABLE ACCESS BY ROWID CUSTOMER 1-0-1 INDEX RANGE SCAN IX_CUST_PHONE 2-1-1
Index Suppression
1TABLE ACCESS
BY ROWIDON CUSTOMER
2INDEX
RANGE SCANON IX_CUST_PHONE
52
FROM Clause Table OrderSELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM order_hdr b ,customer aWHERE cust_phone = :host1AND b.order_cust_no = a.cust_noAND b.order_status = 'OPEN';
53
FROM Clause Table OrderSELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM order_hdr b ,customer aWHERE cust_phone = :host1AND b.order_cust_no = a.cust_noAND b.order_status = 'OPEN';
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE NESTED LOOPS 1-0-1 TABLE ACCESS BY ROWID CUSTOMER 2-1-1 INDEX RANGE SCAN IX_CUST_PHONE 3-2-1 TABLE ACCESS BY ROWID ORDER_HDR 4-1-2 AND-EQUAL 5-4-1 INDEX RANGE SCAN IX_ORDER_CUST 6-5-1 INDEX RANGE SCAN IX_ORDER_STATUS 7-5-2
54
FROM Clause Table OrderSELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM order_hdr b ,customer aWHERE cust_phone = :host1AND b.order_cust_no = a.cust_noAND b.order_status = 'OPEN';
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE NESTED LOOPS 1-0-1 TABLE ACCESS BY ROWID CUSTOMER 2-1-1 INDEX RANGE SCAN IX_CUST_PHONE 3-2-1 TABLE ACCESS BY ROWID ORDER_HDR 4-1-2 AND-EQUAL 5-4-1 INDEX RANGE SCAN IX_ORDER_CUST 6-5-1 INDEX RANGE SCAN IX_ORDER_STATUS 7-5-2
1
2
3 5
6 7
4
55
Tuned QuerySELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM order_hdr b ,customer aWHERE cust_phone = :host1AND b.cust_no = a.cust_noAND b.order_status || ‘*’ = 'OPEN*';
56
Tuned QuerySELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM order_hdr b ,customer aWHERE cust_phone = :host1AND b.cust_no = a.cust_noAND b.order_status || ‘*’ = 'OPEN*';
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE NESTED LOOPS 1-0-1 TABLE ACCESS BY ROWID CUSTOMER 2-1-1 INDEX RANGE SCAN IX_CUST_PHONE 3-2-1 TABLE ACCESS BY ROWID ORDER_HDR 4-1-2 INDEX RANGE SCAN IX_ORDER_CUST 5-4-1
57
Tuned QuerySELECT a.cust_last_name ,a.cust_first_name ,a.cust_address ,b.order_desc ,b.order_create_dtFROM order_hdr b ,customer aWHERE cust_phone = :host1AND b.cust_no = a.cust_noAND b.order_status || ‘*’ = 'OPEN*';
OPERATION OPTIONS OBJECT NAME ORDER OPT------------------ ------------ -------------------- ------- ------SELECT STATEMENT COST = n/a 0-0-0 RULE NESTED LOOPS 1-0-1 TABLE ACCESS BY ROWID CUSTOMER 2-1-1 INDEX RANGE SCAN IX_CUST_PHONE 3-2-1 TABLE ACCESS BY ROWID ORDER_HDR 4-1-2 INDEX RANGE SCAN IX_ORDER_CUST 5-4-1
1
2
3 5
4
58
TUNING TIPS AVOID UNPLANNED FULL TABLE SCANS. If Rule-Based optimization is used, a full table scan will be used on a table
if any of the following conditions are met in a SQL statement: No Indexes exist on the table No limiting conditions are placed on the rows returned Limiting conditions placed on the rows that correspond to the leading column of an
index, but the conditions are used inside expressions. (ex. UPPER, CONCATENATION etc.)
Limiting conditions placed on the rows that correspond to the leading column of an index, but the conditions are either NULL checks or inequalities. (ex. IS NULL, IS NOT NULL, != etc.)
If Cost-Based optimization is used, Oracle will use full table scans for all the above cases shown for Rule-Based. In addition to that, Cost-Based optimizer may decide to use full table scans, if the table has not been analyzed, if the table is small, if the indexed columns are not selective, or if the optimization goal is set to ALL_ROWS.
59
TUNING TIPS
The leading column of a concatenated index should be the most selective column, and it should also be the column most often used by the limiting condition in the queries.
60
TUNING TIPS
NESTED LOOPS
When performing a NESTED LOOPS join, the optimizer first selects a driving table for the join. A full table scan may be performed on the driving table (Note: Select the driving table in the query to be small). In rule-based optimization, if there is equal chance of using an
index regardless of the choice of the driving table, the driving table will be the one that is listed LAST in the FROM clause.
In cost-based optimization, the optimizer will consider the size of the tables and the selectivity of the indexes while selecting a driving table.
61
TUNING TIPS
MERGE JOIN: Merge join can be used wherever a full table scan will be effective in the query. That is, in situations in which a full table scan is preferable to an index scan/table access by ROWID combination.
62
TUNING TIPS MANAGE SQL STATEMENTS CONTAINING VIEWS
If a query contains a view, then the optimizer has two ways of resolving the query: resolve the view first and then resolve the query, or integrate the view source into the query. If the view is resolved first, then the entire result set of the view is first determined, and the rest of the query conditions are applied as a filter. If a view contains a set operation, such as GROUP BY, SUM,
DISTINCT etc., then the view cannot be integrated into the query. If a view returns a large result set, or if the view’s result set is to
be filtered by additional limiting conditions in the query, then the query will benefit from having the view’s SQL integrated into the query. (Note: So avoid using functions such as group by etc. in the VIEWS).
63
TUNING TIPS
TUNE SUBQUERIES: Potential problems that are encountered involving SUBQUERIES include SUBQUERIES may be resolved before the rest of the query is
resolved. SUBQUERIES may require specific hints that are not directly related to
the query that calls the SUBQUERY. SUBQUERIES that could be performed as a single query may instead
be written as several distinct SUBQUERIES. SUBQUERIES may not perform existence checks in the most efficient
manner. (ex. NOT IN clause)
64
TUNING TIPS
REMOTE TABLE ACCESS: Whenever a SQL statement uses a remote object, a portion of the SQL statement is extracted to be executed on the remote node. Some times instead of tuning the main query, one may have to tune the SQL on the remote node. Depending upon the remote node query, to achieve better performance, one might use NESTED loops join or MERGE loop joins.
65
Summary
To determine how Oracle is going to process a SQL statement you must generate and interpret an execution plan for the statement.
With access to tools that can generate execution plans for SQL statements, along with a rudimentary understanding of the information that is in an execution plan and the knowledge of how to construct an execution tree, a developer or DBA can begin exploring the vast variety of explain plans their diverse SQL code will produce, and learn fairly quickly how to tune and develop quality SQL.
66
Top Related