+ All Categories
Home > Documents > SQL Tuning 101 excerpt: Explain Plan A Logical Approach [email protected] Michael...

SQL Tuning 101 excerpt: Explain Plan A Logical Approach [email protected] Michael...

Date post: 14-Jan-2016
Category:
Upload: shanon-carson
View: 216 times
Download: 3 times
Share this document with a friend
74
SQL Tuning 101 SQL Tuning 101 excerpt: Explain excerpt: Explain Plan Plan A Logical Approach A Logical Approach By By mruckdaschel@affiniongroup. mruckdaschel@affiniongroup. com com Michael Ruckdaschel Michael Ruckdaschel Affinion Group Affinion Group
Transcript
Page 1: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

SQL Tuning 101SQL Tuning 101excerpt: Explain Planexcerpt: Explain Plan

SQL Tuning 101SQL Tuning 101excerpt: Explain Planexcerpt: Explain Plan

A Logical ApproachA Logical Approach

ByBy

[email protected]@affiniongroup.comm

Michael RuckdaschelMichael Ruckdaschel

Affinion Group InternationalAffinion Group International

Page 2: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

My Qualifications• Software Developer for Affinion Group

International for 12 years• an expert in SQL Performance Tuning

for Oracle Databases. • Over 8 years tuning experience• Over 20 years Applications Design and

Development experience. • Current tuning experience includes

Oracle 9iR2 RAC, and earlier versions of Oracle to Version 7, with databases up to 7 Terabytes in size

Page 3: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Question:What is the Single Most-Effective way to tune a SQL statement?

Answer:Reduce the amount of work Oracle needs to do to return the desired result.

That’s All Y

ou Need To

Know!!!!

Page 4: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

????? My SQL is performing poorly, there must be other users / processes slowing me down.If only there was an index on column “x”, my SQL would perform

????? It doesn’t matter how I write my SQL or Process, we can always tune it later.

MYTH: It doesn’t matter how I write my SQL or Process, we can always tune it later.

FACT:SQL Tuning cannot overcome poor process design.

MYTH: I need to add hints to every query to make Oracle perform. Oracle is going to choose the wrong access method most of the time.

MYTH: My SQL is performing poorly, there must be other users / processes slowing me down.If only there was an index on column “x”, my SQL would perform

MYTH: Full Table Scans are bad! Index Access is always better!

FACT:There are many times where a Full Table Scan is going to be more efficient than Index Access, and vice-versa.

FACT:Given correct information (i.e. Statistics), and properly written SQL, Oracle will make the “right” decision in its execution of a Given Query most of the time.

FACT:90% of all performance problems involve inefficiency of your SQL and process, NOT problems with the database (i.e. indexing, other users, file system, data model, etc)

????? Solely from looking at the Explained Plan one can tell how a query will perform.

FACT:Only executing a query will determine its performance characteristics. However, comparing two plans, one may estimate which will likely incur “less work”.

????? I need to add hints to every query to make Oracle perform. Oracle is going to choose the wrong access method most of the time.

????? Full Table Scans are bad! Index Access is always better!

MYTH:Solely from looking at the Explained Plan one can tell how a query will perform.

Myth or Fact???

Page 5: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Our Agenda• What is Oracle going to do?• How does Oracle derive this plan?• How do we find out Oracle’ plan?• How do we read an Explain Plan?

– Access Methods– Join Methods and Order– Stepping through the plan

• Plan Evaluation

Page 6: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Given a SQL Statement,What is Oracle going to do?

The steps Oracle is going to go through in executing our query, to get us the information we’ve requested.

FACT: Oracle only knows how to deal with 1-2 row sources (e.g. Tables) at a time.

Explain Plan:

Possible Exception is BITMAP table access --More on that later.

Page 7: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

EXPLAIN PLAN (Cont’d)

It will Tell Us:• … what Table Access Method Oracle is going to use to

access each table in our query (Direct Row Access or Table/Index Scan)

• … what Join Method Oracle is going use to join each row set with another row set.

• … what order Oracle is going to access and join the tables in our query.

• … how much data (rows and bytes) Oracle is estimating the query is going to access at each step.

• …, if the underlying table is partitioned, how many, and which, partitions will be scanned / accessed.

Page 8: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

SELECT …FROM temp_open_ar_transactions ar ,fin_trans ft ,ftc_inv fi ,member_contract mc ,recognition_fin_link rfl ,member_contract_attrib mca ,refund_method rm ,member_recognition mr ,partner p ,partner_corporation pcWHERE ar.fin_trans_sysid = ft.fin_trans_sysidAND ft.ftc_inv_sysid = fi.ftc_inv_sysidAND ft.member_contract_sysid = mc.member_contract_sysidAND ft.cur_recognition_fin_link_sysid = rfl.recognition_fin_link_sysidAND rfl.mem_contract_attrib_sysid = mca.member_contract_attrib_sysidAND mca.refund_method_id = rm.refund_method_idAND mca.partner_id = p.partner_sysidAND p.partner_corporation_sysid = pc.partner_corporation_sysidAND rfl.recognition_fin_link_sysid = mr.recognition_fin_link_sysidAND mr.recognition_date <= cycle_date.mth_cycle_date_eodAND mr.closed_date IS NULLGROUP BY … HAVING mr_revenue_amt != 0 AND mr_comm_amt != 0

What do you think of this SQL?

Page 9: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

------------------------------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes |TempSpc| Cost | Pstart| Pstop |------------------------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 9872 | 2371K| | 2029K| | ||* 1 | FILTER | | | | | | | || 2 | SORT GROUP BY | | 9872 | 2371K| 981M| 2029K| | ||* 3 | HASH JOIN | | 3948K| 926M| | 1992K| | || 4 | TABLE ACCESS FULL | REFUND_METHOD | 28 | 196 | | 2 | | ||* 5 | HASH JOIN | | 3948K| 899M| | 1992K| | || 6 | TABLE ACCESS FULL | PARTNER_CORPORATION | 1323 | 26460 | | 2 | | ||* 7 | HASH JOIN | | 3948K| 824M| | 1992K| | || 8 | TABLE ACCESS FULL | PARTNER | 3896 | 35064 | | 3 | | ||* 9 | HASH JOIN | | 3948K| 790M| 400M| 1991K| | || 10 | TABLE ACCESS FULL | MEMBER_CONTRACT_ATTRIB | 8230K| 306M| | 3809 | | ||* 11 | HASH JOIN | | 3948K| 643M| 15M| 1973K| | || 12 | TABLE ACCESS FULL | FTC_INV | 618K| 9062K| | 80 | | ||* 13 | HASH JOIN | | 3948K| 587M| 576M| 1965K| | ||* 14 | HASH JOIN | | 3948K| 530M| 1998M| 1867K| | ||* 15 | HASH JOIN | | 17M| 1797M| 1746M| 1072K| | ||* 16 | HASH JOIN | | 17M| 1545M| 1226M| 613K| | || 17 | TABLE ACCESS FULL | TEMP_OPEN_AR_TRANSACTIONS | 17M| 1024M| | 4856 | | || 18 | TABLE ACCESS FULL | FIN_TRANS | 552M| 15G| | 229K| | || 19 | PARTITION RANGE ALL | | | | | | 1 | 22 || 20 | TABLE ACCESS FULL | RECOGNITION_FIN_LINK | 608M| 8708M| | 120K| 1 | 22 || 21 | PARTITION RANGE ITERATOR| | | | | | 1 | KEY ||* 22 | TABLE ACCESS FULL | MEMBER_RECOGNITION | 136M| 4425M| | 637K| 1 | KEY || 23 | TABLE ACCESS FULL | MEMBER_CONTRACT | 144M| 2073M| | 42574 | | |------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):---------------------------------------------------

1 - filter(ROUND(SUM("MR"."REVENUE_AMT"*"AR"."UNAPP_PERCENT"),2)<>0 AND ROUND(SUM("MR"."COMM_AMT"*"AR"."UNAPP_PERCENT"),2)<>0) 3 - access("MCA"."REFUND_METHOD_ID"="RM"."REFUND_METHOD_ID") 5 - access("P"."PARTNER_CORPORATION_SYSID"="PC"."PARTNER_CORPORATION_SYSID") 7 - access("MCA"."PARTNER_ID"="P"."PARTNER_SYSID") 9 - access("RFL"."MEM_CONTRACT_ATTRIB_SYSID"="MCA"."MEMBER_CONTRACT_ATTRIB_SYSID") 11 - access("FT"."FTC_INV_SYSID"="FI"."FTC_INV_SYSID") 13 - access("FT"."MEMBER_CONTRACT_SYSID"="MC"."MEMBER_CONTRACT_SYSID") 14 - access("RFL"."RECOGNITION_FIN_LINK_SYSID"="MR"."RECOGNITION_FIN_LINK_SYSID") 15 - access("FT"."CUR_RECOGNITION_FIN_LINK_SYSID"="RFL"."RECOGNITION_FIN_LINK_SYSID") 16 - access("AR"."FIN_TRANS_SYSID"="FT"."FIN_TRANS_SYSID") 22 - filter("MR"."CLOSED_DATE" IS NULL AND "MR"."RECOGNITION_DATE"<="INFOCTL"."CYCLE_DATE"."MTH_CYCLE_DATE_EOD"())

Page 10: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

How does Oracle derive this plan?The Cost-Based Optimizer

The optimizer determines the most efficient way to execute a SQL statement after considering many factors related to the objects referenced and the conditions specified in the query. This determination is an important step in the processing of any SQL statement and can greatly affect execution time1

It is a program that uses various database statistics, and other “knowledge” of the data, to derive estimated costs for “all” of the various ways a given join condition or data selection may be performed. It selects the “lowest cost” method of achieving the desired result.

Most of the time this works very well.

Page 11: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

The Cost-Based Optimizer (Cont’d)

But sometimes, Oracle does not “know” the data as well as we do.

• Oracle will occasionally start with the wrong table

• Or, Oracle will occasionally choose the wrong Join or Access method, etc. for one or more tables

In these instances, we “tune” the SQL (e.g. Manually alter the SQL for execution path).

What are some ways we can do this?• Hints

– Change Join Order– Change Join Method (Hash Join, Sort Join, Nested Loops,

etc…)– Force Index Usage

• Rewrite the SQL– Prevent Index Access (Apply function to indexed column)– Use correlated sub-query vs. table join– Create an in-line view in the FROM clause

Page 12: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

The Cost-Based Optimizer (Cont’d)

Some functions of the CBO:• Evaluation of expressions and conditions

• Statement Transformation

• Choose Optimization Approach (Best Throughput, or Response Time)

• Choose Access Paths

• Choose Join Orders

• Choose Join Method

Statistics are CRUCIAL to this processing!!!

Page 13: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Figure 1-2 Cost-Based Optimizer Components

                                                                                                                                                                                          

Page 14: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Statistics generated include the following:

• Table statistics – Number of rows – Number of blocks – Average row length

• Column statistics – Number of distinct values (NDV) in column – Number of nulls in column – Data distribution (histogram)

• Index statistics – Number of leaf blocks – Levels – Clustering factor

• System statistics– I/O performance and utilization – CPU performance and utilization

Page 15: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Without statistics Oracle makes bad decisions!

w/o Stats Oracle Assumes (for tables):

Table Statistic DefaultNumber of rows

num_of_blocks * (block_size - cache_layer) / avg_row_len

Average row length 100 Bytes

Number of blocks 100 blocks

Remote – Number of rows 2000 rows

Remote – Average row length 100 bytes

Page 16: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Without statistics Oracle makes bad decisions!

w/o Stats Oracle Assumes (for indexes):

Index Statistic DefaultLevels 1

Leaf blocks 25

Leaf blocks per key 1

Data blocks per key 1

Distinct keys 100

Clustering Factor 800 (8 * number of blocks)

Page 17: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Bad Stats ExampleFIN_TRANS Table

OWNER TABLE NAME INDEX_NAME DISTINCT_KEYS

---------- ----------- ------------------------------ -------------

FDS FIN_TRANS FIN_TRANS_MEMCONSYSID 195840

TABLE_NAME NUM_ROWS BLOCKS

------------------------------ ---------- ----------

FIN_TRANS 577445040 3939004

TABLE_NAME NUM_ROWS BLOCKS

------------------------------ ---------- ----------

TMP_NFT_NEW 719 10

195,840 Member Contract Sysids in FIN_TRANS?

577M / 195,840 = 2949 Rows per key (MC_SYSID)

Page 18: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

SELECT *

FROM fin_trans ft

,tmp_nft_new tnn

WHERE tnn.member_contract_sysid = ft.member_contract_sysid

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE

(Cost=284543 Cardinality=13349 Bytes=3177062)

1 0 HASH JOIN

(Cost=284543 Card=13349 Bytes=3177062)

2 1 TABLE ACCESS (FULL) OF 'TMP_NFT_NEW’

(Cost=2 Cardinality=719 Bytes=97065)

3 1 TABLE ACCESS (FULL) OF 'FIN_TRANS’

(Cost=240055 Cardinality=577445040 Bytes=59476839120)

Bad Stats Example

Page 19: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

SET AUTOTRACE TRACEONLY EXPLAIN 1 select count(1) 2 from member_contract mc 3 ,member_contract_attrib mca 4* where mca.member_contract_attrib_sysid = cur_mem_contract_attrib_sysid/Execution Plan---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=23585 Card=1 Bytes=12) 1 0 SORT (AGGREGATE) 2 1 NESTED LOOPS (Cost=23585 Card=153843400 Bytes=1846120800) 3 2 INDEX (FAST FULL SCAN) OF 'MC_MCAS_IDX' (NON-UNIQUE)

(Cost=13745 Card=153843400 Bytes=923060400) 4 2 INDEX (UNIQUE SCAN) OF 'PK_MEMBER_CONTRACT_ATTRIB' (UNIQUE)

(Cost=1 Card=1 Bytes=6)

How do we find out Oracle’ Plan?

Using SQL*Plus Autotrace Facility

Page 20: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Or: Using the Explain Plan Stmt.

1 EXPLAIN PLAN2 SET statement_id = 'MRUCKDASCHEL' FOR3 SELECT count(1)4 FROM member_contract mc5 ,member_recognition mr6 WHERE mr.member_contract_sysid = mc.member_contract_sysid7 AND mr.recognition_date > '01-jan-2006'#> /

Explained.

Explain Plan

Set Statement Id = ‘<some id value>’

For <SQL Statement>

Such As:

Page 21: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

This will store rows in a table called: PLAN_TABLE keyed by STATEMENT_ID

These are retrieve using SQL like:SELECT decode(id, 0,'1.1',

lpad(' ', 2 * (level - 1)) || level || '.' || position) || ' ' ||

initcap(decode(object_type, null, null, object_type || ' ')) ||initcap(operation) || ' ' || decode(object_name, null,

initcap(options),'(' || initcap(options) || ') of ' ||

object_name) || ' ' ||decode(id, 0, decode(position, null, 'Rule', 'Cost = ' || position)) Query_Plan

FROM plan_table

CONNECT BY PRIOR id = parent_id

AND statement_id = USER

START WITH id = 0

AND statement_id = USER

/

Page 22: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

This will produce a plan like:QUERY_PLAN-------------------------------------------------1.1 Select Statement Cost = 1374725 2.1 Sort Aggregate 3.1 Hash Join 4.1 Unique Index (Fast Full Scan) of PK_MEMBER_CONTRACT_MEMCONSYSID 4.2 Partition Range Iterator 5.1 Table Access (Full) of MEMBER_RECOGNITION

Page 23: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

---------------------------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes |TempSpc| Cost | Pstart| Pstop ---------------------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 22 | | 1374K| | | 1 | SORT AGGREGATE | | 1 | 22 | | | | |* 2 | HASH JOIN | | 1450M| 29G| 3092M| 1374K| | | 3 | INDEX FAST FULL SCAN | PK_MEMBER_CONTRACT_MEMCONSYSID | 170M| 1139M| | 10628 | | | 4 | PARTITION RANGE ITERATOR| | | | | | 53 | 65 |* 5 | TABLE ACCESS FULL | MEMBER_RECOGNITION | 1450M| 20G| | 178K| 53 | 65 ---------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):---------------------------------------------------

2 - access("MR"."MEMBER_CONTRACT_SYSID"="MC"."MEMBER_CONTRACT_SYSID") 5 - filter("MR"."RECOGNITION_DATE">TO_DATE('2006-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))

Another way to retrieve your Plan:

SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY())

Or: @?/rdbms/admin/utlxpls

Or: @/home/mruckdas/sql/plan_out

Will Produce This:

Page 24: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

To Run Explain Plan:

Create One In Your Schema Using:@?/rdbms/admin/utlxplan

Or:Gain Access to an existing one by someone

granting you access and create a synonymCREATE SYNONYM PLAN_TABLE FOR COMMON_AREA.PLAN_TABLE;

You need access to a PLAN_TABLE

Page 25: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

How to readExplain Plan Output:

First, Understand the following:• Table Access Methods• Table Join Methods• Table Join Order

Page 26: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Table Access Methods

▬ Index Unique Scans ▬ Index Range Scans ▬ Index Range Scans Descending ▬ Index Skip Scans ▬ Full Scans ▬ Fast Full Index Scans ▬ Index Joins ▬ Bitmap Joins▬ Bitmap AND / OR

• Full Table Scans • Rowid Scans • Index Scans• Bitmap Access

• Cluster Scans • Hash Scans

Page 27: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

• Lack of Index• Large Amount

of Data• Small Table• Parallelism

• FULL Hint Given

When does this Occur?

Full Table ScanThis type of scan reads all rows from a table

and filters out all rows which do not meet the WHERE clause criteria.

This involves one logical read per row.

Page 28: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Rowid ScansA second step. Oracle first obtains the rowids of selected rows either from the table’ WHERE clause, or through an index scan of table indexes.

Locating a row by specifying its rowid is the fastest way to retrieve a single row.

Access by rowid might be required to retrieve any columns which are not present in an index.

Not Always Necessary on index access.

Definition: A Rowid specifies a datafile and the data block containing a particular Row and the location of the row in that block.

Page 29: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Index ScansA row is retrieved by traversing the

index, using the indexed column values specified by the statement.

An index scan retrieves data from an index based on the value of one or more columns in the index.

Index access involves at least two logical reads per row.

Consider the following Diagram of the B-Tree Index Structure:

There are several types of Index Scans:

B-Tree Index Organization

Page 30: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Index Unique ScanThis scan returns, at most, a single rowid. This

scan may be done when there is a UNIQUE or PRIMARY KEY constraint on the table containing the search key.

This type of scan is used when all columns of a unique B-Tree index are specified using an equality condition.

May be forced with the INDEX hint.

When Used:

Page 31: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Index Range ScanThis scan is used for accessing selective data.

The range may be bounded or unbounded.

When Used:This type of scan is used when one or more leading-columns of an index is specified in conditions such as:

• Col1 = :b1

• Col1 < :b1

• Col1 > :b1

• Col1 LIKE ‘ABC%’

• AND combination of the preceding conditions for leading columns in the index

May be forced with the INDEX hint.

Page 32: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Index Range Scan DescendingIdentical to Index Range Scan, except that data

is returned in descending order.

When Used:This type of scan is used when ordering data in descending order and that order may be satisfied by an index or when seeking a value less than a specified value.

By Default, indexed data is returned ascending order.

May be forced with the INDEX_DESC hint.

Page 33: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Index Skip ScanThis scan is used for composite indexes where

the leading-column of the index is not specified in the predicate. The index is split into logically smaller sub-indexes.

When Used:This type of scan is used when the leading-column of an index is not specified in the conditions. Skip Scanning is advantageous if there are few distinct values in the leading column of the composite index, and many distinct values in the non-leading key.

Page 34: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Index Full ScanThis is like a Full table scan, but Oracle only

reads Index blocks, one at a time. Typically scanning index blocks is faster than scanning table blocks.

When Used:This scan is used if a predicate references one of the columns in the index, not necessarily the leading column.

Or:If there is no predicate reference and:•All columns in the table referenced are in the index•At least one of the indexed columns is NOT NULL.

A Full Scan may be used to eliminate a sort operation.

Page 35: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Index Fast Full ScanThis is an alternative to a FULL table scan, when

the index contains all columns that are needed by the query, and at least one index column is NOT NULL

This scan accesses data in the index itself, without accessing the table.

The entire index is read using multi-block reads and can be parallelized. Data is NOT returned in the index order.

Restrictions: • At least one indexed column must have the NOT NULL constraint• There must be a parallel clause on the Index if FFS in parallel is desired.• The index must have been analyzed.

May be forced using the INDEX_FFS hint

Page 36: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Index JoinsThis is a hash join of several indexes that

collectively contain all of the table columns that are referenced in the query. No table access is thereby needed.

May be forced with the INDEX_JOIN hint

A bitmap join uses a bitmap for key values and a mapping function that converts each bit position to a rowid. Bitmaps can efficiently merge indexes that correspond to several conditions in a WHERE clause, using Boolean operations to resolve AND and OR conditions.

Bitmap Joins

Page 37: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Bitmap Table AccessThis is a special Method of accessing a

table whereby Oracle will combine the use of multiple B-Tree indexes according to criteria in the WHERE Clause.

Oracle will only consider if there is at least 1 bitmap index on the table.

Can involve combinations of B-Tree and Bitmap, but needn’t involve any Bitmap Idx

Rowids contained in B-Tree Indexes must be converted to bitmaps. After conversion, Boolean AND/OR operations for Bitmaps may be used.

May be forced using the INDEX_COMBINE hint

Page 38: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

This could produce a plan like:SELECT STATEMENT SORT AGGREGATE BITMAP CONVERSION COUNT BITMAP OR BITMAP AND BITMAP INDEX c1_ind SINGLE VALUE BITMAP CONVERSION FROM ROWIDS INDEX c2_ind RANGE SCAN BITMAP CONVERSION FROM ROWIDS SORT ORDER BY INDEX c3_ind RANGE SCAN

Page 39: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

How does the CBO choose the Access Path?• The optimizer first determines which access

paths are available by examining the conditions in the statement's WHERE clause and its FROM clause2.

• The optimizer then generates a set of possible execution plans using available access paths and estimates the cost of each plan, using the statistics for the index, columns, and tables accessible to the statement2.

• The lowest estimated cost wins.

Page 40: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Join Methods• Nested Loop Joins • Hash Joins • Sort Merge Joins • Cartesian Joins • Outer Joins

Page 41: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Nested Loop JoinOne table is designated as an outer (Driving)

table, and the other the inner table. All matching rows in the inner table are accessed for each row in the outer table.

Consider the following Nested Loop:

For X in 1 to 10 Loop (Outer)For Y in 1 to 10 Loop

(Inner)i = i + 1print i: X , Y

End LoopEnd Loop

Page 42: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Nested Loop Join (cont’d)

• Ideally, the inner table access is some type of index access, or the table s/b very small.

• Otherwise, a Hash Join may be more efficient.

• The order of tables in this type of Join is Very Important.

• Nested Loops may be Nested inside other Nested Loops.

Page 43: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Hash JoinThis Join Method is used to join large

data sets.

The optimizer uses the smaller of two data sources to build a hash table, in Memory, if possible, on the Join Key.

The optimizer scans the larger table, probing the hash table to find the joined rows.

Hash Table: DefinitionThe join key is hashed to an index entry in a hash table.

The hash table is an array and the row that goes with the hash key is stored in that entry.

Page 44: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Hash Join (cont’d)

When Used:The Optimizer will use a hash join to join two tables if they are joined using an equi-join (i.e. a.col1 = b.col1) And if either of the following conditions are met:• A large amount of data needs to be joined.• A large fraction of the table needs to be joined.

Hash Joins can be effective when the lack of a useful index renders Nested Loop joins ineffective.3

Page 45: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Sort Merge JoinCan be used to join rows from two

independent sources.Generally, perform worse than Hash

Joins, except if the following are true:– The Row Sources are sorted already– A Sort Operation does not have to be done.

Benefit may be lost if slower table access method is chosen (e.g. Full Table Scan)

Useful when an inequality condition (i.e. <, <=, >, or >=) is selected

Page 46: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Sort Merge Join (cont’d)

Sort / Merge Joins perform better than Nested Loops Joins for large data sets.

Two Steps: (No Driving Table as in NL Join)

1. Sort: Both inputs are Sorted on Join Key2. Merge: Two sorted lists are merged

Page 47: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Sort Merge Join (cont’d)

When Used:– When Join Condition is not an equi-join– Parameter OPTIMIZER_MODE is set to RULE– Parameter HASH_JOIN_ENABLE is set to FALSE– Because data must already be sorted by other

operations, optimizer thinks SJ is cheaper than HJ

– Estimated Cost: Optimizer thinks SJ cost less than HJ cost based on HASH_AREA_SIZE and SORT_AREA_SIZE

– The USE_MERGE hint has been specified.

Page 48: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Cartesian JoinA join where every row from one data source

is joined with every row from another data source. This creates a Cartesian Product.

Happens when a table is listed in the FROM clause, but not joined to any other table in the WHERE clause.

Generally, “BAD NEWS!”, resulting from poorly written SQL

Sometimes, rarely, the optimizer thinks this type of join is less costly and induces.

Page 49: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Outer JoinExtends the results of a simple join.Returns all rows that satisfy the Join

Condition plus some or all rows from one table where the join condition is not satisfied.

Similar But Different Types:• Nested Loop Outer Join• Hash Join Outer Join• Sort Merge Outer Join• Full Outer Join

Page 50: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Join OrderNow we need to know how to analyze an

Explained Plan and understand what is done when.

Remember our Nested Loop example:For X in 1 to 10 Loop (Outer)

For Y in 1 to 10 Loop (Inner)

i = i + 1print i: X , Y

End LoopEnd Loop

Page 51: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Join Order (Cont’d)

Q:What is the first real instruction executed?A: i = i + 1

The first innermost item from the top is the first instruction executed.

For X in 1 to 10 Loop (Outer)For Y in 1 to 10 Loop

(Inner)i = i + 1print i: X , Y

End LoopEnd Loop

Page 52: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Join Order (Cont’d)

Similarly: 1.1 SELECT STATEMENT Optimizer=CHOOSE(Cost=23585 Card=1 Bytes=12) 2.1 SORT (AGGREGATE) 3.1 NESTED LOOPS (Cost=23585 Card=153843400 Bytes=1846120800) 4.1 INDEX (FAST FULL SCAN) OF 'MC_MCAS_IDX' (NON-UNIQUE) (Cost=13745 Card=153843400 Bytes=923060400) 4.2 INDEX (UNIQUE SCAN) OF 'PK_MEMBER_CONTRACT_ATTRIB' (UNIQUE) (Cost=1 Card=1 Bytes=6)

First Step?

4.1 Index Access (Fast Full Scan)

Then what?

For the first value returned by 4.1, and every other, 4.2 is performed.

3.1 Indicates that for every row 4.1 returns 4.2 is repeated to EOT (Index) 4.1

2.1 Sort (Aggregate) = COUNT(1)

Page 53: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

ID Query Plan----------------------------------------------------------------------------------------------------------------- 1 | Select Statement Choose Cost=743,837 Rows=27,748 COST/ROW = 27 2 | Sort Group By Cost=743,837 Rows=27,748 3* | Hash Join Cost=743,528 Rows=27,748 4 | View Cost=287,095 Rows=5,772 5 | Sort Group By Cost=287,095 Rows=5,772 6* | Hash Join Cost=286,920 Rows=106,262 7* | Hash Join Cost=286,616 Rows=106,262 8 | Table Access (Full) of REJ_CRED_MBRS_BAL Analyzed Cost=2 Rows=5,772 9 | Table Access (Full) of FIN_TRANS Analyzed Cost=272,992 Rows=655,903,400 10 | Table Access (Full) of FTC_INV Analyzed Cost=91 Rows=697,780 11 | View Cost=456,424 Rows=27,748 12 | Sort Group By Cost=456,424 Rows=27,748 13* | Hash Join Cost=456,189 Rows=27,748 14* | Hash Join Cost=445,299 Rows=776,936 15 | Merge Join Cartesian Cost=23,090 Rows=161,616 16 | Nested Loops Cost=11,546 Rows=5,772 17 | Table Access (Full) of REJ_CRED_MBRS_BAL Analyzed Cost=2 Rows=5,772 18 | Table Access (By Index Rowid) of MEMBER_CONTRACT Analyzed Cost=2 Rows=1 19* | Unique Index (Unique Scan) of PK_MEMBER_CONTRACT_MEMCONSYSID Analyzed Cost=1 Rows=1 20 | Buffer Sort Cost=23,088 Rows=28 21 | Table Access (Full) of REFUND_METHOD Analyzed Cost=2 Rows=28 22 | Table Access (Full) of AR_DISTRIB_DETAILS Analyzed Cost=124,239 Rows=784,295,220 23 | Table Access (Full) of MEMBER_CONTRACT_ATTRIB Analyzed Cost=4,744 Rows=10,223,240

Predicate Information (identified by operation id):-------------------------------------------------- 3 - Access - ("A"."MEMBER_CONTRACT_SYSID"="B"."MEMBER_CONTRACT_SYSID") 6 - Access - ("FI"."FTC_INV_SYSID"="FT"."FTC_INV_SYSID") 7 - Access - ("A"."MEMBER_CONTRACT_SYSID"="FT"."MEMBER_CONTRACT_SYSID") 13 - Access - ("MC"."CUR_MEM_CONTRACT_ATTRIB_SYSID"="MCA"."MEMBER_CONTRACT_ATTRIB_SYSID“ AND

"MCA"."REFUND_METHOD_ID"="RM"."REFUND_METHOD_ID") 14 - Access - ("MC"."MEMBER_CONTRACT_SYSID"="ARDD"."MEMBER_CONTRACT_SYSID") 19 - Access - ("A"."MEMBER_CONTRACT_SYSID"="MC"."MEMBER_CONTRACT_SYSID")

~/src/tuning_requests/2006_requests/20060823_bsperling/plan_orig_query.10835.log

Let’s examine a few:

Page 54: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

ID Query Plan----------------------------------------------------------------------------------------------- 1 | Insert Statement Choose Cost=1,779,896 Rows=1,128,413 COST/ROW = 2 2 | Sort Group By Cost=1,779,896 Rows=1,128,413 3* | Hash Join Cost=1,769,786 Rows=1,128,413 4 | Table Access (Full) of PARTNER_CORPORATION Analyzed Cost=2 Rows=1,379 5* | Hash Join Cost=1,769,747 Rows=1,128,413 6 | Table Access (Full) of PARTNER Analyzed Cost=3 Rows=4,056 7* | Hash Join Cost=1,769,677 Rows=1,128,413 8* | Table Access (Full) of MEMBER_CONTRACT_ATTRIB Analyzed Cost=4,744 Rows=851,937 9* | Hash Join Cost=1,763,458 Rows=1,128,413 10 | Table Access (Full) of CA_MONTHLY_MEMBERS Analyzed Cost=3 Rows=21,400 11* | Hash Join Cost=1,757,904 Rows=27,603,992 12* | Table Access (Full) of MEMBER_CONTRACT Analyzed Cost=51,344 Rows=529,252 13 | Partition Range Iterator Partitions: KEY - 65 14* | Table Access (Full) of MEMBER_RECOGNITION Analyzed Cost=764,775 Rows=2,022,571,722

Partitions: KEY - 65

Predicate Information (identified by operation id):-------------------------------------------------- 3 - Access - ("P"."PARTNER_CORPORATION_SYSID"="PC"."PARTNER_CORPORATION_SYSID") 5 - Access - ("MCA"."PARTNER_ID"="P"."PARTNER_SYSID") 7 - Access - ("MC"."CUR_MEM_CONTRACT_ATTRIB_SYSID"="MCA"."MEMBER_CONTRACT_ATTRIB_SYSID") 8 - Filter - ("MCA"."BILLING_METHOD_ID"=3) 9 - Access - ("A"."MEMBERSHIP_NUMBER"="MC"."MEM_CONTRACT_ID") 11 - Access - ("MR"."MEMBER_CONTRACT_SYSID"="MC"."MEMBER_CONTRACT_SYSID") 12 - Filter - ("MC"."SERVICE"='SHP' AND "MC"."TERM_COUNTER"<=11) 14 - Filter - ("MR"."CLOSED_DATE" IS NULL AND "MR"."RECOGNITION_DATE">'31-MAR-05')

~/src/tuning_requests/2006_requests/20060706_bsperling/plan_orig_query.7409.log

Page 55: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

ID Query Plan----------------------------------------------------------------------------------------------- 1 | Select Statement Choose Cost=10,429,451 Rows=401,107,070 COST/ROW = 0 2 | Sort Group By Cost=10,429,451 Rows=401,107,070 3 | Merge Join Cartesian Cost=93,689 Rows=401,107,070 4* | Table Access (By Index Rowid) of FIN_TRANS Analyzed Cost=75 Rows=1 5 | Nested Loops Cost=43,388 Rows=621 6 | Nested Loops Cost=9,188 Rows=456 7* | Hash Join Cost=4,232 Rows=118 8 | Nested Loops Cost=4,228 Rows=118 9* | Hash Join Cost=4,228 Rows=118 10 | Nested Loops Cost=3 Rows=28 11 | Table Access (By Index Rowid) of BILLING_METHOD Analyzed Cost=1 Rows=1 12* | Unique Index (Unique Scan) of XPKBILLING_METHOD Analyzed Rows=1 13 | Table Access (Full) of REFUND_METHOD Analyzed Cost=2 Rows=28 14* | Table Access (By Index Rowid) of MEMBER_CONTRACT_ATTRIB Analyzed Cost=4,224 Rows=1,421 15* | Non-Unique Index (Range Scan) of MEMCA_MEMEXPDT_IDX Analyzed Cost=88 Rows=40,928 16* | Unique Index (Unique Scan) of XPKTERM_TYPE Analyzed Rows=1 17 | Table Access (Full) of BILLING_GROUP Analyzed Cost=3 Rows=3,042 18* | Table Access (By Index Rowid) of MEMBER_CONTRACT Analyzed Cost=42 Rows=4 19* | Non-Unique Index (Range Scan) of MC_MCAS_IDX Analyzed Cost=2 Rows=75 20* | Non-Unique Index (Range Scan) of FIN_TRANS_MEMCONSYSID Analyzed Cost=2 Rows=19 21 | Sort Aggregate Rows=1 22 | Partition Range Iterator Partitions: KEY - KEY 23* | Table Access (By Local Index Rowid) of AR_AP_FIN_LINK Analyzed Cost=16,658 Rows=260,943 Partitions: KEY - KEY 24* | Non-Unique Index (Range Scan) of AR_AP_FIN_LINK_PROCDATE Analyzed Cost=3,488 Rows=2,818,189 Partitions: KEY - KEY 25 | Buffer Sort Cost=10,429,376 Rows=646,320 26 | Unique Index (Fast Full Scan) of FTC_INV_TYPNUMSEQ Analyzed Cost=81 Rows=646,320

Predicate Information (identified by operation id):-------------------------------------------------- 4 - Filter - ("FT"."FIN_TRANS_TYPE"<>'J' AND "FT"."FIN_TRANS_TYPE"<>'T' AND "FT"."FIN_TRANS_SYSID">= (SELECT /*+ */

MIN("AR_AP_FIN_LINK"."FIN_TRANS_SYSID") FROM "FDS"."AR_AP_FIN_LINK" "AR_AP_FIN_LINK" WHERE "AR_AP_FIN_LINK"."PROCESSED_DATE"<"INFOCTL"."CYCLE_DATE"."CYCLE_DATE"()+1 AND "AR_AP_FIN_LINK"."PROCESSED_DATE">"INFOCTL"."CYCLE_DATE"."CYCLE_DATE_BOM"() AND "AR_AP_FIN_LINK"."PROCESS_CODE"='F'))

7 - Access - ("MCA"."BILLING_GROUP_SEQ_NUM"="BG"."BILLING_GROUP_SYSID") 9 - Access - ("MCA"."BILLING_METHOD_ID"="BM"."BILLING_METHOD_ID" AND "MCA"."REFUND_METHOD_ID"="RM"."REFUND_METHOD_ID") 12 - Access - ("BM"."BILLING_METHOD_ID"=3) 14 - Filter - ("MCA"."BILLING_METHOD_ID"=3 AND "MCA"."COMPANY_CODE"<>'NON') 15 - Access - ("MCA"."MEM_EXP_DATE">ADD_MONTHS("INFOCTL"."CYCLE_DATE"."CYCLE_DATE_EOM"(),-3) AND

"MCA"."MEM_EXP_DATE"<"INFOCTL"."CYCLE_DATE"."CYCLE_DATE_EOM"()) 16 - Access - ("MCA"."TERM_TYPE_ID"="TT"."TERM_TYPE_ID") 18 - Filter - ("MC"."RECORD_ADD_DATE">"INFOCTL"."CYCLE_DATE"."CYCLE_DATE_BOM"()) 19 - Access - ("MC"."CUR_MEM_CONTRACT_ATTRIB_SYSID"="MCA"."MEMBER_CONTRACT_ATTRIB_SYSID") 20 - Access - ("MC"."MEMBER_CONTRACT_SYSID"="FT"."MEMBER_CONTRACT_SYSID") 23 - Filter - ("AR_AP_FIN_LINK"."PROCESS_CODE"='F') 24 - Access - ("AR_AP_FIN_LINK"."PROCESSED_DATE">"INFOCTL"."CYCLE_DATE"."CYCLE_DATE_BOM"() AND

"AR_AP_FIN_LINK"."PROCESSED_DATE"<"INFOCTL"."CYCLE_DATE"."CYCLE_DATE"()+1)

~/src/tuning_requests/2006_requests/20060511_bsperling/plan_orig_query.21000.log

Page 56: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Ok. So we know how to read a Plan…

Now What?

Where to go from here?

How do we Tune the SQL?

Page 57: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Where to go from here?Remember:

In most Cases, Oracle will make the right decision.

“If it ain’t broke, don’t fix it!”

The single most-effective way to tune any SQL statement:

… reduce the amount of work that Oracle needs to do, to return the desired result

Your Tuning Goals:

What is acceptable performance?

Achieve it and move on!!!!

Page 58: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Where to go from here? (Cont’d)

Use these to evaluate the plan.1. Look at Oracle’ chosen join order.

With your understanding of the underlying data, does the initial join produce the smallest result set first?

Does the table Oracle decides to start with make sense (i.e. Will produce the smallest data set, or could be easily joined to an indexed column?)

Is there any Join Criteria that you could add to give Oracle an opportunity make more selective joins (e.g. Smaller Result Set initially)

Page 59: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Where to go from here? (Cont’d)

2. Look at Oracle’ chosen join type for each set.

With your understanding of the underlying data, and the query, does Oracle select the right join type for each set of data?

Are large data sets being joined (i.e. Hash Join is better)?

Is the “driving data set” sufficiently small, and an index available, to support Nested Loops?

Did you expect Index access, and got Full Table scan, or vice-versa? Is Oracle smarter than you? (e.g. Did it make the right decision?)

Page 60: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Where to go from here? (Cont’d)

3. Look at Oracle’ chosen method of table access.

With your understanding of the underlying data, and the query, does Oracle select the right method to access each table?

Did you expect Index access, and got Full Table scan, or vice-versa? Is Oracle smarter than you? (e.g. Did it make the right decision?)

Page 61: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Where to go from here? (Cont’d)

3. Oracle’ chosen method of table access. (cont’d)

What Filters are in the Where clause to limit data? Is Oracle starting with the Filtered Data?

Could you add selection criteria to the WHERE clause to cause the amount of data selected (and joined) to be reduced?

Could you avoid large amounts of data being needlessly scanned by adding a partition key to your selection criteria?

Page 62: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Where to go from here? (Cont’d)

4. Check Oracle’ Assumptions

With your understanding of the underlying data, and the query, does Oracle make the correct assumptions (estimates) regarding the amount of data that will be returned at each step?

Consider the following example:

Page 63: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

SELECT sub.row_id AS subscription_id ,pkg.row_id AS pkg_row_id ,inv.row_id inv_row_id ,pay.con_id ,pay.actl_pay_dt ,pay.x_mlov_pay_type_cd ,pay.x_mlov_status_cd ,pay.pay_amt ,pkg.x_billing_cycle ,pl.x_pay_freq ,pli.x_membership_fee_trial ,sub.x_promo_cd ,sub.createdFROM siebel.s_src_payment pay ,siebel.s_invoice inv ,siebel.s_pri_lst_item pli ,siebel.s_pri_lst pl ,siebel.s_agree_item sub ,siebel.s_prod_int pkgWHERE pkg.prod_cd = 'Package'AND pkg.x_pkg_type IS NOT NULLAND pkg.row_id = sub.prod_int_idAND pl.row_id = sub.pri_lst_idAND pkg.row_id = pli.prod_idAND pli.pri_lst_id = sub.pri_lst_idAND sub.row_id = inv.agree_item_idAND inv.row_id = pay.pr_invoice_idAND pay.pay_amt > 0 AND pay.pay_amt <> pli.x_membership_fee_trialAND pay.x_pay_flow_type_cd = 'Debit'AND pay.x_transact_reason = 'Fees'AND pay.x_mlov_status_cd <> 'Cancelled'ORDER BY sub.row_id ,pay.actl_pay_dt ,inv.row_id

Consider this SQL…

Page 64: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

ID Query Plan--------------------------------------------------------------------------------------------------------------------- 1 | Select Statement Choose Cost=16,091 Rows=741 COST/ROW = 22 2 | Sort Order By Cost=16,091 Rows=741 3 | Nested Loops Cost=16,056 Rows=741 4 | Nested Loops Cost=16,049 Rows=741 5* | Hash Join Cost=15,376 Rows=22,429 6 | Nested Loops Cost=6,514 Rows=155,073 7 | Nested Loops Cost=5 Rows=353 8* | Table Access (By Index Rowid) of S_PROD_INT Analyzed Cost=1 Rows=78 9* | Non-Unique Index (Skip Scan) of S_PROD_INT_F11 Analyzed Cost=13 Rows=1,019 10 | Table Access (By Index Rowid) of S_PRI_LST_ITEM Analyzed Cost=1 Rows=5 11* | Unique Index (Range Scan) of S_PRI_LST_ITEM_U1 Analyzed Cost=2 Rows=5 12* | Table Access (By Index Rowid) of S_AGREE_ITEM Analyzed Cost=6,514 Rows=440 13 | And-Equal 14* | Non-Unique Index (Range Scan) of S_AGREE_ITEM_F5 Analyzed 15* | Non-Unique Index (Range Scan) of S_AGREE_ITEM_F1 Analyzed Cost=714 Rows=134,525 16* | View () of index$_join$_002 Cost=6,187 Rows=5,019,953 17* | Hash Join Cost=15,376 Rows=22,429 18* | Non-Unique Index (Fast Full Scan) of S_INVOICE_F20 Analyzed Cost=263 Rows=5,019,953 19 | Unique Index (Fast Full Scan) of S_INVOICE_P1 Analyzed Cost=263 Rows=5,019,953 20* | Table Access (By Index Rowid) of S_SRC_PAYMENT Analyzed Cost=1 Rows=1 21* | Non-Unique Index (Range Scan) of S_SRC_PAYMENT_V1 Analyzed Cost=2 Rows=1 22 | Table Access (By Index Rowid) of S_PRI_LST Analyzed Cost=1 Rows=1 23* | Unique Index (Unique Scan) of S_PRI_LST_P1 Analyzed Rows=1

Predicate Information (identified by operation id):----------------------------------------------------------------------- 5 - Access - ("SUB"."ROW_ID"="INV"."AGREE_ITEM_ID") 8 - Filter - ("PKG"."X_PKG_TYPE" IS NOT NULL) 9 - Access - ("PKG"."PROD_CD"='Package') Filter - ("PKG"."PROD_CD"='Package') 11 - Access - ("PKG"."ROW_ID"="PLI"."PROD_ID") 12 - Filter - ("PKG"."ROW_ID"="SUB"."PROD_INT_ID" AND "PLI"."PRI_LST_ID"="SUB"."PRI_LST_ID") 14 - Access - ("PLI"."PRI_LST_ID"="SUB"."PRI_LST_ID") 15 - Access - ("PKG"."ROW_ID"="SUB"."PROD_INT_ID") 16 - Filter - ("INV"."AGREE_ITEM_ID" IS NOT NULL) 17 - Access - ("indexjoin$_alias$_008".ROWID="indexjoin$_alias$_007".ROWID) 18 - Filter - ("indexjoin$_alias$_007"."AGREE_ITEM_ID" IS NOT NULL) 20 - Filter - ("PAY"."PAY_AMT">0 AND "PAY"."PAY_AMT"<>"PLI"."X_MEMBERSHIP_FEE_TRIAL" AND "PAY"."X_PAY_FLOW_TYPE_CD"='Debit‘ AND "PAY"."X_TRANSACT_REASON "='Fees' AND "PAY"."X_MLOV_STATUS_CD"<>'Cancelled') 21 - Access - ("INV"."ROW_ID"="PAY"."PR_INVOICE_ID") 23 - Access - ("PL"."ROW_ID"="SUB"."PRI_LST_ID")

~/src/tuning_requests/2008_requests/2008_04_04_siebel_lrq

With this Plan…

Page 65: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

SELECT COUNT(1)

FROM siebel.s_prod_int pkg

,siebel.s_pri_lst_item pli

WHERE pkg.prod_cd = 'Package'

AND pkg.x_pkg_type IS NOT NULL

AND pkg.row_id = pli.prod_id

/

...

COUNT(1)

----------

1361

1 row selected.

Elapsed: 00:00:01.22

No errors.

run_sql.sh : End : Mon Aug 11 17:34:42 EDT 2008

Page 66: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

ID Query Plan--------------------------------------------------------------------------------------------------------------------- 1 | Select Statement Choose Cost=16,091 Rows=741 COST/ROW = 22 2 | Sort Order By Cost=16,091 Rows=741 3 | Nested Loops Cost=16,056 Rows=741 4 | Nested Loops Cost=16,049 Rows=741 5* | Hash Join Cost=15,376 Rows=22,429 6 | Nested Loops Cost=6,514 Rows=155,073 7 | Nested Loops Cost=5 Rows=353 8* | Table Access (By Index Rowid) of S_PROD_INT Analyzed Cost=1 Rows=78 9* | Non-Unique Index (Skip Scan) of S_PROD_INT_F11 Analyzed Cost=13 Rows=1,019 10 | Table Access (By Index Rowid) of S_PRI_LST_ITEM Analyzed Cost=1 Rows=5 11* | Unique Index (Range Scan) of S_PRI_LST_ITEM_U1 Analyzed Cost=2 Rows=5 12* | Table Access (By Index Rowid) of S_AGREE_ITEM Analyzed Cost=6,514 Rows=440 13 | And-Equal 14* | Non-Unique Index (Range Scan) of S_AGREE_ITEM_F5 Analyzed 15* | Non-Unique Index (Range Scan) of S_AGREE_ITEM_F1 Analyzed Cost=714 Rows=134,525 16* | View () of index$_join$_002 Cost=6,187 Rows=5,019,953 17* | Hash Join Cost=15,376 Rows=22,429 18* | Non-Unique Index (Fast Full Scan) of S_INVOICE_F20 Analyzed Cost=263 Rows=5,019,953 19 | Unique Index (Fast Full Scan) of S_INVOICE_P1 Analyzed Cost=263 Rows=5,019,953 20* | Table Access (By Index Rowid) of S_SRC_PAYMENT Analyzed Cost=1 Rows=1 21* | Non-Unique Index (Range Scan) of S_SRC_PAYMENT_V1 Analyzed Cost=2 Rows=1 22 | Table Access (By Index Rowid) of S_PRI_LST Analyzed Cost=1 Rows=1 23* | Unique Index (Unique Scan) of S_PRI_LST_P1 Analyzed Rows=1

Predicate Information (identified by operation id):----------------------------------------------------------------------- 5 - Access - ("SUB"."ROW_ID"="INV"."AGREE_ITEM_ID") 8 - Filter - ("PKG"."X_PKG_TYPE" IS NOT NULL) 9 - Access - ("PKG"."PROD_CD"='Package') Filter - ("PKG"."PROD_CD"='Package') 11 - Access - ("PKG"."ROW_ID"="PLI"."PROD_ID") 12 - Filter - ("PKG"."ROW_ID"="SUB"."PROD_INT_ID" AND "PLI"."PRI_LST_ID"="SUB"."PRI_LST_ID") 14 - Access - ("PLI"."PRI_LST_ID"="SUB"."PRI_LST_ID") 15 - Access - ("PKG"."ROW_ID"="SUB"."PROD_INT_ID") 16 - Filter - ("INV"."AGREE_ITEM_ID" IS NOT NULL) 17 - Access - ("indexjoin$_alias$_008".ROWID="indexjoin$_alias$_007".ROWID) 18 - Filter - ("indexjoin$_alias$_007"."AGREE_ITEM_ID" IS NOT NULL) 20 - Filter - ("PAY"."PAY_AMT">0 AND "PAY"."PAY_AMT"<>"PLI"."X_MEMBERSHIP_FEE_TRIAL" AND "PAY"."X_PAY_FLOW_TYPE_CD"='Debit‘ AND "PAY"."X_TRANSACT_REASON "='Fees' AND "PAY"."X_MLOV_STATUS_CD"<>'Cancelled') 21 - Access - ("INV"."ROW_ID"="PAY"."PR_INVOICE_ID") 23 - Access - ("PL"."ROW_ID"="SUB"."PRI_LST_ID")

~/src/tuning_requests/2008_requests/2008_04_04_siebel_lrq

Page 67: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

SELECT COUNT(1)

FROM siebel.s_prod_int pkg

,siebel.s_pri_lst_item pli

,siebel.s_agree_item subWHERE pkg.prod_cd = 'Package'

AND pkg.x_pkg_type IS NOT NULL

AND pkg.row_id = pli.prod_id

AND sub.pri_lst_id = pli.pri_lst_id/

...

COUNT(1)

----------

18958864

1 row selected.

Elapsed: 00:03:39.73

No errors.

run_sql.sh : Begin : Mon Aug 11 18:06:24 EDT 2008

6 | Nested Loops Cost=6,514 Rows=155,073 7 | Nested Loops Cost=5 Rows=353 8* | Table Access (By Index Rowid) of S_PROD_INT Analyzed Cost=1 Rows=78 9* | Non-Unique Index (Skip Scan) of S_PROD_INT_F11 Analyzed Cost=13 Rows=1,019 10 | Table Access (By Index Rowid) of S_PRI_LST_ITEM Analyzed Cost=1 Rows=5 11* | Unique Index (Range Scan) of S_PRI_LST_ITEM_U1 Analyzed Cost=2 Rows=5 12* | Table Access (By Index Rowid) of S_AGREE_ITEM Analyzed Cost=6,514 Rows=440 13 | And-Equal 14* | Non-Unique Index (Range Scan) of S_AGREE_ITEM_F5 Analyzed 15* | Non-Unique Index (Range Scan) of S_AGREE_ITEM_F1 Analyzed Cost=714 Rows=134,525

1 SELECT table_name 2 ,owner 3 ,num_rows 4 ,partitioned 5 FROM dba_tables 6* WHERE table_name = UPPER('S_AGREE_ITEM')

MRUCKDASCHEL@elizabeth_crmuk2 SQL> /

TABLE_NAME OWNER NUM_ROWS PAR------------------------------ -------------------- ---------- ---S_AGREE_ITEM SIEBEL 36494164 NO

~19M / 155K = 122 Times More rows than expected.

~19M / 36M = 52% of Rows in Table

That is a significant difference!!!!

Page 68: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

What are some ways we can alter this plan?

• Rewrite and/or modify the SQL:– Force Index Usage Elimination (WHERE)– Modify selection criteria to WHERE (i.e.

Partition Key)– Use Correlated Sub-Query (EXISTS) rather

than Join• Alter the Database and/or Session (Not

too common, other than Indexes)

• Add Hints (s/b last resort)

Page 69: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Plan Modification:1.Enable Index Usage / Partition Pruning

– If a Function is applied to an indexed column in the WHERE clause, the Index cannot be used.

– Same goes for Partition Pruning. If a function is applied to the partition key column, partition pruning CANNOT occur.

– Conversly, the application of a Function may be used eliminate the usage of an index.

What is Partition Pruning???

On a partitioned table or index, if the partition’ key is referenced in the WHERE clause, Oracle will only access those Partitions that have that/those partition key value(s)

Page 70: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Plan Modification: (Cont’d)

2. Modify Selection Criteria to WHERE clause:

– If Oracle is not using a Join Method, Join Order, or Table Access that you think should be used, you can try adding/deleting Join conditions which you know to be true (or are also true).

– For example, if a Join is being done to a table that is redundant (e.g. A join on the Primary Key AND another set of columns from the same two tables, unnecessary Table Access may occur.

Page 71: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Plan Modification: (Cont’d)

3. Use correlated sub-query rather than join.

Instead of coding this:SELECT MC.MEM_CONTRACT_IDFROM MEMBER_CONTRACT MC ,MC_TEMP_TABLE MCTWHERE MCT.MC_SYSID = MC.MEMBER_CONTRACT_SYSID/

Page 72: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Plan Modification: (Cont’d)

3. Use correlated sub-query rather than join.

Consider Doing This:SELECT MC.MEM_CONTRACT_IDFROM MEMBER_CONTRACT MCWHERE EXISTS ( SELECT 1 FROM MC_TEMP_TABLE MCT WHERE MCT.MC_SYSID = MC.MEMBER_CONTRACT_SYSID)/

(Assuming idx on MCT.MC_SYSID)

Page 73: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

Plan Modification: (Cont’d)

4. Hinting

– Hints are not really “Hints”

They are Directives!!!!!

– Should be used as a “last Resort”.

– Use CAUTION when storing hard-coded in application code.

– Consider employing Parallelism

Page 74: SQL Tuning 101 excerpt: Explain Plan A Logical Approach Bymruckdaschel@affiniongroup.com Michael Ruckdaschel Affinion Group International.

I’m probably over my time limit!

• We talked about how to understand what an Explain Plan is telling us

• Table Access Methods, Join Methods, and Join Orders

• We discussed how we can evaluate this plan, and alter it intelligently to achieve our objectives.


Recommended