Sie sind auf Seite 1von 67

4

Optimizer Operators

Copyright 2008, Oracle. All rights reserved.

Objectives
After completing this lesson, you should be able to:
Describe most of the SQL operators
List the possible access paths
Explain how join operations are performed

4-2

Copyright 2008, Oracle. All rights reserved.

Row Source Operations


Unary operations
Access Path

Binary operations
Joins

N-ary operations

4-3

Copyright 2008, Oracle. All rights reserved.

Main Structures and Access Paths


Structures

Access Paths
1. Full Table Scan

Tables

2. Rowid Scan
3. Sample Table Scan
4. Index Scan (Unique)
5. Index Scan (Range)
6. Index Scan (Full)

Indexes

7. Index Scan (Fast Full)


8. Index Scan (Skip)
9. Index Scan (Index Join)
10. Using Bitmap Indexes
11. Combining Bitmap Indexes

4-4

Copyright 2008, Oracle. All rights reserved.

Full Table Scan


Performs multiblock reads
(here DB_FILE_MULTIBLOCK_READ_COUNT = 4)
Reads all formatted blocks below the high-water mark HWM
May filter rows
B B B B ... B B B B B
Faster than index
range scans for large amount of data
select * from emp where ename='King';
--------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------|
0 | SELECT STATEMENT |
|
1 |
37 |
3
(0)|
|* 1 | TABLE ACCESS FULL| EMP |
1 |
37 |
3
(0)|
--------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - filter("ENAME"='King')

4-5

Copyright 2008, Oracle. All rights reserved.

Full Table Scans: Use Cases

4-6

No suitable index
Low selectivity filters (or no filters)
Small table
High degree of parallelism
Full table scan hint: FULL (<table name>)

Copyright 2008, Oracle. All rights reserved.

ROWID Scan
select * from scott.emp where rowid='AAAQ+LAAEAAAAAfAAJ';

Block 6959Row 2
4-7

2145,MH,V,20,

1034,JF,V,10,

-----------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost |
-----------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
37 |
1|
|
1 | TABLE ACCESS BY USER ROWID| EMP |
1 |
37 |
1|
------------------------------------------------------------------

Row migration

Copyright 2008, Oracle. All rights reserved.

Sample Table Scans

SELECT * FROM emp SAMPLE BLOCK (10) [SEED (1)];


--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
4 |
99 |
2
(0)|
|
1 | TABLE ACCESS SAMPLE| EMP |
4 |
99 |
2
(0)|
---------------------------------------------------------------------

4-8

Copyright 2008, Oracle. All rights reserved.

Indexes: Overview
Index storage techniques:
B*-tree indexes: The default and the most common
Normal
Function based: Precomputed value of a function or
expression
Index-organized table (IOT)
Bitmap indexes
Cluster indexes: Defined specifically for cluster

Index attributes:
Key compression
Reverse key
Ascending, descending

Domain indexes: Specific to an application or cartridge


4 - 10

Copyright 2008, Oracle. All rights reserved.

Normal B*-tree Indexes


Index entry
Root

Branch
Index entry header
Key column length
Leaf

Key column value


rowid

Table data retrieved by using rowid


4 - 12

Copyright 2008, Oracle. All rights reserved.

Index Scans
Types of index scans:
Unique
Min/Max
Range (Descending)
Skip
Full and fast full
Index join

B-Tree index IX_EMP

B : block
Table EMP

B
4 - 13

Copyright 2008, Oracle. All rights reserved.

Index Unique Scan

index UNIQUE Scan PK_EMP

create unique index PK_EMP on EMP(empno)


select * from emp where empno = 9999;
-------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost|
-------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
37 |
1|
|
1 | TABLE ACCESS BY INDEX ROWID| EMP
|
1 |
37 |
1|
|
2 |
INDEX UNIQUE SCAN
| PK_EMP |
1 |
|
0|
-------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access("EMPNO"=9999)

4 - 14

Copyright 2008, Oracle. All rights reserved.

Index Range Scan


Index Range SCAN I_DEPTNO

create index I_DEPTNO on EMP(deptno);


select /*+ INDEX(EMP I_DEPTNO) */ *
from emp where deptno = 10 and sal > 1000;
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
3 |
261 |
2
|
1 | TABLE ACCESS BY INDEX ROWID| EMP
|
3 |
261 |
2
|
2 |
INDEX RANGE SCAN
| I_DEPTNO |
3 |
|
1
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - filter("SAL">1000)
2 - access("DEPTNO"=10)

4 - 15

Copyright 2008, Oracle. All rights reserved.

Index Range Scan: Descending


Index Range SCAN IDX

create index IDX on EMP(deptno);

select * from emp where deptno>20 order by deptno desc;


--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost
|
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
6 |
522 |
2|
|
1 | TABLE ACCESS BY INDEX ROWID| EMP |
6 |
522 |
2|
|
2 | INDEX RANGE SCAN DESCENDING| IDX |
6 |
|
1|
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access("DEPTNO">20)

4 - 16

Copyright 2008, Oracle. All rights reserved.

Descending Index Range Scan


Index Range SCAN IX_D

create index IX_D on EMP(deptno desc);


select * from emp where deptno <30;
--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost
|
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
9 |
333 |
2|
|
1 | TABLE ACCESS BY INDEX ROWID| EMP |
9 |
333 |
2|
| 2 |
INDEX RANGE SCAN
| IX_D |
1 |
|
1|
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access(SYS_OP_DESCEND("DEPTNO")>HEXTORAW('3EE0FF') )
filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("DEPTNO"))<30)

4 - 17

Copyright 2008, Oracle. All rights reserved.

Index Range Scan: Function-Based


Index Range SCAN IX_FBI

create index IX_FBI on EMP(UPPER(ename));


select * from emp where upper(ENAME) like 'A%';
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
37 |
2|
|
1 | TABLE ACCESS BY INDEX ROWID| EMP
|
1 |
37 |
2|
|
2 |
INDEX RANGE SCAN
| IX_FBI |
1 |
|
1|
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access(UPPER("ENAME") LIKE 'A%')
filter(UPPER("ENAME") LIKE 'A%')

4 - 18

Copyright 2008, Oracle. All rights reserved.

Index Full Scan

create index I_DEPTNO on EMP(deptno);


select *
from emp
where sal > 1000 and deptno is not null
order by deptno;

index Full Scan I_DEPTNO

--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |Cost|
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
12 |
444 |
2|
|
1 | TABLE ACCESS BY INDEX ROWID| EMP
|
12 |
444 |
2|
|
2 |
INDEX FULL SCAN
| I_DEPTNO |
14 |
|
1|
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - filter("SAL">1000)
2 - filter("DEPTNO" IS NOT NULL)

4 - 19

Copyright 2008, Oracle. All rights reserved.

Index Fast Full Scan


LEGEND:

db_file_multiblock_read_count = 4
multiblock read

SH

R
discard

SH=segment header
R=root block
B=branch block
L=leaf block

multiblock read

B
discard

...

discard

create index I_DEPTNO on EMP(deptno);


select /*+ INDEX_FFS(EMP I_DEPTNO) */ deptno from emp
where deptno is not null;
---------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost |
---------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
14 |
42 |
2|
|
1 | INDEX FAST FULL SCAN| I_DEPTNO |
14 |
42 |
2|
---------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - filter("DEPTNO" IS NOT NULL)

4 - 20

Copyright 2008, Oracle. All rights reserved.

Index Skip Scan


SELECT * FROM employees WHERE age BETWEEN 20 AND 29
Min M10

B1
Min F16 F20 F26 F30

4 - 21

Index on (GENDER, AGE)

B2

M10 M16 M20 M26 M30

F10
F11
F12
F13
F14
F15

F16
F17
F18
F19

F20
F21
F22
F23
F24
F25

F26
F27
F28
F29

F30
F31
F32
F33
F34
F35

M10
M11
M12
M13
M14
M15

M16
M17
M18
M19

M20
M21
M22
M23
M24
M25

M26
M27
M28
M29

M30
M31
M32
M33
M34
M35

L1

L2

L3

L4

L5

L6

L7

L8

L9

L10

Copyright 2008, Oracle. All rights reserved.

Index Skip Scan: Example

Index on (DEPTNO, SAL)


create index IX_SS on EMP(DEPTNO,SAL);
select /*+ index_ss(EMP IX_SS) */ * from emp where SAL < 1500;
--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
6 |
222 |
6 |
|
1 | TABLE ACCESS BY INDEX ROWID| EMP
|
6 |
222 |
6 |
|
2 |
INDEX SKIP SCAN
| IX_SS |
6 |
|
5 |
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access("SAL"<1500)
filter("SAL"<1500)

4 - 23

Copyright 2008, Oracle. All rights reserved.

Index Join Scan


alter table emp modify (SAL not null, ENAME not null);
create index I_ENAME on EMP(ename);
create index I_SAL on EMP(sal);
select /*+ INDEX_JOIN(e)

*/ ename, sal from emp e;

--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
14 |
140 |
|
1 | VIEW
| index$_join$_001 |
14 |
140 |
|
2 |
HASH JOIN
|
|
|
|
|
3 |
INDEX FAST FULL SCAN| IX_SS
|
14 |
140 |
|

4 |

INDEX FAST FULL SCAN| I_ENAME

14 |

140 |

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


--------------------------------------------------2 - access(ROWID=ROWID)
4 - 24

Copyright 2008, Oracle. All rights reserved.

The AND-EQUAL Operation

SELECT /*+ AND_EQUAL(emp isal ijob) */


FROM
emp
WHERE sal=1000 and job='CLERK';

--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost
|
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
87 |
2 |
|
1 | TABLE ACCESS BY INDEX ROWID| EMP |
1 |
87 |
2 |
|
2 |
AND-EQUAL
|
|
|
|
|
|
3 |
INDEX RANGE SCAN
| ISAL |
1 |
|
1 |
|
4 |
INDEX RANGE SCAN
| IJOB |
4 |
|
1 |
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - filter("SAL"=1000 AND "JOB"='CLERK')
3 - access("SAL"=1000)
4 - access("JOB"='CLERK')

4 - 25

Copyright 2008, Oracle. All rights reserved.

B*-tree Indexes and Nulls


create table nulltest ( col1 number, col2 number not null);
create index nullind1 on nulltest (col1);
create index notnullind2 on nulltest (col2);
select /*+ index(t nullind1) */ col1 from nulltest t;
-------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------|
0 | SELECT STATEMENT |
| 10000 |
126K|
11
(0)|
|
1 | TABLE ACCESS FULL| NULLTEST | 10000 |
126K|
11
(0)|
select col1 from nulltest t where col1=10;
------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------|
0 | SELECT STATEMENT |
|
1 |
13 |
1
(0)|
|
1 | INDEX RANGE SCAN| NULLIND1 |
1 |
13 |
1
(0)|
select /*+ index(t notnullind2) */ col2 from nulltest t;
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------|
0 | SELECT STATEMENT |
|
1 |
13 |
2
(0)|
|
1 | INDEX FULL SCAN | NOTNULLIND2 |
1 |
13 |
2
(0)|

4 - 26

Copyright 2008, Oracle. All rights reserved.

Using Indexes: Considering Nullable Columns


Column

Null?

SSN
FNAME
LNAME

Y
Y
N

CREATE UNIQUE INDEX person_ssn_ix


ON person(ssn);
SELECT COUNT(*) FROM person;
SELECT STATEMENT
|
SORT AGGREGATE
|
TABLE ACCESS FULL| PERSON

PERSON

DROP INDEX person_ssn_ix;

Column

Null?

SSN
FNAME
LNAME

N
Y
N

PERSON
4 - 27

ALTER TABLE person ADD CONSTRAINT pk_ssn


PRIMARY KEY (ssn);
SELECT /*+ INDEX(person) */ COUNT(*) FROM
person;
SELECT STATEMENT
|
SORT AGGREGATE
|
INDEX FAST FULL SCAN| PK_SSN

Copyright 2008, Oracle. All rights reserved.

Index-Organized Tables
Indexed
access on table

Accessing
index-organized table

ROWID

Nonkey columns
Key column
Row header
4 - 28

Copyright 2008, Oracle. All rights reserved.

Index-Organized Table Scans


select * from iotemp where empno=9999;
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost|
--------------------------------------------------------------------|
0 | SELECT STATEMENT |
|
1 |
87 |
1|
|
1 | INDEX UNIQUE SCAN| SYS_IOT_TOP_75664 |
1 |
87 |
1|
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - access("EMPNO"=9999)
select * from iotemp where sal>1000;
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
12 | 1044 |
|
1 | INDEX FAST FULL SCAN| SYS_IOT_TOP_75664 |
12 | 1044 |
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - filter("SAL">1000)

4 - 29

Copyright 2008, Oracle. All rights reserved.

Bitmap Indexes
Table
File 3
Block 10

Index

Block 11

Block 12

<Blue,
<Green,
<Red,
<Yellow,
Key

4 - 30

10.0.3,
10.0.3,
10.0.3,
10.0.3,
Start
ROWID

12.8.3,
12.8.3,
12.8.3,
12.8.3,

100010000
000101000
010000000
001000000

010000000
000000000
001100000
100000000

End
ROWID

Copyright 2008, Oracle. All rights reserved.

Bitmap

010010100>
100100000>
000001001>
001000010>

Bitmap Index Access: Examples


SELECT * FROM PERF_TEAM WHERE country='FR';
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
45 |
|

1 |

2 |

TABLE ACCESS BY INDEX ROWID | PERF_TEAM |


BITMAP CONVERSION TO ROWIDS|

1 |

45 |

|
3 |
BITMAP INDEX SINGLE VALUE | IX_B2
|
|
|
SELECT * FROM PERF_TEAM WHERE country>'FR';
--------------------------------------------------------------------Predicate:
3 - access("COUNTRY"='FR')
| Id | Operation
| Name
| Rows | Bytes |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
45 |
|
1 | TABLE ACCESS BY INDEX ROWID | PERF_TEAM |
1 |
45 |
|

2 |

3 |

BITMAP CONVERSION TO ROWIDS|


BITMAP INDEX RANGE SCAN

| IX_B2

--------------------------------------------------------------------4 - 31Predicate: 3 - access("COUNTRY">'FR')


Copyright 2008, Oracle. Allfilter("COUNTRY">'FR')
rights reserved.

Combining Bitmap Indexes: Examples


SELECT * FROM PERF_TEAM WHERE country in('FR','DE');

FR 0 0 1 1 1 1 0 0 0 0 0 0
OR

0 1 1 1 1 1 0 0 0 0 0

DE 0 1 0 0 0 0 0 0 0 0 0 0

F 0 0 1 1 1 1 0 0 0 0 0 0
AND

0 0 1 0 1 1 0 0 0 0 0

M 1 1 1 0 1 1 0 1 0 1 1 1
SELECT * FROM EMEA_PERF_TEAM T WHERE country='FR' and gender='M';

4 - 32

Copyright 2008, Oracle. All rights reserved.

Combining Bitmap Index Access Paths


SELECT * FROM PERF_TEAM WHERE country in ('FR','DE');
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |
|
0 | SELECT STATEMENT
|
|
1 |
45 |
|
1 | INLIST ITERATOR
|
|
|
|
|
2 |
TABLE ACCESS BY INDEX ROWID | PERF_TEAM |
1 |
45 |
|
3 |
BITMAP CONVERSION TO ROWIDS|
|
|
|
|
4 |
BITMAP INDEX SINGLE VALUE | IX_B2
|
|
|
Predicate: 4 - access("COUNTRY"='DE' OR "COUNTRY"='FR')
SELECT * FROM PERF_TEAM WHERE country='FR' and gender='M';
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |
|
0 | SELECT STATEMENT
|
|
1 |
45 |
|
1 | TABLE ACCESS BY INDEX ROWID | PERF_TEAM |
1 |
45 |
|
2 |
BITMAP CONVERSION TO ROWIDS|
|
|
|
|
3 |
BITMAP AND
|
|
|
|
|
4 |
BITMAP INDEX SINGLE VALUE| IX_B1
|
|
|
|
5 |
BITMAP INDEX SINGLE VALUE| IX_B2
|
|
|
Predicate: 4 - access("GENDER"='M') 5 - access("COUNTRY"='FR')

4 - 33

Copyright 2008, Oracle. All rights reserved.

Bitmap Operations
BITMAP CONVERSION:
TO ROWIDS
FROM ROWIDS
COUNT

BITMAP INDEX:
SINGLE VALUE
RANGE SCAN
FULL SCAN

4 - 34

BITMAP
BITMAP
BITMAP
BITMAP

MERGE
AND/OR
MINUS
KEY ITERATION
Copyright 2008, Oracle. All rights reserved.

Bitmap Join Index

1.2.3
Sales

CREATE BITMAP INDEX cust_sales_bji


ON
sales(c.cust_city)
FROM sales s, customers c
WHERE c.cust_id = s.cust_id;
Customers

10.8000.3
<Rognes, 1.2.3, 10.8000.3, 100010010010100>
<Aix-en-Provence, 1.2.3, 10.8000.3, 000101000100000>
<Marseille, 1.2.3, 10.8000.3, 010000001000001>
4 - 35

Copyright 2008, Oracle. All rights reserved.

Composite Indexes
MAKE

MODEL

CARS
Index columns
create index cars_make_model_idx on cars(make, model);
select *
from cars
where make = 'CITRON' and model = '2CV';
----------------------------------------------------------------| Id | Operation
| Name
|
----------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
|
1 | TABLE ACCESS BY INDEX ROWID| CUSTOMERS
|
|* 2 |
INDEX RANGE SCAN
| CARS_MAKE_MODEL_IDX
|
-----------------------------------------------------------------

4 - 36

Copyright 2008, Oracle. All rights reserved.

Invisible Index: Overview


Use index.

Do not use index.

Optimizer view point


INVISIBLE

VISIBLE

Index

Index

OPTIMIZER_USE_INVISIBLE_INDEXES=FALSE

Data view point

Update index.

Update index.
Update table.

Update table.

4 - 37

Copyright 2008, Oracle. All rights reserved.

Invisible Indexes: Examples


Index is altered as not visible to the optimizer:
ALTER INDEX ind1 INVISIBLE;

Optimizer does not consider this index:


SELECT /*+ index(TAB1 IND1) */ COL1 FROM TAB1 WHERE ;

Optimizer considers this index:


ALTER INDEX ind1 VISIBLE;

Create an index as invisible initially:


CREATE INDEX IND1 ON TAB1(COL1) INVISIBLE;

4 - 38

Copyright 2008, Oracle. All rights reserved.

Guidelines for Managing Indexes

Create indexes after inserting table data.


Index the correct tables and columns.
Order index columns for performance.
Limit the number of indexes for each table.
Drop indexes that are no longer required.
Specify the tablespace for each index.
Consider parallelizing index creation.
Consider creating indexes with NOLOGGING.
Consider costs and benefits of coalescing or rebuilding
indexes.
Consider cost before disabling or dropping constraints.

4 - 39

Copyright 2008, Oracle. All rights reserved.

Investigating Index Usage


An index may not be used for one of many reasons:
There are functions being applied to the predicate.
There is a data type mismatch.
Statistics are old.
The column can contain null.
Using the index would actually be slower than not using it.

4 - 41

Copyright 2008, Oracle. All rights reserved.

Practice 4: Overview
This practice covers using different access paths for better
optimization.
Case 1 through case 13

4 - 43

Copyright 2008, Oracle. All rights reserved.

Clusters
ORD_NO
-----101
102
102
102
101
101

PROD
-----A4102
A2091
G7830
N9587
A5675
W0824

QTY
-----20
11
20
26
19
10

...

ORD_NO
-----101
102

ORD_DT
CUST_CD
----------05-JAN-97
R01
07-JAN-97
N45

Unclustered ORDERS and


ORDER_ITEMS tables

4 - 44

Cluster Key
(ORD_NO)
101 ORD_DT
CUST_CD
05-JAN-97
R01
PROD
QTY
A4102
20
A5675
19
W0824
10
102
ORD_DT
CUST_CD
07-JAN-97
N45
PROD
QTY
A2091
11
G7830
20
N9587
26

Clustered ORDERS and


ORDER_ITEMS tables

Copyright 2008, Oracle. All rights reserved.

When Are Clusters Useful?


Index cluster:
Tables always joined on the same keys
The size of the table is not known
In any type of searches

Hash cluster:
Tables always joined on the same keys
Storage for all cluster keys allocated initially
In either equality (=) or nonequality (<>) searches

4 - 45

Copyright 2008, Oracle. All rights reserved.

When Are Clusters Useful?


Single-table hash cluster:
Fastest way to access a large table with an equality search

Sorted hash cluster:


Only used for equality search
Avoid sorts on batch reporting
Avoid overhead probe on the branch blocks of an IOT

4 - 46

Copyright 2008, Oracle. All rights reserved.

Cluster Access Path: Examples


SELECT * FROM calls WHERE origin_number=33442395322;
---------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------|
0 | SELECT STATEMENT |
|
1 |
56 |
0
(0)|
|
1 | TABLE ACCESS HASH| CALLS |
1 |
56 |
|
---------------------------------------------------------------1 - access("ORIGIN_NUMBER"=33442395322)
SELECT * FROM emp,dept WHER emp.deptno=dept.deptno;
----------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost
|
----------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
117 |
3
|
|
1 | NESTED LOOPS
|
|
1 |
117 |
3
|
|
2 |
TABLE ACCESS FULL
| EMP |
1 |
87 |
2
|
|
3 |
TABLE ACCESS CLUSTER| DEPT |
1 |
30 |
1
|
----------------------------------------------------------------3 - filter("EMP"."DEPTNO"="DEPT"."DEPTNO")

4 - 47

Copyright 2008, Oracle. All rights reserved.

Sorting Operators
SORT operator:

AGGREGATE: Single row from group function


UNIQUE: To eliminate duplicates
JOIN: Precedes a merge join
GROUP BY, ORDER BY: For these operators

HASH operator:
GROUP BY: For this operator
UNIQUE: Equivalent to SORT UNIQUE

If you want ordered results, always use ORDER BY.

4 - 48

Copyright 2008, Oracle. All rights reserved.

Buffer Sort Operator


select ename, emp.deptno, dept.deptno, dname
from
emp, dept
where ename like 'A%';
--------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
4 |
124 |
5
|
1 | MERGE JOIN CARTESIAN
|
|
4 |
124 |
5
|
2 |
TABLE ACCESS BY INDEX ROWID| EMP
|
1 |
9 |
2
|
3 |
INDEX RANGE SCAN
| I_ENAME |
1 |
|
1
|
4 |
BUFFER SORT
|
|
4 |
88 |
3
|
5 |
TABLE ACCESS FULL
| DEPT
|
4 |
88 |
3
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------3 - access("ENAME" LIKE 'A%')
filter("ENAME" LIKE 'A%')

4 - 49

Copyright 2008, Oracle. All rights reserved.

Inlist Iterator
Every value executed separately
deptno=1

deptno=2

select * from emp where deptno in (1,2);


select * from emp where deptno = 1 or deptno =2 ;
--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
2 |
78 |
2|
|
1 | INLIST ITERATOR
|
|
|
|
|
|
2 |
TABLE ACCESS BY INDEX ROWID| EMP
|
2 |
78 |
2|
|
3 |
INDEX RANGE SCAN
| IX_SS |
2 |
|
1|
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------3 - access("DEPTNO"=1 OR "DEPTNO"=2)
4 - 50

Copyright 2008, Oracle. All rights reserved.

View Operator
create view V as select /*+ NO_MERGE */ DEPTNO, sal from emp ;
select * from V;
--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)| Time
|
0 | SELECT STATEMENT |
|
14 |
364 |
1
(0)| 0:01
|
1 | VIEW
| V
|
14 |
364 |
1
(0)| 0:01
|
2 |
INDEX FULL SCAN| IX_SS |
14 |
98 |
1
(0)| 0:01
--------------------------------------------------------------------select v.*,d.dname from (select DEPTNO, sum(sal) SUM_SAL
from emp group by deptno) v, dept d where v.deptno=d.deptno;
--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)|
|
0 | SELECT STATEMENT
|
|
3 |
144 |
5 (20)|
|
1 | HASH JOIN
|
|
3 |
144 |
5 (20)|
|
2 |
VIEW
|
|
3 |
78 |
1
(0)|
|
3 |
HASH GROUP BY
|
|
3 |
21 |
1
(0)|
|
4 |
INDEX FULL SCAN| IX_SS |
14 |
98 |
1
(0)|
|
5 |
TABLE ACCESS FULL| DEPT |
4 |
88 |
3
(0)|
--------------------------------------------------------------------Predicate: 1 - access("V"."DEPTNO"="D"."DEPTNO")

4 - 51

Copyright 2008, Oracle. All rights reserved.

Count Stop Key Operator


select count(*)
from (select /*+ NO_MERGE */ *
from TC where C1 ='1' and rownum < 10);
--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
|
4
(0)|
|
1 | SORT AGGREGATE
|
|
1 |
|
|
|
2 |
VIEW
|
|
9 |
|
4
(0)|
|
3 |
COUNT STOPKEY
|
|
|
|
|
|
4 |
TABLE ACCESS FULL| TC
| 4282 | 4190K|
4
(0)|
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------3 - filter(ROWNUM<10)
4 - filter("C1"='1')

4 - 52

Copyright 2008, Oracle. All rights reserved.

Min/Max and First Row Operators

select min(id) FROM t WHERE id > 500000;


--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
1 |
13 |
3|
|
1 | SORT AGGREGATE
|
|
1 |
13 |
|
|
2 |
FIRST ROW
|
|
717K| 9113K|
3|
|
3 |
INDEX RANGE SCAN (MIN/MAX)| IXT |
717K| 9113K|
3|
--------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------3 - access("ID">500000)

4 - 53

Copyright 2008, Oracle. All rights reserved.

Join Methods
A join defines the relationship between two row sources.
A join is a method of combining data from two data sources.
It is controlled by join predicates, which define how the
objects are related.
Join methods:
Nested loops
Sort-merge join
Hash join
SELECT e.ename, d.dname
FROM dept d JOIN emp e USING (deptno)
WHERE e.job = 'ANALYST' OR e.empno = 9999;

Join predicate
Nonjoin predicate

SELECT e.ename,d.dname
FROM
emp e, dept d
WHERE e.deptno = d.deptno AND
(e.job = 'ANALYST' OR e.empno = 9999);

Join predicate
Nonjoin predicate

4 - 54

Copyright 2008, Oracle. All rights reserved.

Nested Loops Join


NL

Driving row source is scanned


Each row returned drives a lookup in
inner row source
Joining rows are then returned

TAF

TAR

Driving
For
each

IS
Inner

select ename, e.deptno, d.deptno, d.dname


from emp e, dept d
where e.deptno = d.deptno and ename like 'A%';
--------------------------------------------------------------------| Id | Operation
| Name
| Rows |Cost |
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
2 |
4 |
|
1 | NESTED LOOPS
|
|
2 |
4 |
|
2 |
TABLE ACCESS FULL
| EMP
|
2 |
2 |
|
3 |
TABLE ACCESS BY INDEX ROWID| DEPT
|
1 |
1 |
|
4 |
INDEX UNIQUE SCAN
| PK_DEPT
|
1 |
|
--------------------------------------------------------------------2 - filter("E"."ENAME" LIKE 'A%')
4 - access("E"."DEPTNO"="D"."DEPTNO")

4 - 55

Copyright 2008, Oracle. All rights reserved.

Nested Loops Join: Prefetching


NL
TAF

TAR

Driving

IRS
Inner

select ename, e.deptno, d.deptno, d.dname


from emp e, dept d
where e.deptno = d.deptno and ename like 'A%';
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
2 |
84 |
5
|
1 | TABLE ACCESS BY INDEX ROWID| DEPT |
1 |
22 |
1
|
2 |
NESTED LOOPS
|
|
2 |
84 |
5
|* 3 |
TABLE ACCESS FULL
| EMP
|
2 |
40 |
3
|* 4 |
INDEX RANGE SCAN
| IDEPT |
1 |
|
0
--------------------------------------------------------------------3 - filter("E"."ENAME" LIKE 'A%')
4 - access("E"."DEPTNO"="D"."DEPTNO")

4 - 56

Copyright 2008, Oracle. All rights reserved.

Nested Loops Join: 11g Implementation


NL
TAR

NL
TAF

IRS

Driving

Inner

select ename, e.deptno, d.deptno, d.dname


from emp e, dept d
where e.deptno = d.deptno and ename like 'A%';
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
2 |
84 |
5
|
1 | NESTED LOOPS
|
|
|
|
|
2 |
NESTED LOOPS
|
|
2 |
84 |
5
|* 3 |
TABLE ACCESS FULL
| EMP
|
2 |
40 |
3
|* 4 |
INDEX RANGE SCAN
| DDEPT |
1 |
|
0
|
5 |
TABLE ACCESS BY INDEX ROWID| DEPT |
1 |
22 |
1
--------------------------------------------------------------------3 - filter("E"."ENAME" LIKE 'A%')
4 - access("E"."DEPTNO"="D"."DEPTNO")

4 - 57

Copyright 2008, Oracle. All rights reserved.

Sort Merge Join

Merged

SJ

SJ

TAF

TAF

Independent

select ename, e.deptno, d.deptno, dname


from emp e, dept d
where e.deptno = d.deptno and ename > 'A';
--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)|
|
0 | SELECT STATEMENT
|
|
2 |
84 |
8 (25)|
|
1 | MERGE JOIN
|
|
2 |
84 |
8 (25)|
|
2 |
SORT JOIN
|
|
2 |
40 |
4 (25)|
|
3 |
TABLE ACCESS FULL| EMP |
2 |
40 |
3
(0)|
|
4 |
SORT JOIN
|
|
4 |
88 |
4 (25)|
|
5 |
TABLE ACCESS FULL| DEPT |
4 |
88 |
3
(0)|
--------------------------------------------------------------------Predicate:
3 - filter("ENAME">'A')
4 - access("E"."DEPTNO"="D"."DEPTNO")
filter("E"."DEPTNO"="D"."DEPTNO")

4 - 58

Copyright 2008, Oracle. All rights reserved.

Sorted

First and second row sources are sorted


by same sort key.
Sorted rows from both side are merged.

Sorted

MJ

Hash Join
The smallest row source is used
to build a hash table.
The second row source is hashed
and checked against the hash table.

HJ
Driving TAF
Build hash
table in
memory

TAR
IS

Probe

select ename, e.deptno, d.deptno, dname from emp e, dept d


where e.deptno = d.deptno and ename like 'A%';
--------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost
--------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
3 |
66 |
6
|
1 | HASH JOIN
|
|
3 |
66 |
6
|
2 |
TABLE ACCESS BY INDEX ROWID| EMP
|
3 |
27 |
2
|
3 |
INDEX FULL SCAN
| EDEPT |
14 |
|
1
|
4 |
TABLE ACCESS FULL
| DEPT |
4 |
52 |
3
--------------------------------------------------------------------Predicate:
1 - access("E"."DEPTNO"="D"."DEPTNO")
2 - filter("ENAME" LIKE 'A%')

4 - 59

Copyright 2008, Oracle. All rights reserved.

Cartesian Join

select ename, e.deptno, d.deptno, dname


from emp e, dept d where ename like 'A%';
-------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
11 |
242 |
8
(0)|
|
1 | MERGE JOIN CARTESIAN|
|
11 |
242 |
8
(0)|
|
2 |
TABLE ACCESS FULL | EMP |
3 |
27 |
3
(0)|
|
3 |
BUFFER SORT
|
|
4 |
52 |
5
(0)|
|
4 |
TABLE ACCESS FULL | DEPT |
4 |
52 |
2
(0)|
-------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - filter("ENAME" LIKE 'A%')

4 - 60

Copyright 2008, Oracle. All rights reserved.

Join Types
A join operation combines the output from two row sources
and returns one resulting row source.
Join operation types include the following :

4 - 61

Join (Equijoin/Natural Nonequijoin)


Outer join (Full, Left, and Right)
Semi join: EXISTS subquery
Anti join: NOT IN subquery
Star join (Optimization)

Copyright 2008, Oracle. All rights reserved.

Equijoins and Nonequijoins


SELECT e.ename, e.sal, s.grade
FROM
emp e ,salgrade s
WHERE e.sal = s.hisal;
--------------------------------------| Id | Operation
| Name
|
--------------------------------------|
0 | SELECT STATEMENT
|
|
|
1 | HASH JOIN
|
|
|
2 |
TABLE ACCESS FULL| EMP
|
|
3 |
TABLE ACCESS FULL| SALGRADE |
--------------------------------------1 - access("E"."SAL"="S"."HISAL")

Nonequijoin

4 - 62

Equijoin

SELECT e.ename, e.sal, s.grade


FROM
emp e ,salgrade s
WHERE e.sal between s.hisal and s.hisal;
--------------------------------------| Id | Operation
| Name
|
|
0 | SELECT STATEMENT
|
|
|
1 | NESTED LOOPS
|
|
|
2 |
TABLE ACCESS FULL| EMP
|
|
3 |
TABLE ACCESS FULL| SALGRADE |
--------------------------------------3 - filter("E"."SAL">="S"."HISAL" AND
"E"."SAL"<="S"."HISAL")

Copyright 2008, Oracle. All rights reserved.

Outer Joins
An outer join also returns a row
if no match is found.
DEPT
10
20
30
40

EMP
20
10
20
30
10

SELECT d.deptno,d.dname,e.empno,e.ename
FROM
emp e, dept d
WHERE e.deptno(+)=d.deptno;
---------------------------------------------| Id | Operation
| Name |
---------------------------------------------|
0 | SELECT STATEMENT
|
|
|
1 | NESTED LOOPS OUTER
|
|
|
2 |
TABLE ACCESS FULL
| DEPT |
|
3 |
TABLE ACCESS BY INDEX ROWID| EMP
|
|
4 |
INDEX RANGE SCAN
| EDEPT |
---------------------------------------------4 - access("E"."DEPTNO"(+)="D"."DEPTNO")

4 - 63

SELECT d.deptno,d.dname,e.empno,e.ename
FROM
emp e, dept d
WHERE e.deptno(+)=d.deptno;
--------------------------------------| Id | Operation
| Name |
--------------------------------------|
0 | SELECT STATEMENT
|
|
|
1 | HASH JOIN RIGHT OUTER |
|
|
2 |
TABLE ACCESS FULL
| EMP |
|
3 |
TABLE ACCESS FULL
| DEPT |
----------------------------------1 - access("E"."DEPTNO"(+)="D"."DEPTNO")
SELECT d.deptno,d.dname,e.empno,e.ename
FROM
emp e, dept d
WHERE e.deptno(+)=d.deptno;
----------------------------------| Id | Operation
| Name |
----------------------------------|
0 | SELECT STATEMENT
|
|
|
1 | HASH JOIN OUTER
|
|
|
2 |
TABLE ACCESS FULL| DEPT |
|
3 |
TABLE ACCESS FULL| EMP |
----------------------------------1 - access("E"."DEPTNO"(+)="D"."DEPTNO")

Copyright 2008, Oracle. All rights reserved.

Semijoins
Semijoins only look for the first match.

DEPT
10
20
30
40

EMP
20
10
10
30
10

SELECT deptno, dname


FROM
dept
WHERE EXISTS (SELECT 1 FROM emp WHERE emp.deptno=dept.deptno);
-------------------------------------------------------------------| Id | Operation
| Name | Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
3 |
105 |
7 (15)|
|
1 | HASH JOIN SEMI
|
|
3 |
105 |
7 (15)|
|
2 |
TABLE ACCESS FULL| DEPT |
4 |
88 |
3
(0)|
|
3 |
TABLE ACCESS FULL| EMP |
14 |
182 |
3
(0)|
-------------------------------------------------------------------1 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")

4 - 64

Copyright 2008, Oracle. All rights reserved.

Antijoins
Reverse of what would have been returned by a join
SELECT deptno, dname
FROM
dept
WHERE deptno not in
(SELECT deptno FROM emp);
--------------------------------------| Id | Operation
| Name
|
--------------------------------------|
0 | SELECT STATEMENT
|
|
|
1 | NESTED LOOPS ANTI |
|
|
2 |
TABLE ACCESS FULL| DEPT
|
|
3 |
INDEX RANGE SCAN | I_DEPTNO |
--------------------------------------3 - access("DEPTNO"="DEPTNO")

EMP

4 - 65

DEPT

DEPT
10
20
30
40

EMP
20
10
20
30
10

SELECT deptno, dname


FROM
dept
WHERE deptno not in
(SELECT deptno FROM emp);
----------------------------------| Id | Operation
| Name |
----------------------------------|
0 | SELECT STATEMENT
|
|
|
1 | HASH JOIN ANTI
|
|
|
2 |
TABLE ACCESS FULL| DEPT |
|
3 |
TABLE ACCESS FULL| EMP |
-----------------------------------

Copyright 2008, Oracle. All rights reserved.

Other N-Array Operations

4 - 66

FILTER
CONCATENATION
UNION ALL/UNION
INTERSECT
MINUS

Copyright 2008, Oracle. All rights reserved.

Filter Operations
Accepts a set of rows
Eliminates some of them
Returns the rest
SELECT
deptno, sum(sal) SUM_SAL
FROM
emp
GROUP BY deptno
HAVING sum(sal) > 9000;
-----------------------------------| Id | Operation
| Name |
-----------------------------------|
0 | SELECT STATEMENT
|
|
|
1 | FILTER
|
|
|
2 |
HASH GROUP BY
|
|
|
3 |
TABLE ACCESS FULL| EMP |
-----------------------------------1 - filter(SUM("SAL")>9000)

4 - 67

SELECT deptno, dname


FROM dept d WHERE NOT EXISTS
(select 1 from emp e
where e.deptno=d.deptno);
-----------------------------------| Id | Operation
| Name |
-----------------------------------|
0 | SELECT STATEMENT
|
|
1 | FILTER
|
|
2 |
TABLE ACCESS FULL| DEPT
|
3 |
INDEX RANGE SCAN |I_DEPTNO
-----------------------------------1 - filter( NOT EXISTS
(SELECT 0 FROM "EMP" "E" WHERE
"E"."DEPTNO"=:B1))
3 - access("E"."DEPTNO"=:B1)

Copyright 2008, Oracle. All rights reserved.

Concatenation Operation

SELECT * FROM emp WHERE deptno=1 or sal=2;


-------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |
-------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
8 |
696 |
|
1 | CONCATENATION
|
|
|
|
|
2 |
TABLE ACCESS BY INDEX ROWID| EMP
|
4 |
348 |
|
3 |
INDEX RANGE SCAN
| I_SAL
|
2 |
|
|
4 |
TABLE ACCESS BY INDEX ROWID| EMP
|
4 |
348 |
|
5 |
INDEX RANGE SCAN
| I_DEPTNO |
2 |
|
-------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------3 - access("SAL"=2)
4 - filter(LNNVL("SAL"=2))
5 - access("DEPTNO"=1)

4 - 68

Copyright 2008, Oracle. All rights reserved.

UNION [ALL], INTERSECT, MINUS

UNION
UNION ALL

SORT UNIQUE
UNION-ALL
INDEX FULL SCAN
INDEX FAST FULL SCAN

INTERSECT

INTERSECTION
SORT UNIQUE NOSORT
INDEX FULL SCAN
SORT UNIQUE
INDEX FAST FULL SCAN

MINUS

4 - 69

1
2

3
3

MINUS
SORT UNIQUE NOSORT
INDEX FULL SCAN
SORT UNIQUE
INDEX FAST FULL SCAN

Copyright 2008, Oracle. All rights reserved.

1
2

1
2

1
2

3
3

3
3

3
3

4
5

Result Cache Operator

EXPLAIN PLAN FOR


SELECT /*+ RESULT_CACHE */ department_id, AVG(salary)
FROM employees
GROUP BY department_id;
-------------------------------------------------------------| Id

| Operation

| Name

|Rows

-------------------------------------------------------------|

0 | SELECT STATEMENT

1 |

| 8fpza04gtwsfr6n595au15yj4y |

2 |

3 |

RESULT CACHE
HASH GROUP BY

TABLE ACCESS FULL| EMPLOYEES

11

11

| 107

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

4 - 70

Copyright 2008, Oracle. All rights reserved.

Summary
In this lesson, you should have learned to:
Describe most of the SQL operators
List the possible access paths
Explain how join operations are performed

4 - 71

Copyright 2008, Oracle. All rights reserved.

Practice 4: Overview
This practice covers the following topics:
Using different access paths for better optimization
Case 14 to case 16

Using the result cache

4 - 72

Copyright 2008, Oracle. All rights reserved.

Das könnte Ihnen auch gefallen