SQL Optimization Slides
SQL Optimization Slides
Day 1:
• Exploring the Oracle Database Arhitecture
• Introduction to SQL Tuning
• Introduction to the Optimizer
• Optimizer Operations
I-2
Course Agenda
Day 2:
• Optimizer Operations – cont’ed
• Interpreting Execution Plans
• Materialized Views
I-3
Course Agenda
Day 3:
• Optimizer Statistics
• Using Bind Variables
• Optimizer Hints
• Application Tracing
I-4
Oracle Database Architecture
Oracle Database Architecture: Overview
1-2
Oracle Instance Management
SGA
Check
Archiver
point Control Redo log ARC0
CKPT Data
file files
files
1-3
Database Physical Structure
Control files
1-4
Oracle Memory Structures
SGA
1-5
Automatic Shared Memory Management
SGA
SGA_TARGET + STATISTICS_LEVEL
1-6
Shared Pool
The shared pool consists of:
• Data dictionary cache containing information on
objects, storage, and privileges
• Library cache containing information such as SQL
statements, parsed or compiled PL/SQL blocks, and
Java classes
• Result Cache
Appropriate sizing of the shared pool affects performance
by:
• Reducing disk reads
• Allowing shareable SQL code
• Reducing parsing, thereby saving CPU resources
• Reducing latching overhead, thereby improving
scalability
1-7
Program Global Area (PGA)
1-8
Automated SQL Execution Memory (PGA)
Management
PGA_AGGREGATE_TARGET
1-9
Database Buffer Cache
Server
Database
process
buffer
cache
DBWn
Database writer
Data files process
1-10
Redo Log Buffer
• Is a circular buffer in the SGA (based on the number of
CPUs)
• Contains redo entries that have the information to
redo changes made by operations, such as DML and
DDL SGA
Server
process Redo log
buffer
LGWR
Log writer
Redo log process
files
1-11
Large Pool
1-12
Java Pool and Streams Pool
1-13
Background Process Roles
Database
SGA Redo log
buffer Shared pool
buffer
cache
1-14
Connecting to an Instance
User Server
Oracle database
User Server
Client
User Server
Browser
1-15
Shared SQL Areas
1-16
SQL Statement Processing Phases
Open Close
1-17
SQL Statement Processing Phases: Parse
• Parse phase:
– Searches for the statement in the shared pool
– Checks syntax
– Checks semantics and privileges
– Merges view definitions and subqueries
– Determines execution plan
• Minimize parsing as much as possible:
– Parse calls are expensive.
– Avoid reparsing
– Parse once, execute many times
1-18
SQL Statement Processing Phases: Bind
• Bind phase:
– Checks the statement for bind variables
– Assigns or reassigns a value to the bind variable
• Bind variables impact performance when:
– They are not used, and your statement would
benefit from a shared cursor
– They are used, and your statement would benefit
from a different execution plan
1-19
SQL Statement Processing Phases:
Execute and Fetch
• Execute phase:
– Executes the SQL statement
– Performs necessary I/O and sorts for data
manipulation language (DML) statements
• Fetch phase:
– Retrieves rows for a query
– Sorts for queries when needed
– Uses an array fetch mechanism
1-20
Processing a DML Statement
Database SGA
2 Database
buffer cache
1
Data Redo log
Server 3 buffer
files process
Shared pool
UPDATE
Control employees ...
files
4
User
Redo process
log files
1-21
COMMIT Processing
Instance
Database SGA
Database
buffer cache
Control
files
User
process
Redo
log files LGWR
1-22
Logical and Physical Database Structures
Logical Physical
Database
Only 1 with
bigfile
tablespaces
Schema Tablespace Data file
0, 1, or many
Undo tablespaces
never have 0 Segment
Extent
Oracle data
OS block
block
1-23
Segments, Extents, and Blocks
1-24
SYSTEM and SYSAUX Tablespaces
1-25
Functions of the Oracle Query Optimizer
1-26
Top Database Performance Issues
1-27
Summary
1-28
Tuning Methodology
Reasons for Inefficient SQL Performance
2-2
What You Need to Write Efficient SQL
2-3
Inefficient SQL: Examples
2-5
SQL Tuning Tasks: Overview
2-6
Tuning Goals
2-7
Tuning Tools: Overview
2-8
11g Performance Monitoring Solutions
Automatic
Fore- 60 mn
In-memory
-ground
statistics
MMON
SGA AWR
ASH
Snapshots
Snapshots ADDM
Alerts AST
Statspack
ADDM
results AWR report
2-9
Overview of SQL Tuning
2-10
Manual Tuning
2-11
Gather Information About
Referenced Objects
• SQL text (V$SQLTEXT)
• Structure of tables and indexes (SQL> desc table)
• Optimizer statistics
• Views
• Optimizer plan: current and prior (EXPLAIN PLAN)
2-12
Gathering Optimizer Statistics
2-13
The factors affecting execution plan
2-14
Reviewing the Execution Plan
2-15
Restructuring the SQL Statements
• Use equijoins
• Compose predicates by using AND
• Avoid transformed columns in the WHERE clause.
• Avoid mixed-mode expressions and beware of
implicit type conversions.
• Write separate SQL statements for specific tasks
and use SQL constructs appropriately.
• Use EXISTS or IN for subqueries as required
• Cautiously change the access path and join order
with hints.
2-16
EXISTS vs. IN
SELECT * FROM T1
WHERE x IN ( SELECT y FROM T2 )
2-19
Maintaining Execution Plans over Time
2-20
Automatic SQL Tuning
2-21
Automatic Tuning Mechanisms
2-22
SQL Tuning Advisor
2-23
SQL Access Advisor
2-24
Proactive Tuning Methodology
• Simple design
• Data modeling
• Tables and indexes
• Using views
• Writing efficient SQL
• Cursor sharing
• Using bind variables
• SQL versus PL/SQL
• Dynamic SQL
2-25
Simplicity In Application Design
• Simple tables
• Well-written SQL
• Indexing only as required
• Retrieving only required information
2-26
Data Modeling
2-27
Table Design
2-28
Index Design
• Index keys
– Primary key (automatically created)
– Unique key (automatically created)
– Foreign keys (good candidates)
• Index data that is frequently queried (select list)
• Use SQL as a guide to index design
2-29
Using Views
2-30
SQL Execution Efficiency
2-31
Writing SQL to Share Cursors
2-32
Controlling Shared Cursors
2-34
Summary
2-35
Introduction to Optimizer
Oracle Optimizer
3-2
SQL Statement Implementation
SGA
Shared Shared
SQL area SQL area
Library cache Java pool
Buffer cache
Data dictionary Result cache Other
cache
Redo log SHARED_POOL
buffer Streams pool
3-3
SQL Statement Parsing: Overview
Privileges check
Private Parse
SQL area Allocate private SQL Area call
Parsed representation
Shared
Execute statement SQL area
3-4
Why Do You Need an Optimizer?
Query to optimize
Schema
How can I retrieve these rows? information
Possible access paths
Read
Use the
index. 1 each row
and check.
3-5
Why Do You Need an Optimizer?
Query to optimize
Schema
How can I retrieve these rows? information
Possible access paths
Read
Use the
index. 1 each row
and check.
3-6
Cost-Based Optimizer (CBO)
• Piece of code:
– Estimator – generates selectivity, cardinality and cost
– Plan generator – try out different plans and pick one
• Estimator determines cost of optimization suggestions
made by the plan generator:
– Cost: Optimizer’s best estimate of the number of
standardized I/Os made to execute a particular
statement optimization
• Plan generator:
– Tries out different statement optimization techniques
– Uses the estimator to cost each optimization suggestion
– Chooses the best optimization suggestion based on
cost
– Generates an execution plan for best optimization
3-7
Optimization During Hard Parse Operation
Parsed representation
(query blocks)
Optimizer
Transformer
Statistics
Estimator
CBO
Dictionary
Plan Generator
Execution Plan
Shared
SQL area
3-8
Transformer: OR Expansion Example
SELECT *
FROM emp
WHERE job = 'CLERK' OR deptno = 10;
3-9
Transformer: Subquery Unnesting Example
• Original query:
SELECT *
FROM accounts
WHERE custno IN
(SELECT custno FROM customers);
3-10
Transformer: View Merging Example
3-11
Transformer: Predicate Pushing Example
• Original query: Index
3-12
Transformer: Transitivity Example
SELECT *
FROM emp, dept
WHERE emp.deptno = 20 AND emp.deptno = dept.deptno;
3-13
Estimator: Selectivity
• column = constant
selectivity = 1/num_distinct; (no histogram available) or
selectivity = density; (when histogram available)
• column has null values
selectivity = (num_rows - num_nulls)/(num_distinct*num_rows); (when
histogram non-available) or
selectivity = density * (num_rows - num_nulls)/num_rows; (when
histogram available)
• multiple predicates
selectivity(predicate1 AND predicate2) = selectivity(predicate1) *
selectivity(predicate2).
selectivity(predicate1 OR predicate2) = selectivity(predicate1) +
selectivity(predicate2) - selectivity(predicate1 AND predicate2)
selectivity(NOT predicate1) = 1 – selectivity(predicate1)
3-15
Estimator: Cardinality
3-16
Estimator: Cost
3-17
Plan Generator
3-18 3_18.sql
Query Optimizer Statistics in
the Data Dictionary
3-19
Enabling Query Optimizer Features
3-20
Controlling the Behavior of the Optimizer
3-21
Controlling the Behavior of the Optimizer
• OPTIMIZER_INDEX_CACHING
• OPTIMIZER_INDEX_COST_ADJ
• OPTIMIZER_FEATURES_ENABLED
• OPTIMIZER_MODE: ALL_ROWS, FIRST_ROWS, FIRST_ROWS_n
• OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES
• OPTIMIZER_USE_SQL_PLAN_BASELINES
• OPTIMIZER_DYNAMIC_SAMPLING
• OPTIMIZER_USE_INVISIBLE_INDEXES
• OPTIMIZER_USE_PENDING_STATISTICS
3-22
Setting the Optimizer Approach
3-23
Optimizing for Fast Response
3-24
Optimizing SQL Statements
Best throughput
• Time required to complete the request
• Suitable for:
– Batch processing
– Report applications
Fast response
• Time for retrieving the first rows
• Suitable for:
– Interactive applications
– Web-based or GUI applications
3-25
How the Query Optimizer
Executes Statements
3-26
Access Paths
• Full-table scans
• Row ID scans
• Index scans
• Cluster scans
• Hash scans
3-27
Join Orders
3-28
Join Methods
3-29
Optimizer Features and Oracle Database
Releases
OPTIMIZER_FEATURES_ENABLED
Features 9.0.0 to 9.2.0 10.1.0 to 10.1.0.5 10.2.0 to 10.2.0.2 11.1.0.6
Index fast full scan
Consideration of bitmap access to paths for tables with
only B-tree indexes
Complex view merging
Peeking into user-defined bind variables
Index joins
Dynamic sampling
Query rewrite enables
Skip unusable indexes
Automatically compute index statistics as part of creation
Cost-based query transformations
Allow rewrites with multiple MVs and/or base tables
Adaptive cursor sharing
Use extended statistics to estimate selectivity
Use native implementation for full outer joins
Partition pruning using join filtering
Group by placement optimization
Null aware antijoins
3-30
Summary
3-31
Optimizer Operations
Review: How the Query Optimizer
Executes Statements
4-2
Main Structures and Access Paths
4-3
Full Table Scan
---------------------------------------------------------------
| 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-4 fts.sql
Full Table Scans: Use Cases
• No suitable index
• Low selectivity filters (or no filters)
• Small table
• High degree of parallelism
• Full table scan hint: FULL (<table name>)
4-5
ROWID Scan
------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 37 | 1|
| 1 | TABLE ACCESS BY USER ROWID| EMP | 1 | 37 | 1|
------------------------------------------------------------------
B B . B B B
Block 6959–Row 2
Row migration
rowid.sql
4-6
ROWID Scans
sample.sql
4-7
Sample Table Scans
---------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 99 | 2 (0)|
| 1 | TABLE ACCESS SAMPLE| EMP | 4 | 99 | 2 (0)|
---------------------------------------------------------------------
B B B B B
4-8
Indexes: Overview
4-9
Normal B*-tree Indexes
Index entry
Root
Branch
4-10
Index Scans
4-11
Index Unique Scan
--------------------------------------------------------------------
| 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)
unique.sql
4-12
Index Range Scan
select *
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)
range.sql
4-13
Index Range Scan: Descending
---------------------------------------------------------------------
| 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)
desc.sql
4-14
Index Skip Scan
Min F16 F20 F26 F30 M10 M16 M20 M26 M30
F10 F16 F20 F26 F30 M10 M16 M20 M26 M30
F11 F17 F21 F27 F31 M11 M17 M21 M27 M31
F12 F18 F22 F28 F32 M12 M18 M22 M28 M32
F13 F19 F23 F29 F33 M13 M19 M23 M29 M33
F14 F24 F34 M14 M24 M34
F15 F25 F35 M15 M25 M35
L1 L2 L3 L4 L5 L6 L7 L8 L9 L10
4-15
Index Skip Scan: Example
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)
skip.sql
4-16
Index Range Scan: Function-Based
---------------------------------------------------------------------
| 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%')
fbi.sql
4-17
Index Scans
4-18
Index Full Scan
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)
fullscan.sql
4-19
Index Fast Full Scan
LEGEND:
db_file_multiblock_read_count = 4 SH=segment header
R=root block
multiblock read multiblock read B=branch block
L=leaf block
SH R L L L B L L B ... L
discard discard discard
fastfullscan.sql
4-20
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);
---------------------------------------------------------------------
| 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 |
--------------------------------------------------------------------
indexjoin.sql
4-21
The AND-EQUAL Operation
---------------------------------------------------------------------
| 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-22
andequal.sql
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);
4-23
Using Indexes: Considering Nullable
Columns
Column Null? CREATE UNIQUE INDEX person_ssn_ix
SSN Y ON person(ssn);
FNAME Y SELECT COUNT(*) FROM person;
LNAME N
SELECT STATEMENT |
SORT AGGREGATE |
PERSON TABLE ACCESS FULL| PERSON
DROP INDEX person_ssn_ix;
4-24
Index-Organized Tables
Indexed Accessing
access on table index-organized table
ROWID
Nonkey columns
Key column
Row header
4-25
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)
4-26
Bitmap Indexes
Table
File 3
Block 10
Index
Block 11
Block 12
4-27
Bitmap Index Access: Examples
SELECT * FROM PERF_TEAM WHERE country='FR';
---------------------------------------------------------------------
| 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 INDEX SINGLE VALUE | IX_B2 | | |
---------------------------------------------------------------------
Predicate: 3 - access("COUNTRY"='FR')
4-28
Combining Bitmap Indexes: Examples
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
4-29
Combining Bitmap Index Access Paths
bitmap.sql
4-30
Bitmap Operations
• BITMAP CONVERSION:
– TO ROWIDS
– FROM ROWIDS
– COUNT
• BITMAP INDEX:
– SINGLE VALUE
– RANGE SCAN
– FULL SCAN
• BITMAP MERGE
• BITMAP AND/OR
• BITMAP MINUS
• BITMAP KEY ITERATION
4-31
Bitmap Join Index
CREATE BITMAP INDEX cust_sales_bji
ON sales(c.cust_city)
FROM sales s, customers c
1.2.3
WHERE c.cust_id = s.cust_id;
Sales
Customers
10.8000.3
<Rognes, 1.2.3, 10.8000.3, 100010010010100P>
<Aix-en-Provence, 1.2.3, 10.8000.3, 000101000100000P>
<Marseille, 1.2.3, 10.8000.3, 010000001000001P>
4-32
Composite Indexes
MAKE MODEL
CARS
Index columns
create index cars_make_model_idx on cars(make, model);
select *
from cars
where make = 'CITROËN' 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-33
Invisible Index: Overview
Use index. Do not use index.
VISIBLE INVISIBLE
Index Index
OPTIMIZER_USE_INVISIBLE_INDEXES=FALSE
4-34
Invisible Indexes: Examples
4-35
Guidelines for Managing Indexes
4-36
Investigating Index Usage
4-37
Lesson Break
4-38
Clusters
ORD_NO PROD QTY ... --- Cluster Key
--- ------ ------ (ORD_NO)
101 A4102 20 101 ORD_DT CUST_CD
102 A2091 11 05-JAN-97 R01
102 G7830 20 PROD QTY
102 N9587 26 A4102 20
101 A5675 19 A5675 19
101 W0824 10 W0824 10
102 ORD_DT CUST_CD
07-JAN-97 N45
PROD QTY
ORD_NO ORD_DT CUST_CD A2091 11
------ ------ ------ G7830 20
101 05-JAN-97 R01 N9587 26
102 07-JAN-97 N45
4-39
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-40
When Are Clusters Useful?
4-41
Cluster Access Path: Examples
----------------------------------------------------------------
| 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)
-----------------------------------------------------------------
| 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-42
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-43
Buffer Sort Operator
---------------------------------------------------------------------
| 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%')
buffersort.sql
4-44
Inlist Iterator
Every value executed separately
deptno=1 deptno=2
4-45
inlist.sql
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
---------------------------------------------------------------------
---------------------------------------------------------------------
| 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')
stopkey.sql
4-47
Min/Max and First Row Operators
---------------------------------------------------------------------
| 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|
---------------------------------------------------------------------
3 - access("ID">500000)
4-48
Joining Multiple Tables
4-49
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) Join predicate
WHERE e.job = 'ANALYST' Nonjoin predicate
OR e.empno = 9999; Single-row predicate
SELECT e.ename,d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno Join predicate
AND (e.job = 'ANALYST' Nonjoin predicate
OR e.empno = 9999);
4-50 Single-row predicate
Comparing ANSI SQL Join Syntax
with Oracle SQL Join Syntax
Oracle SQL supports ANSI SQL joins.
Oracle SQL:2003
Equijoin Natural or inner join
Outer join Left outer join
Self join Join ON
Nonequijoin Join ON
Cartesian product Cross join
Inner/outer join with the + RIGHT OUTER JOIN
operator LEFT OUTER JOIN
4-51
Join Methods
4-52
Nested Loop Joins
4-53
Nested Loops Join
NL
• Driving row source is scanned TAF TAR
• Each row returned drives a lookup in Driving
IS
inner row source For
each Inner
• Joining rows are then returned
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-54
Nested Loops Join: 11g Implementation
NL
NL TAR
TAF IRS
Driving Inner
4-55
When Are Nested Loop Joins Used?
nestedloop.sql
nestedloopouter.sql
4-56
Hash Joins
4-57
Hash Join
HJ
• The smallest row source is used
Driving TAF TAR
to build a hash table.
Build hash
• The second row source is hashed table in IS
memory
and checked against the hash table. Probe
---------------------------------------------------------------------
| 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 RANGE SCAN | EDEPT | 14 | | 1
| 4 | TABLE ACCESS FULL | DEPT | 4 | 52 | 3
---------------------------------------------------------------------
Predicate: 1 - access("E"."DEPTNO"="D"."DEPTNO")
3 - access("ENAME" LIKE 'A%')
3 – filter ("ENAME" LIKE 'A%')
4-58
When Are Hash Joins Used?
hashjoin.sql
hashjoinouter.sql
4-59
Sort-Merge Joins
4-60
Sort Merge Join Merged
MJ
Sorted
Sorted
by same sort key. TAF TAF
• Sorted rows from both side are merged. Independent
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 (%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“ like 'A%')
4 - access("E"."DEPTNO"="D"."DEPTNO")
filter("E"."DEPTNO"="D"."DEPTNO")
4-61
When Are Sort-Merge Joins Used?
sortmerge.sql
4-62
Equijoins and Nonequijoins
SELECT e.ename, e.sal, s.grade
FROM emp e ,salgrade s
WHERE e.sal = s.hisal;
--------------------------------------- Equijoin
| Id | Operation | Name |
---------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | HASH JOIN | |
| 2 | TABLE ACCESS FULL| EMP |
| 3 | TABLE ACCESS FULL| SALGRADE |
--------------------------------------- SELECT e.ename, e.sal, s.grade
1 - access("E"."SAL"="S"."HISAL") 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 |
Nonequijoin | 3 | TABLE ACCESS FULL| SALGRADE |
---------------------------------------
3 - filter("E"."SAL">="S"."HISAL" AND
"E"."SAL"<="S"."HISAL")
4-63
Outer Joins
4-64
Subqueries and Joins
4-65
Nocorrelated subquery
select ename
from emp
where dept_id in ( select dept_id
from dept
where dname in ('IT'));
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------
| 0 |SELECT STATEMENT | | 3 | 105 | 7 (15)|
| 1 | NESTED LOOPS | | 3 | 105 | 7 (15)|
| 2 | NESTED LOOPS | | 4 | 88 | 3 (0)|
| *3 | TABLE ACCESS FULL | DEPT | 1 | 182 | 3 (0)|
| *4 | INDEX RANGE SCAN | E_DID| 14 | 182 | 3 (0)|
| 5 | INDEX ACCESS BY INDEX| EMP | 14 | 182 | 3 (0)|
ROWID
--------------------------------------------------------------------
3 - filter(“DEPT"."DEPTNO"=‘IT’)
4 – access (“DEPTNO” = “DEPTNO”
nocorrelated.sql
4-66
Correlated subquery
correlated.sql
4-67
Semijoins
EMP
Semijoins only look for the first match.DEPT 20
10
10
20
10
30
30
40
10
--------------------------------------------------------------------
| 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")
semijoin.sql
4-68
Antijoins
antijoin.sql
4-69
Sort Operations
• SORT UNIQUE
• SORT AGGREGATE
• SORT GROUP BY
• SORT JOIN
• SORT ORDER BY
4-70
Tuning Sort Performance
4-71
Top-N SQL
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------
| 0 |SELECT STATEMENT | | 5 | 105 | 7 (15)|
| * 1 | COUNT STOP KEY | | 5 | 105 | 7 (15)|
| 2 | VIEW | | 14 | 88 | 3 (0)|
| * 3 | SORT ORDER BY KEY | | 14 | 182 | 3 (0)|
| 4 | TABLE ACCESS FULL| EMP | 14 | 182 | 3 (0)|
--------------------------------------------------------------------
1 - filter(ROWNUM <=5)
3 - filter(ROWNUM <=5)
4-72
Result Cache Operator
--------------------------------------------------------------
| Id | Operation | Name |Rows
--------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11
| 1 | RESULT CACHE | 8fpza04gtwsfr6n595au15yj4y |
| 2 | HASH GROUP BY | | 11
| 3 | TABLE ACCESS FULL| EMPLOYEES | 107
--------------------------------------------------------------
4-73
Summary
4-74
Understanding Execution Plan
What Is an Execution Plan?
5-2
Where to Find Execution Plans?
5-3
Using Execution Plans
5-4
DBMS_XPLAN Package: Overview
5-5
EXPLAIN PLAN Command
5-6
EXPLAIN PLAN Command
EXPLAIN PLAN
SET STATEMENT_ID
= 'text'
FOR statement
5-7
EXPLAIN PLAN Command: Example
EXPLAIN PLAN
SET STATEMENT_ID = 'demo01' FOR
SELECT e.last_name, d.department_name
FROM hr.employees e, hr.departments d
WHERE e.department_id = d.department_id;
Explained.
explain.sql
5-8
EXPLAIN PLAN Command: Output
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 106 | 2862 | 6 (17|
| 1 | MERGE JOIN | | 106 | 2862 | 6 (17|
| 2 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 27 | 432 | 2 (0|
| 3 | INDEX FULL SCAN | DEPT_ID_PK | 27 | | 1 (0|
|* 4 | SORT JOIN | | 107 | 1177 | 4 (25|
| 5 | TABLE ACCESS FULL | EMPLOYEES | 107 | 1177 | 3 (0|
--------------------------------------------------------------------------------
4 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
filter("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
18 rows selected.
explainoutput.sql
5-9
Parse Tree
SELECT STATEMENT
0
1 MERGE JOIN
SORT JOIN
TABLE ACCESS BY 4
2
INDEX ROWID
of DEPARTMENTS FULL TABLE SCAN
of EMPLOYEES
3 5
INDEX FULL SCAN
DEPT_ID_PK
5-10
Interpreting an Execution Plan
Root/Parent Level 1
Executed first Executed next
From
Parent/Child top/down Parent/Child Level 2
From left/right
5-11
Execution Plan Interpretation: Example 1
--------------------------------------------------
| Id | Operation | Name | FILTER 1
--------------------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | FILTER | |
| 2 | NESTED LOOPS | | NESTED
| 3 | TABLE ACCESS FULL | EMP | LOOPS 2 6
| 4 | TABLE ACCESS BY INDEX ROWID| DEPT |
|* 5 | INDEX UNIQUE SCAN | PK_DEPT | TABLE ACCESS FULL
|* 6 | TABLE ACCESS FULL | SALGRADE | SALGRADE
--------------------------------------------------
3 4 TABLE ACCESS
Predicate Information (identified by operation id): BY ROWID
--------------------------------------------------- DEPT
TABLE ACCESS FULL
EMP
1 - filter( NOT EXISTS
(SELECT 0 FROM "SALGRADE" "SALGRADE" WHERE
5
"HISAL">=:B1 AND "LOSAL"<=:B2))
5 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")
INDEX UNIQUE SCAN
6 - filter("HISAL">=:B1 AND "LOSAL"<=:B2) PK_DEPT
5-12
Execution Plan Interpretation: Example 2
0 SELECT STATEMENT
1 0 NESTED LOOPS 1
2 1 NESTED LOOPS
3 2 TABLE ACCESS BY INDEX ROWID LOCATIONS
4 3 INDEX RANGE SCAN LOC_CITY_IX
5 2 TABLE ACCESS BY INDEX ROWID DEPARTMENTS
6 5 INDEX RANGE SCAN DEPT_LOCATION_IX 2 7
7 1 TABLE ACCESS BY INDEX ROWID EMPLOYEES
8 7 INDEX UNIQUE SCAN EMP_EMP_ID_PK
3 5 8
4 6
5-13
Using the V$SQL_PLAN View
5-14
V$SQL_PLAN Columns
5-15
V$SQL_PLAN
SQL_ID SQL_TEXT
------- -----------------------------------------------------
13saxr0mmz1s3 SELECT SQL_ID, SQL_TEXT FROM V$SQL………
47ju6102uvq5q SELECT e.last_nane, d.department_name……
5_16.sql
5-16
Querying V$SQL_PLAN
SELECT PLAN_TABLE_OUTPUT FROM
TABLE(DBMS_XPLAN.DISPLAY_CURSOR('47ju6102uvq5q'));
4 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
filter("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
24 rows selected.
5-17
V$SQL_PLAN_STATISTICS View
5-18
Automatic Workload Repository
5-19
Managing AWR with PL/SQL
• Creating snapshots
• Dropping snapshots
• Managing snapshot settings
5-20
AWR Views
• V$ACTIVE_SESSION_HISTORY
• V$metric views
• DBA_HIST views:
– DBA_HIST_ACTIVE_SESS_HISTORY
– DBA_HIST_BASELINE
DBA_HIST_DATABASE_INSTANCE
– DBA_HIST_SNAPSHOT
– DBA_HIST_SQL_PLAN
– DBA_HIST_WR_CONTROL
5-21
AWR
SQL_ID SQL_TEXT
------- -----------------------------------------------------
F8tc4anpz5cdb select sql_id, sql_text from v$SQL …
454rug2yva18w select /* example */ * from …
awr.sql
5-22
Querying the AWR
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
SQL_ID 454rug2yva18w
--------------------
select /* example */ * from hr.employees natural join hr.departments
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 6 (100)| |
| 1 | HASH JOIN | | 11 | 968 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS FULL| DEPARTMENTS | 11 | 220 | 2 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMPLOYEES | 107 | 7276 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------
5-23
Generating SQL Reports from AWR Data
SQL> @$ORACLE_HOME/rdbms/admin/awrsqrpt
5-24
SQL*Plus AUTOTRACE
OFF
SET AUTOTRACE ON
TRACE[ONLY]
EXPLAIN
STATISTICS
SHOW AUTOTRACE
5-25
SQL*Plus AUTOTRACE: Examples
5-26
SQL*Plus AUTOTRACE: Statistics
set autotrace traceonly statistics
SELECT *
FROM products;
Statistics
------------------------------------------------------
1 recursive calls
0 db block gets
9 consistent gets
3 physical reads
0 redo size
15028 bytes sent via SQL*Net to client
556 bytes received via SQL*Net from client
6 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
72 rows processed
auto.sql
5-27
SQL Monitoring: Overview
STATISTICS_LEVEL=TYPICAL|ALL
+
CONTROL_MANAGEMENT_PACK_ACCESS=DIAGNOSTIC+TUNING
SQL monitoring
Every
second V$SQL_MONITOR
V$SQL_PLAN_MONITOR
DBMS_SQLTUNE.REPORT_SQL_MONITOR
V$SQL
V$SQL_PLAN
V$ACTIVE_SESSION_HISTORY
V$SESSION_LONGOPS
V$SESSION
5-28
SQL Monitoring Report: Example
SQL> set long 10000000
SQL> set longchunksize 10000000
SQL> set linesize 200
SQL> select dbms_sqltune.report_sql_monitor from dual;
Global Information
Status : EXECUTING
Instance ID : 1
Session ID : 125
SQL ID : fazrk33ng71km
SQL Execution ID : 16777216
Plan Hash Value : 1047182207
Execution Started : 02/19/2008 21:01:18
First Refresh Time : 02/19/2008 21:01:22
Last Refresh Time : 02/19/2008 21:01:42
------------------------------------------------------------
| Elapsed | Cpu | IO | Other | Buffer | Reads |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Gets | |
------------------------------------------------------------
| 22 | 3.36 | 0.01 | 19 | 259K | 199K |
------------------------------------------------------------
5-29
SQL Monitoring Report: Example
==================================================================================
Starts | Rows | Activity | Activity Detail | Progress |
| (Actual) | (percent) | (sample #) | |
1 | | | | |
1 | | | | |
1 | 42081K | 100.00 | Cpu (4) | 74% |
==================================================================================
5-30
Summary
5-31
Materialized Views
Materialized Views
A materialized view:
• Is a precomputed set of results
• Has its own data segment and offers:
– Space management options
– Use of its own indexes
• Is useful for:
– Expensive and complex joins
– Summary and aggregate data
6-2
If Materialized Views Are Not Used
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 …)
1 0 MAT_VIEW REWRITE ACCESS (FULL) OF 'CUST_SALES_MV' (MAT_VIEW
REWRITE) (Cost=6 …)
mv.sql
How Many Materialized Views?
6-5
Creating Materialized Views:
Syntax Options
AS SELECT … FROM …
Creating Materialized Views: Example
6-8
Refresh Methods
6-9
Refresh Modes
• Manual refresh
– Specify ON DEMAND option
– By using the DBMS_MVIEW package
• Automatic refresh Synchronous
– Specify ON COMMIT option
– Upon commit of changes to the underlying tables
but independent of the committing transaction
• Automatic refresh Asynchronous
– Specify using START WITH and NEXT clauses
– Defines a refresh interval for the materialized view
• REFRESH_MODE in ALL_MVIEWS
6-10
Manual Refresh with DBMS_MVIEW
6-11
Materialized Views: Manual Refresh
6-12
Query Rewrites
6-13
Query Rewrites
6-14
Enabling and Controlling
Query Rewrites
6-15
Query Rewrite: Example
mvexample.sql
Query Rewrite: Example
SELECT t.week_ending_day
, t.calendar_year
, p.prod_subcategory
, sum(c.unit_cost) AS dollars
FROM costs c, times t, products p
WHERE c.time_id = t.time_id
AND c.prod_id = p.prod_id
AND t.calendar_year = '1999'
GROUP BY t.week_ending_day, t.calendar_year
, p.prod_subcategory
HAVING sum(c.unit_cost) > 10000;
SELECT week_ending_day
, prod_subcategory
, dollars
FROM cost_per_year_mv
WHERE calendar_year = '1999'
AND dollars > 10000;
mvexample2.sql
Verifying Query Rewrite
6-19
Using the DBMS_MVIEW Package
DBMS_MVIEW methods
• EXPLAIN_MVIEW
• EXPLAIN_REWRITE
• TUNE_MVIEW
6-20
Tuning Materialized Views for
Fast Refresh and Query Rewrite
DBMS_ADVISOR.TUNE_MVIEW (
task_name IN OUT VARCHAR2,
mv_create_stmt IN [CLOB | VARCHAR2]
);
6-21
Results of Tune_MVIEW
• IMPLEMENTATION recommendations
– CREATE MATERIALIZED VIEW LOG statements
– ALTER MATERIALIZED VIEW LOG FORCE
statements
– One or more CREATE MATERIALIZED VIEW
statements
• UNDO recommendations
– DROP MATERIALIZED VIEW statements
6-22
DBMS_MVIEW.EXPLAIN_MVIEW Procedure
• Accepts:
– Materialized view name
– SQL statement
• Advises what is and what is not possible:
– For an existing materialized view
– For a potential materialized view before you create it
• Stores results in MV_CAPABILITIES_TABLE
(relational table) or in a VARRAY
• utlxmv.sql must be executed as the current user
to create MV_CAPABILITIES_TABLE.
6-23
Explain Materialized View: Example
EXEC dbms_mview.explain_mview (
'cust_sales_mv', '123');
6-24
Materialized View Hints
6-26
Optimizer Statistics
Optimizer Statistics
7-2
Types of Optimizer Statistics
7-3
Table Statistics (USER_TAB_STATISTICS)
• Used to determine:
– Table access cost
– Join cardinality
– Join order
• Some of the statistics gathered are:
– Row count (NUM_ROWS)
– Block count (BLOCKS) Exact
– Empty blocks (EMPTY_BLOCKS) Exact
– Average free space per block (AVG_SPACE)
– Number of chained rows (CHAIN_CNT)
– Average row length (AVG_ROW_LEN)
– Statistics status (STALE_STATS)
tablestat.sql
7-4
Index Statistics (USER_IND_STATISTICS)
• Used to decide:
– Full table scan versus index scan
• Statistics gathered are:
– B*-tree level (BLEVEL) Exact
– Leaf block count (LEAF_BLOCKS)
– Clustering factor (CLUSTERING_FACTOR)
– Distinct keys (DISTINCT_KEYS)
– Average number of leaf blocks in which each distinct value in
the index appears (AVG_LEAF_BLOCKS_PER_KEY)
– Average number of data blocks in the table pointed to by a
distinct value in the index (AVG_DATA_BLOCKS_PER_KEY)
– Number of rows in the index (NUM_ROWS)
indstat.sql
7-5
Index Clustering Factor
A B C A B C A B C
A A A B B B C C C
Block 1 Block 2 Block 3
7-6
Column Statistics (USER_TAB_COL_STATISTICS)
colstat.sql
7-7
Histograms
7-8
Frequency Histograms
Cumulative cardinality
ENDPOINT NUMBER
20000
10000
0
1 3 5 7 10 16 27 32 39 49
7-9
Viewing Frequency Histograms
BEGIN
DBMS_STATS.gather_table_STATS (OWNNAME=>'OE', TABNAME=>'INVENTORIES',
METHOD_OPT => 'FOR COLUMNS SIZE 20 warehouse_id');
END;
ENDPOINT_NUMBER ENDPOINT_VALUE
--------------- --------------
36 1
213 2
261 3
…
7 - 10 frequencyhist.sql
Height-Balanced Histograms
Popular value
ENDPOINT VALUE
1 7 10 10 32 49
Same number
of rows per bucket
0 1 2 3 4 5
7 - 11
Viewing Height-Balanced Histograms
BEGIN
DBMS_STATS.gather_table_STATS(OWNNAME =>'OE', TABNAME=>'INVENTORIES',
METHOD_OPT => 'FOR COLUMNS SIZE 10 quantity_on_hand');
END;
ENDPOINT_NUMBER ENDPOINT_VALUE
--------------- --------------
0 0
1 27
2 42
3 57
…
balancedhist.sql
7 - 12
Histogram Considerations
7 - 13
Multicolumn Statistics: Overview
VEHICLE
MAKE MODEL
1
S(MAKE Λ MODEL)=S(MAKE)xS(MODEL)
select
dbms_stats.create_extended_stats('jfv','vehicle','(make,model)')
2
from dual;
exec dbms_stats.gather_table_stats('jfv','vehicle',-
method_opt=>'for all columns size 1 for columns (make,model) size 3'); 3
MAKE MODEL
4
S(MAKE Λ MODEL)=S(MAKE,MODEL)
7 - 14
Expression Statistics: Overview
VEHICLE
MODEL
VEHICLE
MODEL Still possible
Recommended
VEHICLE DBA_STAT_EXTENSIONS
S(upper( MODEL))=0.01 MODEL
SYS_STU3FOQ$BDH0S_14NGXFJ3TQ50
exec dbms_stats.gather_table_stats('jfv','vehicle',-
method_opt=>'for all columns size 1 for columns (upper(model)) size 3');
7 - 15
Gathering System Statistics
7 - 16
Gathering System Statistics: Example
EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS(
First day interval => 120,
stattab => 'mystats', statid => 'OLTP');
EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS(
First night interval => 120,
stattab => 'mystats', statid => 'OLAP');
EXECUTE DBMS_STATS.IMPORT_SYSTEM_STATS(
Next days stattab => 'mystats', statid => 'OLTP');
EXECUTE DBMS_STATS.IMPORT_SYSTEM_STATS(
Next nights
stattab => 'mystats', statid => 'OLAP');
7 - 17
Gathering System Statistics: Example
7 - 18
Mechanisms for Gathering Statistics
7 - 19
When to Gather Statistics Manually
7 - 20
Manual Statistics Gathering
7 - 21
Manual Statistics Collection: Factors
7 - 22
Managing Statistics Collection: Example
dbms_stats.gather_table_stats
('sh' -- schema
,'customers' -- table
, null -- partition
, 20 -- sample size(%)
, false -- block sample?
,'for all columns' -- column spec
, 4 -- degree of parallelism
,'default' -- granularity
, true ); -- cascade to indexes
dbms_stats.set_param('CASCADE',
'DBMS_STATS.AUTO_CASCADE');
dbms_stats.set_param('ESTIMATE_PERCENT','5');
dbms_stats.set_param('DEGREE','NULL');
7 - 23
Optimizer Dynamic Sampling: Overview
7 - 24
Optimizer Dynamic Sampling at Work
7 - 25
OPTIMIZER_DYNAMIC_SAMPLING
7 - 26
Locking Statistics
7 - 27
Summary
7 - 28
Using Bind Variables
Cursor Sharing and Different Literal Values
Cursor sharing
Library cache
8-2
Cursor Sharing and Bind Variables
Cursor sharing
Library cache
8-3
Bind Variables in SQL*Plus
COUNT(*)
----------
30
COUNT(*)
----------
2
8-4
Bind Variable Peeking
First time
you execute
Plan A
min_sal=12000
Next time
you execute
8-5
Bind Variable Peeking
1 min_sal=12000
2 min_sal=18000
3 min_sal=7500
Plan A
One plan not always appropriate for all bind values
8-6
Cursor Sharing Enhancements
8-7
The CURSOR_SHARING Parameter
8-8
Forcing Cursor Sharing: Example
System-generated
bind variable
8-9
Adaptive Cursor Sharing: Overview
8 - 10
Adaptive Cursor Sharing: Architecture
Bind-sensitive cursor
System 11
observes SELECT * FROM emp WHERE sal = :1 and dept = :2
statement
for a while. Bind-aware cursor
Initial selectivity cube Same selectivity cube No need
Initial plan
for new plan
GB S
o GB
HJ f
t HJ
0.0025 .
HJ
P
a
0.003 . HJ
2
r
s
e
0.15 0.18
:1=A & :2=B ⇒ S(:1)=0.15 ∧ S(:2)=0.0025 :1=C & :2=D ⇒ S(:1)=0.18 ∧ S(:2)=0.003
Merged selectivity cubes No need Second selectivity cube Need new plan
for new plan
H
a
r
GB GB H
a
r
0.009 . GB GB
d HJ HJ HJ HJ
d
4 P
a
0.004 . HJ HJ
P HJ HJ 3
a
r r
s Cubes merged s
e e
0.28 0.3
:1=G & :2=H ⇒ S(:1)=0.28 ∧ S(:2)=0.004 :1=E & :2=F ⇒ S(:1)=0.3 ∧ S(:2)=0.009
8 - 11
Adaptive Cursor Sharing: Views
8 - 12
Adaptive Cursor Sharing: Example
Selectivity
Plan A Plan B
'AD_ASST'
'SA_REP'
acs.sql
8 - 13
Interacting with Adaptive Cursor Sharing
• CURSOR_SHARING:
– If CURSOR_SHARING <> EXACT, statements containing
literals may be rewritten using bind variables.
– If statements are rewritten, adaptive cursor sharing may apply
to them.
• SQL Plan Management (SPM):
– If OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES is set to
TRUE, only the first generated plan is used.
– As a workaround, set this parameter to FALSE, and run your
application until all plans are loaded in the cursor cache.
– Manually load the cursor cache into the corresponding plan
baseline.
8 - 14
Summary
8 - 15
Hints
Optimizer Hints
Optimizer hints:
• Influence optimizer decisions
• Example:
SELECT /*+ INDEX(e empfirstname_idx) skewed col */ *
FROM employees e
WHERE first_name='David'
9-2
Optimizer Hints
Optimizer hints:
• Are used to alter execution plans
• Force optimizer to use certian plan
• Provide a mechanism to instruct the optimizer to
choose a certain query execution plan
9-3
Types of Hints
9-4
Specifying Hints
MERGE
SELECT
INSERT /*+ hint */
UPDATE comment
text
DELETE
MERGE
SELECT
INSERT --+ hint
UPDATE comment
text
DELETE
9-5
Rules for Hints
9-6
Hint Recommendations
9-7
Optimizer Hint Syntax: Example
9-8
Hint Categories
9-9
Optimization Goals and Approaches
9_10.sql
9-10
Hints for Access Paths
9_11.sql
9-11
Hints for Access Paths
9_12.sql
9-12
INDEX_COMBINE Hint: Example
SELECT --+INDEX_COMBINE(CUSTOMERS)
cust_last_name
FROM SH.CUSTOMERS
WHERE ( CUST_GENDER= 'F' AND
CUST_MARITAL_STATUS = 'single')
OR CUST_YEAR_OF_BIRTH BETWEEN '1917'
AND '1920';
9-13
INDEX_COMBINE Hint: Example
Execution Plan
---------------------------------------------------
| 0 | SELECT STATEMENT |
| 1 | TABLE ACCESS BY INDEX ROWID | CUSTOMERS
| 2 | BITMAP CONVERSION TO ROWIDS |
| 3 | BITMAP OR |
| 4 | BITMAP MERGE |
| 5 | BITMAP INDEX RANGE SCAN | CUST_YOB_BIX
| 6 | BITMAP AND |
| 7 | BITMAP INDEX SINGLE VALUE| CUST_MARITAL_BIX
| 8 | BITMAP INDEX SINGLE VALUE| CUST_GENDER_BIX
9-14
Hints for Query Transformation
9_15.sql
9-15
Hints for Query Transformation
9_16.sql
9-16
Hints for Join Orders
9_17.sql
9-17
Hints for Join Operations
9-18 9_18.sql
Additional Hints
9-19
Additional Hints
9-20
Hints for Suppressing Index Usage
Hint Description
NO_INDEX Disallows use of any indexes
9-21
Hints and Views
9-22
Hints for View Processing
9-23
Global and Local Hints
9-24
9_24.sql
Specifying a Query Block in a Hint
9-25
Specifying a Full Set of Hints
9-26
Summary
9-27
Application Tracing
End-to-End Application Tracing Challenge
10 - 2
End-to-End Application Tracing
10 - 3
Location for Diagnostic Traces
DIAGNOSTIC_DEST
V$DIAG_INFO
ADR trace = Oracle Database 10g trace – critical error trace
10 - 4
What Is a Service?
10 - 5
Use Services with Client Applications
ERP=(DESCRIPTION=
(ADDRESS=(PROTOCOL=TCP)(HOST=mynode)(PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=ERP)))
url="jdbc:oracle:oci:@ERP"
url="jdbc:oracle:thin:@(DESCRIPTION=
(ADDRESS=(PROTOCOL=TCP)(HOST=mynode)(PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=ERP)))"
10 - 6
Tracing Services
10 - 7
Use Enterprise Manager to Trace Services
10 - 8
Service Tracing: Example
exec DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE(-
'AP', 'PAYMENTS', 'QUERY_DELINQUENT');
10 - 9
Session Level Tracing: Example
EXEC dbms_monitor.DATABASE_TRACE_DISABLE();
EXEC dbms_monitor.SESSION_TRACE_DISABLE(session_id
=>27, serial_num=>60);
10 - 10
Trace Your Own Session
• Enabling trace:
EXEC DBMS_SESSION.SESSION_TRACE_ENABLE(waits =>
TRUE, binds => FALSE);
• Disabling trace:
EXEC DBMS_SESSION.SESSION_TRACE_DISABLE();
10 - 11
The trcsess Utility
Client Client Client Clients
TRCSESS TRCSESS
Report
file
10 - 12
Invoking the trcsess Utility
trcsess [output=output_file_name]
[session=session_id]
[clientid=client_identifier]
[service=service_name]
[action=action_name]
[module=module_name]
[<trace file names>]
TRCSESS
Consolidated
trace file
10 - 13
The trcsess Utility: Example
exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE( -
client_id=>'HR session', waits => FALSE, binds => FALSE);
Third session
exec DBMS_MONITOR.CLIENT_ID_TRACE_DISABLE( -
client_id => 'HR session');
10 - 14
SQL Trace File Contents
10 - 15
SQL Trace File Contents: Example
10 - 16
Formatting SQL Trace Files: Overview
Consolidated Concatenated
trace file tkprof trace file
Report
file
10 - 17
Invoking the tkprof Utility
mytrace.sql
10 - 18
tkprof Sorting Options
10 - 19
tkprof Sorting Options
10 - 20
Output of the tkprof Command
10 - 21
Output of the tkprof Command
10 - 22
Output of the tkprof Command
10 - 23
tkprof Output with No Index: Example
...
select max(cust_credit_limit)
from customers
where cust_city ='Paris'
10 - 24
tkprof Output with Index: Example
...
select max(cust_credit_limit) from customers
where cust_city ='Paris'
10 - 25
Summary
10 - 26