0% found this document useful (0 votes)
38 views325 pages

SQL Optimization Slides

The document provides an overview of the agenda for a 3 day Oracle SQL optimization course. Day 1 covers exploring Oracle database architecture, introduction to SQL tuning and the optimizer. Day 2 focuses on additional optimizer operations and interpreting execution plans. Day 3 discusses optimizer statistics, bind variables, optimizer hints and application tracing.

Uploaded by

Zrinka Šimunić
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
38 views325 pages

SQL Optimization Slides

The document provides an overview of the agenda for a 3 day Oracle SQL optimization course. Day 1 covers exploring Oracle database architecture, introduction to SQL tuning and the optimizer. Day 2 focuses on additional optimizer operations and interpreting execution plans. Day 3 discusses optimizer statistics, bind variables, optimizer hints and application tracing.

Uploaded by

Zrinka Šimunić
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 325

Oracle SQL Optimization

Žarko Češljaš, TONGA d.o.o.


Course Agenda

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

• The Oracle Database consists of two main


components:
– The database: physical structures
– The instance: memory structures
• The size and structure of these components
impact performance.

1-2
Oracle Instance Management

SGA

Shared pool Streams pool Large pool

Database Redo log


Java pool
buffer cache buffer

System Process Database Log


Monitor Monitor Writer Writer
SMON PMON DBW0 LGWR
Archived
redo log
files

Check
Archiver
point Control Redo log ARC0
CKPT Data
file files
files

1-3
Database Physical Structure

Control files

Data files Online redo log files

Parameter file Password file Archive log files

1-4
Oracle Memory Structures

PGA PGA PGA

Server Server Server


process 1 process 2 process 3

SGA

Shared pool Streams pool Large pool

Database Redo log


Java Pool
buffer cache buffer

1-5
Automatic Shared Memory Management

SGA

Shared pool Fixed SGA Large pool

Database Redo log


Java pool
buffer cache buffer

Which size to choose?

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)

• PGA is a memory area that contains: Server


process
– Session information
– Cursor information
– SQL execution work areas
- Sort area Stack
User Global Area (UGA)
User
Space Session Cursor SQL
- Hash join area Data
Status Area

- Bitmap merge area


- Bitmap create area
• Work area size influences SQL performance.
• Work areas can be automatically or manually
managed.

1-8
Automated SQL Execution Memory (PGA)
Management

• Allocation and tuning of PGA memory is simplified


and improved.
– Efficient memory allocation for varying workloads
– Queries optimized for both throughput and
response times
• DBAs can use parameters to specify the policy for
PGA sizing.

PGA_AGGREGATE_TARGET

1-9
Database Buffer Cache

• Is a part of the SGA


• Holds copies of data blocks that are read from data
files
• Is shared by all concurrent processes
SGA

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

• Provides large memory allocations for:


– Session memory for the shared server and Oracle XA
interface
– Parallel execution buffers
– I/O server processes Server
– Oracle Database backup process
and restore operations
• Optional pool better suited
when using the following: SGA

– Parallel execution I/O buffer


Free
memory
– Recovery Manager Response Request
– Shared server queue queue
Large pool

1-12
Java Pool and Streams Pool

• Java pool memory is used in server memory for all


session-specific Java code and data in the JVM.
• Streams pool memory is used exclusively by
Oracle Streams to:
– Store buffered queue messages
– Provide memory for Oracle Streams processes

Java pool Streams pool

1-13
Background Process Roles

RCBG MMON CJQ0 QMNn MMAN

Database
SGA Redo log
buffer Shared pool
buffer
cache

CKPT PMON SMON DBWn LGWR ARCn

1-14
Connecting to an Instance

User Server

Oracle database

User Server

Client

Application server Server

User Server
Browser

1-15
Shared SQL Areas

Cursor for Cursor for


SELECT statement 2 SELECT statement 1

SGA Shared SQL

SELECT SELECT SELECT


statement 1 statement 2 statement 1

User A User B User C

1-16
SQL Statement Processing Phases

Open Close

Parse Bind Execute Fetch

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

Data Redo log


Server buffer
files process
Shared pool

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

• Segments exist in a tablespace.


• Segments are collections of extents.
• Extents are collections of data blocks.
• Data blocks are mapped to disk blocks.

Segment Extents Data Disk


blocks blocks

1-24
SYSTEM and SYSAUX Tablespaces

• The SYSTEM and SYSAUX tablespaces are mandatory


tablespaces that are created at the time of database
creation. They must be online.
• The SYSTEM tablespace is used for core functionality
(for example, data dictionary tables).
• The auxiliary SYSAUX tablespace is used for additional
database components (such as the Enterprise
Manager Repository).

1-25
Functions of the Oracle Query Optimizer

The Oracle query optimizer determines the most


efficient execution plan and is the most important step
in the processing of any SQL statement.
The optimizer:
• Evaluates expressions and conditions
• Uses object and system statistics
• Decides how to access the data
• Decides how to join tables
• Decides which path is most efficient

1-26
Top Database Performance Issues

• Bad connection management


• Poor use of cursors and the shared pool
• Bad SQL
• Nonstandard initialization parameters
• I/O issues
• Long full-table scans
• In-disk sorts
• High amounts of recursive SQL
• Schema errors and optimizer problems

1-27
Summary

In this lesson, you should have learned about the


Oracle Database architecture and various components
that require tuning.

1-28
Tuning Methodology
Reasons for Inefficient SQL Performance

• Stale or missing optimizer statistics


• Missing access structures
• Suboptimal execution plan selection
• Poorly constructed SQL

2-2
What You Need to Write Efficient SQL

• Knowledge of the physical organization of what you


are querying
• Knowledge of what the database is capable of doing
• Knowledge of all the features of SQL
• A solid understanding of the goal – what the question
is?

2-3
Inefficient SQL: Examples

SELECT COUNT(*) FROM products p


WHERE prod_list_price <
1
1.15 * (SELECT avg(unit_cost) FROM costs c
WHERE c.prod_id = p.prod_id)

SELECT * FROM job_history jh, employees e


2 WHERE substr(to_char(e.employee_id),2) =
substr(to_char(jh.employee_id),2)

3 SELECT * FROM orders WHERE order_id_char = 1205

SELECT * FROM employees


4
WHERE to_char(salary) = :sal

SELECT * FROM parts_old


5 UNION
SELECT * FROM parts_new

2_4a.sql, 2_4b,.sql 2_4c.sql


2-4
Performance Problems

• Task takes longer time to perform and use


excessive resources
• Inadequate consumable resources
– CPU
– I/O
– Memory (may be detected as an I/O problem)
– Data communications resources
• High-load SQL
• Contention

2-5
SQL Tuning Tasks: Overview

• Identifying high-load SQL


• Gathering statistics
• Generating system statistics
• Rebuilding existing indexes
• Maintaining execution plans
• Creating new index strategies

2-6
Tuning Goals

• Reduce the response time and resource usage:


– Reduce the workload
– Balance the workload
– Parallelize the workload

2-7
Tuning Tools: Overview

• Automatic Database Diagnostic Monitor (ADDM)


• SQL Tuning Advisor
• SQL Tuning Sets
• SQL Access Advisor
• SQL Performance Analyzer
• SQL Monitoring
• SQL Plan Management

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

1. Identify causes of poor performance.


2. Identify problematic SQL.
• Automatic: ADDM, Top SQL
• Manual: V$ views, statspack
3. Apply a tuning method.
• Manual tuning
• Automatic SQL tuning
4. Implement changes to:
• SQL statement constructs
• Access structures such as indexes

2-10
Manual Tuning

1. Gather information about the referenced objects.


2. Gather optimizer statistics.
3. Review execution plans.
4. Restructure SQL statements.
5. Restructure indexes and create materialized views.
6. Maintain execution plans.

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

• Gather statistics for all tables.


• Gather new statistics when existing statistics
become stale.
• 11g gathering is done automatically (every night)
• Gather statistics on all DB objects automatically
and maintain it by system job.
• If statistics is no gathered the optimizer has no
sufficient information to generate the best plan

2-13
The factors affecting execution plan

• Data structures and volume


• Indexes
• PRIMARY and UNIQUE keys
• Views
• Data skews
• Cardinality
• Selectivity
• Cost

2-14
Reviewing the Execution Plan

• Driving table has the best filter.


• Fewest number of rows are being returned to the
next step.
• The join method is appropriate for the number of
rows being returned.
• Views are used efficiently.
• There are no unintentional Cartesian products.
• Each table is being accessed efficiently.
• Examine the predicates in the SQL statement and
the number of rows in the table.
• A full table scan does not mean inefficiency.

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 )

is typically processed as:

SELECT * FROM t1, ( SELECT DISTINCT y FROM


t2 ) t2
WHERE t1.x = t2.y;

The subquery is evaluated, distinct'ed, indexed (or


hashed or sorted) and then joined to the original
table
2-17
EXISTS vs. IN

SELECT * FROM t1 WHERE EXISTS ( SELECT null


FROM t2 WHERE y = x )

is typically processed as:

FOR x IN ( SELECT * FROM t1 ) LOOP


IF ( EXISTS ( SELECT null FROM t2 WHERE
y = x.x ) THEN
OUTPUT THE RECORD
END IF
END LOOP
It always results in a full scan of T1 whereas the first
query can make use of an index on T1(x)
2-18
Restructuring the Indexes

• Remove unnecessary indexes to speed the DML.


• Index the performance-critical access paths.
• Reorder columns in existing concatenated
indexes.
• Add columns to the index to improve selectivity.
• Create appropriate indexes based on usage type:
– B*tree
– Bitmap
– Bitmap join
– Concatenated
• Consider index-organized tables.

2-19
Maintaining Execution Plans over Time

• Maintain execution plan over time using either


stored statistics or stored execution plans
– Stored outlines
– Stored statistics
• Lock statistic at an optimal point
– Locking statistics

2-20
Automatic SQL Tuning

• Automatic SQL tuning facilitates these steps:


– Gather information on the referenced objects.
– Verify optimizer statistics.
– Review execution plans.
– Restructure SQL statements
– Restructure indexes and create materialized views.
– Maintain execution plans.
• Four types of analysis are performed in automatic
SQL tuning:
– Statistics analysis
– SQL profiling
– Access path analysis
– SQL structure analysis

2-21
Automatic Tuning Mechanisms

You can perform automatic SQL tuning using:


• SQL Tuning Advisor
• SQL Access advisor

2-22
SQL Tuning Advisor

The SQL Tuning Advisor does the following:


• Accepts one or more SQL statements from:
– Automatic Database Diagnostic Monitor (ADDM)
– Automatic Workload Repository (AWR)
– Cursor cache
– Custom SQL as defined by the user
• Provides:
– Recommendations
– Explanations
– Expected benefits
– SQL commands for implementing the
recommendations

2-23
SQL Access Advisor

The SQL Access Advisor does the following:


• Provides comprehensive advice on schema
design based on the entire workload from:
– Cursor cache
– Automatic Workload Repository (AWR)
– User-defined workload
– Hypothetical workload if a schema contains
dimensions or primary/foreign key relationships
• Analyzes the entire workload and recommends:
– Creating new indexes as needed
– Dropping any unused indexes
– Creating new materialized views and materialized
view logs

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

• Accurately represent business practices


• Focus on the most frequent and important
business transactions
• Use modeling tools
• Normalize the data (OLTP vs. DW)

2-27
Table Design

• Compromise between flexibility and performance


– Principally normalize
– Selectively denormalize
• Use Oracle performance features
– Default values
– Check constraints
– Materialized views
– Clusters
– Partitioning
• Focus on business-critical tables

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

• Simplifies application design


• Is transparent to the end user
• Can cause suboptimal execution plans

2-30
SQL Execution Efficiency

• Good database connection management


• Good cursor usage and management
• Minimizing parsing
• Using bind variables

2-31
Writing SQL to Share Cursors

• Create generic code using the following:


– Stored procedures and packages
– Database triggers
– Any other library routines and procedures
• Write to format standards:
– Case
– White space
– Comments
– Object references
– Bind variables

2-32
Controlling Shared Cursors

The CURSOR_SHARING initialization parameter can be


set to:
• EXACT (default) - allows statements with identical
text to share the same cursor
• SIMILAR - causes statements that may differ in
some literals, but are otherwise identical, to share
a cursor, unless the literals affect either the
meaning of the statement or the degree to which
the plan is optimized
• FORCE - forces statements that may differ in
some literals, but are otherwise identical, to share
a cursor, unless the literals affect the meaning of
the statement
2-33
Summary

In this lesson, you should have learned how to:


• Manage performance
– Start early; be proactive
– Set measurable objectives
– Monitor requirements compliance
– Handle exceptions and changes
• Identify performance problems
– Inadequate consumable resources
– Inadequate design resources
– Critical resources
– Excessive demand

2-34
Summary

In this lesson, you should have learned how to:


• Tune SQL statements
– Analyze the results at each step
– Tune the physical schema
– Choose when to use SQL
– Reuse SQL statements when possible
– Design and tune the SQL statement
– Get maximum performance with the optimizer

2-35
Introduction to Optimizer
Oracle Optimizer

The optimizer creates an execution plan for every SQL


statement by:
• Evaluating expressions and conditions
• Using object and system statistics
• Deciding how to access the data
• Deciding how to join tables
• Deciding which path is most efficient
• Comparing the cost for execution of different
plans
• Determining the least-cost plan

3-2
SQL Statement Implementation

User User User User User


process process process process process
Client
Server
Server Server Server Server Server
process process process process process

Private Private Private Aggregated Private Private


SQL area SQL area SQL area PGA SQL area SQL area

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

Syntactic and semantic check

Privileges check

Private Parse
SQL area Allocate private SQL Area call

Parsed representation

Existing shared No Parse operation


(Hard parse) (Optimization)
SQL area?
Allocate shared SQL area
Yes (Soft parse)

Shared
Execute statement SQL area

3-4
Why Do You Need an Optimizer?

Query to optimize

SELECT * FROM emp WHERE job = 'MANAGER';

Schema
How can I retrieve these rows? information
Possible access paths
Read
Use the
index. 1 each row
and check.

Statistics Which one is faster? 2

Only 1% of employees are managers

Use the I have a plan!


3
index

3-5
Why Do You Need an Optimizer?

Query to optimize

SELECT * FROM emp WHERE job = 'MANAGER';

Schema
How can I retrieve these rows? information
Possible access paths
Read
Use the
index. 1 each row
and check.

Statistics Which one is faster? 2

80% of employees are managers

Use Full I have a plan!


3
Table Scan

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

• Original query: B*-tree Index

SELECT *
FROM emp
WHERE job = 'CLERK' OR deptno = 10;

• Equivalent transformed query:


SELECT *
FROM emp
WHERE job = 'CLERK'
UNION ALL
SELECT *
FROM emp
WHERE deptno = 10 AND job <> 'CLERK';

3-9
Transformer: Subquery Unnesting Example

• Original query:
SELECT *
FROM accounts
WHERE custno IN
(SELECT custno FROM customers);

• Equivalent transformed query:


SELECT accounts.*
FROM accounts, customers
WHERE accounts.custno = customers.custno;

Primary or unique key

3-10
Transformer: View Merging Example

• Original query: Index

CREATE VIEW emp_10 AS


SELECT empno, ename, job, sal, comm, deptno
FROM emp
WHERE deptno = 10;

SELECT empno FROM emp_10 WHERE empno > 7800;

• Equivalent transformed query:


SELECT empno
FROM emp
WHERE deptno = 10 AND empno > 7800;

3-11
Transformer: Predicate Pushing Example
• Original query: Index

CREATE VIEW two_emp_tables AS


SELECT empno, ename, job, sal, comm, deptno FROM emp1
UNION
SELECT empno, ename, job, sal, comm, deptno FROM emp2;

SELECT ename FROM two_emp_tables WHERE deptno = 20;

• Equivalent transformed query:


SELECT ename
FROM ( SELECT empno, ename, job,sal, comm, deptno
FROM emp1 WHERE deptno = 20
UNION
SELECT empno, ename, job,sal, comm, deptno
FROM emp2 WHERE deptno = 20 );

3-12
Transformer: Transitivity Example

• Original query: Index

SELECT *
FROM emp, dept
WHERE emp.deptno = 20 AND emp.deptno = dept.deptno;

• Equivalent transformed query:


SELECT *
FROM emp, dept
WHERE emp.deptno = 20 AND emp.deptno = dept.deptno
AND dept.deptno = 20;

3-13
Estimator: Selectivity

Number of values satisfying a condition


Selectivity =
Total number of distinct rows

• Selectivity is the estimated proportion of a row set


retrieved by a particular predicate or combination of
predicates.
• It is expressed as a value between 0.0 and 1.0:
– High selectivity: Small proportion of rows
– Low selectivity: Big proportion of rows
• Selectivity computation:
– If no statistics: Use dynamic sampling
– If no histograms: Assume even distribution of rows
• Statistic information:
– DBA_TABLES and DBA_TAB_STATISTICS (NUM_ROWS)
– DBA_TAB_COL_STATISTICS (NUM_DISTINCT, DENSITY,
HIGH/LOW_VALUE,I)
3-14
Selectivity examples

• 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

Cardinality = Selectivity * Total number of rows

• Expected number of rows retrieved by a particular


operation in the execution plan
• Vital figure to determine join, filters, and sort costs
• Simple example:
SELECT salary FROM employees WHERE first_name = 'ANGEL';

– The number of distinct values in FIRST_NAME is 203.


– The number of rows in EMPLOYEES (original cardinality)
is 1018.
– Selectivity = 1/203 = 4.926*e-03
– Cardinality = (1/203)*1018 = 5.01 (rounded off to 6)

3-16
Estimator: Cost

• Cost is the optimizer’s best estimate of the number of


standardized I/Os it takes to execute a particular
statement.
• Cost unit is a standardized single block random read:
– 1 cost unit = 1 SRds
• The cost formula combines three different costs units
into standard cost units.

Single block I/O cost Multiblock I/O cost CPU cost


#SRds*sreadtim + #MRds*mreadtim + #CPUCycles/cpuspeed
Cost=
sreadtim
#SRds: Number of single block reads Sreadtim: Single block read time
#MRds: Number of multiblock reads Mreadtim: Multiblock read time
#CPUCycles: Number of CPU Cycles Cpuspeed: Millions instructions per second

3-17
Plan Generator

select e.last_name, d.department_name


from employees e, departments d where e.dept_id = d.dept_id;

Join order[1]: DEPARTMENTS[D]#0 EMPLOYEES[E]#1


NL Join: Cost: 41.13 Resp: 41.13 Degree: 1
SM cost: 8.01
HA cost: 6.51
Best:: JoinMethod: Hash
Cost: 6.51 Degree: 1 Resp: 6.51 Card: 106.00
Join order[2]: EMPLOYEES[E]#1 DEPARTMENTS[D]#0
NL Join: Cost: 121.24 Resp: 121.24 Degree: 1
SM cost: 8.01
HA cost: 6.51
Join order aborted
Final cost for query block SEL$1 (#0)
All Rows Plan:
Best join order: 1
+----------------------------------------------------------------+
| Id | Operation | Name | Rows | Bytes | Cost |
+----------------------------------------------------------------+
| 0 | SELECT STATEMENT | | | | 7 |
| 1 | HASH JOIN | | 106 | 6042 | 7 |
| 2 | TABLE ACCESS FULL | DEPARTMENTS| 27 | 810 | 3 |
| 3 | TABLE ACCESS FULL | EMPLOYEES | 107 | 2889 | 3 |
+----------------------------------------------------------------+

3-18 3_18.sql
Query Optimizer Statistics in
the Data Dictionary

• The Oracle optimizer requires statistics to


determine the best execution plan.
• Statistics
– Stored in the data dictionary tables
– Must be true representations of data
– Gathered using:
DBMS_STATS package
Dynamic sampling

3-19
Enabling Query Optimizer Features

• The optimizer behavior can be set to prior releases


of the database.
• The OPTIMIZER_FEATURES_ENABLE initialization
parameter can be set to values of different
database releases (such as 8.1.7 or 10.0.0).
• Example:
OPTIMIZER_FEATURES_ENABLE=9.2.0;

3-20
Controlling the Behavior of the Optimizer

• CURSOR_SHARING: SIMILAR, EXACT, FORCE


• DB_FILE_MULTIBLOCK_READ_COUNT
• PGA_AGGREGATE_TARGET
• STAR_TRANSFORMATION_ENABLED
• RESULT_CACHE_MODE: MANUAL, FORCE
• RESULT_CACHE_MAX_SIZE
• RESULT_CACHE_MAX_RESULT
• RESULT_CACHE_REMOTE_EXPIRATION

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

• At the instance level, set the following parameter:


OPTIMIZER_MODE = {FIRST_ROWS(_n)|ALL_ROWS}

• For a session, use the following SQL command:


ALTER SESSION SET optimizer_mode =
{first_rows(_n)|all_rows}

3-23
Optimizing for Fast Response

• OPTIMIZER_MODE is set to FIRST_ROWS or


FIRST_ROWS_n, where n is 1, 10, 100, or 1000.
• This approach is suitable for online users.
• The optimizer generates a plan with the lowest
cost to produce the first row or the first few rows.
• The value of n should be chosen based on the
online user requirement (specifically, how the
result is displayed to the user).
• The optimizer explores different plans and
computes the cost to produce the first n rows for
each plan.

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

The factors considered by the optimizer are:


• Access path
• Join method
• Join order

3-26
Access Paths

• Full-table scans
• Row ID scans
• Index scans
• Cluster scans
• Hash scans

3-27
Join Orders

A join order is the order in which different join items


(such as tables) are accessed and joined together.

3-28
Join Methods

The different join methods considered by the optimizer


are:
• Nested-loop join
• Hash join
• Sort-merge join
• Cartesian join

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

In this lesson, you should have learned about:


• Functions of the optimizer
• Cost factors that are considered by the optimizer
• Setting the optimizer approach

3-31
Optimizer Operations
Review: How the Query Optimizer
Executes Statements

The factors considered by the optimizer are:


• Access path
• Join order
• Join method

4-2
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)
7. Index Scan (Fast Full)
Indexes
8. Index Scan (Skip)
9. Index Scan (Index Join)
10. Using Bitmap Indexes
11. Combining Bitmap Indexes

4-3
Full Table Scan

• Performs multiblock reads


(here DB_FILE_MULTIBLOCK_READ_COUNT = 4) HWM

• Reads all formatted blocks below the high-water mark


• 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-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

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

------------------------------------------------------------------
| 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

• The row ID specifies the data file and data block


containing the row as well as the location of the
row in that block.
• Using the row ID is the fastest way to retrieve a
single row.
• Every index scan does not imply access by row ID.

sample.sql
4-7
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)|
---------------------------------------------------------------------

B B B B B

4-8
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

4-9
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-10
Index Scans

Types of index scans:


• Index unique scan
• Index range scan
• Index range scan descending
• Index skip scan
• Function-based

4-11
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)

unique.sql
4-12
Index Range Scan

Index Range SCAN I_DEPTNO

create index I_DEPTNO on EMP(deptno);

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

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)

desc.sql
4-14
Index Skip Scan

SELECT * FROM employees WHERE age BETWEEN 20 AND 29


Index on (GENDER, AGE)
R
B1 Min M10 B2

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

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)

skip.sql
4-16
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%')

fbi.sql
4-17
Index Scans

Types of index scans:


• Full scan
• Fast-full index scan
• Index join
• Bitmap join

4-18
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)

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

create index I_DEPTNO on EMP(deptno);


select 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)

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);

select 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)

indexjoin.sql
4-21
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-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);

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-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;

ALTER TABLE person ADD CONSTRAINT pk_ssn


Column Null? PRIMARY KEY (ssn);
SSN N SELECT /*+ INDEX(person) */ COUNT(*) FROM
FNAME Y person;
LNAME N
SELECT STATEMENT |
SORT AGGREGATE |
PERSON INDEX FAST FULL SCAN| PK_SSN

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)

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-26
Bitmap Indexes
Table
File 3
Block 10
Index

Block 11

Block 12

<Blue, 10.0.3, 12.8.3, 100010000 010000000 010010100>


<Green, 10.0.3, 12.8.3, 000101000 000000000 100100000>
<Red, 10.0.3, 12.8.3, 010000000 001100000 000001001>
<Yellow, 10.0.3, 12.8.3, 001000000 100000000 001000010>
Key Start End Bitmap
ROWID ROWID

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')

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 RANGE SCAN | IX_B2 | | |
---------------------------------------------------------------------
Predicate: 3 - access("COUNTRY">'FR') filter("COUNTRY">'FR')

4-28
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-29
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')

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.

Optimizer view point

VISIBLE INVISIBLE
Index Index
OPTIMIZER_USE_INVISIBLE_INDEXES=FALSE

Data view point

Update index. Update index.


Update table. Update table.

4-34
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 P;

• Optimizer considers this index:

ALTER INDEX ind1 VISIBLE;

• Create an index as invisible initially:

CREATE INDEX IND1 ON TAB1(COL1) INVISIBLE;

4-35
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-36
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-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

Unclustered ORDERS and Clustered ORDERS


ORDER_ITEMS tables and ORDER_ITEMS
tables

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?

• 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-41
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-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

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%')

buffersort.sql
4-44
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-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
---------------------------------------------------------------------

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-46 mergeview.sql nomergeview.sql


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')

stopkey.sql

4-47
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-48
Joining Multiple Tables

You can join only two row sources at a time. Joins


with more than two tables are executed as follows:
1. Two tables are joined, resulting in a row source.
2. The next table is joined with the row source that
results from step 1.
3. Step 2 is repeated until all tables are joined.
Optimizer determines the folllowing:
1. Order in which to join the tables
2. Best join operation for each join
3. Access path for each row source

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

• A join operation combines the output from two


row sources and returns one resulting row source.
• Join operation types include the following:
– Nested loop join
– Sort-merge join
– Hash join

4-52
Nested Loop Joins

• One of the two tables is defined as the outer table


(or the driving table).
• The other table is called the inner table.
• For each row in the outer table, all matching rows
in the inner table are retrieved.

For each row in the outer table

For each row in the inner table

Check for a match

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

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-55
When Are Nested Loop Joins Used?

Nested loop joins are used when:


• Joining a few rows that have a good driving
condition
• Order of tables is important
• USE_NL(table1 table2)hint is used

nestedloop.sql
nestedloopouter.sql

4-56
Hash Joins

A hash join is executed as follows:


• Both tables are split into as many partitions as
required, using a full table scan.
• For each partition pair, a hash table is built in
memory on the smallest partition.
• The other partition is used to probe the hash table.

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

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 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?

• Hash joins are used if either of the following


conditions is true:
– A large amount of data needs to be joined.
– A large fraction of the table needs to be joined.
• Use the USE_HASH hint.

hashjoin.sql
hashjoinouter.sql

4-59
Sort-Merge Joins

A sort-merge join is executed as follows:


1. The rows from each row source are sorted
on the join predicate columns.
2. The two sorted row sources are then merged
and returned as the resulting row source.

4-60
Sort Merge Join Merged
MJ

• First and second row sources are sorted SJ SJ

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?

Sort-merge joins can be used if either of the following


conditions is true:
• Join condition is not an equijoin (<, >=, P)
• Sorts are required for other operations.

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

An outer join also returns a row SELECT d.deptno,d.dname,e.empno,e.ename


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

4-64
Subqueries and Joins

• Subqueries (like joins) are statements that


reference multiple tables
• Subquery types:
– Noncorrelated subquery
– Correlated subquery
– NOT IN subquery (antijoin)
– EXISTS subquery (semijoin)

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

select ename, sal


from emp e1
where sal > (select avg(sal)
from emp e2
where e1.dept_id = e2.dept_id);
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------
| 0 |SELECT STATEMENT | | 3 | 105 | 7 (15)|
| *1 | HASH JOIN | | 3 | 105 | 7 (15)|
| 2 | VIEW | V_VW1| 4 | 88 | 3 (0)|
| 3 | HASH GROUP BY | | 4 | 182 | 3 (0)|
| 4 | TABLE ACCESS FULL | EMP | 14 | 182 | 3 (0)|
| 5 | TABLE ACCESS FULL | EMP | 14 | 182 | 3 (0)|
--------------------------------------------------------------------
1 - access(“E1"."DEPTNO"=‘ITEM1’)
filter(“SAL”>“AVG(SAL)”)

correlated.sql
4-67
Semijoins

EMP
Semijoins only look for the first match.DEPT 20
10
10
20
10
30
30
40
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")

semijoin.sql
4-68
Antijoins

Reverse of what would have been returned by a join EMP


DEPT
SELECT deptno, dname 20
10
FROM dept 10
20
WHERE deptno not in 20
30
(SELECT deptno FROM emp); 30
40
--------------------------------------- 10
| Id | Operation | Name |
--------------------------------------- SELECT deptno, dname
| 0 | SELECT STATEMENT | | FROM dept
| 1 | NESTED LOOPS ANTI | | WHERE deptno not in
| 2 | TABLE ACCESS FULL| DEPT | (SELECT deptno FROM emp);
| 3 | INDEX RANGE SCAN | I_DEPTNO | -----------------------------------
---------------------------------------
| Id | Operation | Name |
3 - access("DEPTNO"="DEPTNO")
-----------------------------------
| 0 | SELECT STATEMENT | |
| 1 | HASH JOIN ANTI | |
EMP | 2 | TABLE ACCESS FULL| DEPT |
DEPT
| 3 | TABLE ACCESS FULL| EMP |
-----------------------------------

antijoin.sql
4-69
Sort Operations

• SORT UNIQUE
• SORT AGGREGATE
• SORT GROUP BY
• SORT JOIN
• SORT ORDER BY

4-70
Tuning Sort Performance

• Because sorting large sets can be expensive, you


should tune sort parameters.
• Note that DISTINCT, GROUP BY, and most set
operators cause implicit sorts.
• Minimize sorting by one of the following:
– Try to avoid DISTINCT and GROUP BY.
– Use UNION ALL instead of UNION.
– Enable index access to avoid sorting.

4-71
Top-N SQL

SELECT ename, sal


FROM (SELECT ename, sal FROM emp
ORDER BY sal DESC)
WHERE rownum <= 5;

--------------------------------------------------------------------
| 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

EXPLAIN PLAN FOR


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

--------------------------------------------------------------
| 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

In this lesson, you should have learned how to:


• Describe available join operations
• Optimize join performance against different
requirements
• Influence the join order
• Explain why tuning joins is more complicated than
tuning single table statements

4-74
Understanding Execution Plan
What Is an Execution Plan?

• The execution plan of a SQL statement is composed of


small building blocks called row sources for serial
execution plans.
• The combination of row sources for a statement is
called the execution plan.
• By using parent-child relationships, the execution plan
can be displayed in a tree-like structure (text or
graphical).

5-2
Where to Find Execution Plans?

• PLAN_TABLE (EXPLAIN PLAN or SQL*Plus autotrace)


• V$SQL_PLAN (Library Cache)
• V$SQL_PLAN_MONITOR (11g)
• DBA_HIST_SQL_PLAN (AWR)
• STATS$SQL_PLAN (Statspack)
• SQL Management Base (SQL Plan Management
Baselines)
• SQL tuning set
• Trace files generated by DBMS_MONITOR
• Event 10053 trace file
• Process state dump trace file since 10gR2

5-3
Using Execution Plans

• Determining the current execution plan


• Identifying the effect of indexes
• Determining access paths
• Verifying the use of indexes
• Verifying which execution plan may be used

5-4
DBMS_XPLAN Package: Overview

• The DBMS_XPLAN package provides an easy way to


display the output from:
– EXPLAIN PLAN command
– Automatic Workload Repository (AWR)
– V$SQL_PLAN and V$SQL_PLAN_STATISTICS_ALL
fixed views
• The DBMS_XPLAN package supplies three table
functions that can be used to retrieve and display
the execution plan:
– DISPLAY
– DISPLAY_CURSOR
– DISPLAY_AWR

5-5
EXPLAIN PLAN Command

• Generates an optimizer execution plan


• Stores the plan in the PLAN table
• Does not execute the statement itself

5-6
EXPLAIN PLAN Command

EXPLAIN PLAN
SET STATEMENT_ID
= 'text'

INTO your plan table

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.

Note: The EXPLAIN PLAN command does not


actually execute the statement.

explain.sql
5-8
EXPLAIN PLAN Command: Output

SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());

Plan hash value: 2933537672

-------------------------------------------------------------------------------
| 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|
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):


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

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

id= 1 (pid= ) root/parent


id= 2 (pid=1) (pos=1) parent/child
id= 3 (pid=2) (pos=1) child/leaf
id= 4 (pid=2) (pos=2) parent/child
id= 5 (pid=4) (pos=1) child/leaf
id= 6 (pid=4) (pos=2) child/leaf
id= 7 (pid=1) (pos=2) parent/child
id= 8 (pid=7) (pos=1) child/leaf
id= 9 (pid=7) (pos=2) parent/child
id=10 (pid=9) (pos=1) child/leaf

Root/Parent Level 1
Executed first Executed next

From
Parent/Child top/down Parent/Child Level 2

From left/right

Child/Leaf Parent/Child Child/Leaf Parent/Child Level 3

Child/Leaf Child/Leaf Child/Leaf Level 4

5-11
Execution Plan Interpretation: Example 1

SELECT /*+ RULE */ ename,job,sal,dname


FROM emp,dept
WHERE dept.deptno=emp.deptno and not exists(SELECT *
FROM salgrade
WHERE emp.sal between losal and hisal);

--------------------------------------------------
| 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

SQL> select /*+ USE_NL(d) use_nl(m) */ m.last_name as dept_manager


2 , d.department_name
3 , l.street_address
4 from hr.employees m join
5 hr.departments d on (d.manager_id = m.employee_id)
6 natural join
7 hr.locations l
8 where l.city = 'Seattle';

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

• V$SQL_PLAN provides a way of examining the


execution plan for cursors that were recently
executed.
• Information in V$SQL_PLAN is very similar to the
output of an EXPLAIN PLAN statement:
– EXPLAIN PLAN shows a theoretical plan that can be
used if this statement were to be executed.
– V$SQL_PLAN contains the actual plan used.

5-14
V$SQL_PLAN Columns

HASH_VALUE Hash value of the parent statement in the


library cache
ADDRESS Object number of the table or the index

CHILD_NUMBER Child cursor number using this execution plan

POSITION Order of processing for operations that all have


the same PARENT_ID
PARENT_ID ID of the next execution step that operates on
the output of the current step

ID Number assigned to each step in the


execution plan

Note: This is only a partial listing of the columns.

5-15
V$SQL_PLAN

SELECT e.last_name, d.department_name


FROM hr.employees e, hr.departments d
WHERE e.department_id =d.department_id;

SELECT SQL_ID, SQL_TEXT FROM V$SQL


WHERE SQL_TEXT LIKE '%SELECT e.last_name,%' ;

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'));

SQL_ID 47ju6102uvq5q, child number 0


-------------------------------------
SELECT e.last_name, d.department_name
FROM hr.employees e, hr.departments d WHERE
e.department_id =d.department_id

Plan hash value: 2933537672


--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 6 (100|
| 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|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

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

• V$SQL_PLAN_STATISTICS provides actual execution


statistics.
• V$SQL_PLAN_STATISTICS_ALL enables
side-by-side comparisons of the optimizer estimates.

5-18
Automatic Workload Repository

• Collects, processes, and maintains performance


statistics for problem-detection and self-tuning
purposes
• Statistics include:
– Object statistics
– Time-model statistics
– Some system and session statistics
– Active Session History (ASH) statistics
• Automatically generates snapshots of the
performance data

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

select /* example */ * from hr.employees natural


join hr.departments;

select sql_id, sql_text from v$SQL


where sql_text
like '%example%‘;

SQL_ID SQL_TEXT
------- -----------------------------------------------------
F8tc4anpz5cdb select sql_id, sql_text from v$SQL …
454rug2yva18w select /* example */ * from …

awr.sql
5-22
Querying the AWR

SELECT PLAN_TABLE_OUTPUT FROM TABLE


(DBMS_XPLAN.DISPLAY_AWR('454rug2yva18w'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
SQL_ID 454rug2yva18w
--------------------
select /* example */ * from hr.employees natural join hr.departments

Plan hash value: 4179021502

----------------------------------------------------------------------------------
| 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

Specify the Report Type G


Would you like an HTML report, or a plain text report?
Specify the number of days of snapshots to choose from
Specify the Begin and End Snapshot Ids G
Specify the SQL Id G
Enter value for sql_id: 6g1p4s9ra6ag8
Specify the Report Name G

5-24
SQL*Plus AUTOTRACE

OFF
SET AUTOTRACE ON
TRACE[ONLY]

EXPLAIN
STATISTICS

SHOW AUTOTRACE

5-25
SQL*Plus AUTOTRACE: Examples

• To start tracing statements using AUTOTRACE


set autotrace on

• To hide statement output


set autotrace traceonly

• To display execution plans only


set autotrace traceonly explain

• Control the layout with column settings

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;

SQL Monitoring Report


In a different session
SQL Text
--------------------------
select count(*) from sales SQL> select count(*) from sales;

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

SQL Plan Monitoring Details


====================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start |
| | | | (Estim) | | Active(s) | Active |
====================================================================================
| 0 | SELECT STATEMENT | | | 78139 | | |
| 1 | SORT AGGREGATE | | 1 | | | |
| -> 2 | TABLE ACCESS FULL | SALES | 53984K | 78139 | 23 | +1 |
| | | | | | | |
====================================================================================

==================================================================================
Starts | Rows | Activity | Activity Detail | Progress |
| (Actual) | (percent) | (sample #) | |
1 | | | | |
1 | | | | |
1 | 42081K | 100.00 | Cpu (4) | 74% |
==================================================================================

5-30
Summary

In this lesson, you should have learned how to:


• Use EXPLAIN PLAN to view execution plans
• Query V$SQL_PLAN to see the execution plan for
cursors that were recently executed
• Use the Automatic Workload Repository
• Use SQL*Plus AUTOTRACE to run statements
and display execution plans and statistics

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

SELECT c.cust_id, SUM(amount_sold)


FROM sales s, customers c
WHERE s.cust_id = c.cust_id
GROUP BY c.cust_id;

CREATE TABLE cust_sales_sum AS


SELECT c.cust_id, SUM(amount_sold) AS amount
FROM sales s, customers c
WHERE s.cust_id = c.cust_id
GROUP BY c.cust_id;

SELECT * FROM cust_sales_sum;


6-3
Benefits of Using Materialized Views

CREATE MATERIALIZED VIEW cust_sales_mv


ENABLE QUERY REWRITE AS
SELECT c.cust_id, SUM(amount_sold) AS amount
FROM sales s, customers c
WHERE s.cust_id = c.cust_id
GROUP BY c.cust_id;

SELECT c.cust_id, SUM(amount_sold)


FROM sales s, customers c
WHERE s.cust_id = c.cust_id
GROUP BY c.cust_id;

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?

• One materialized view for multiple queries:


– One materialized view can be used to satisfy
multiple queries
– Less disk space is needed
– Less time is needed for maintenance
• Query rewrite chooses the materialized view to
use.
• One materialized view per query:
– Is not recommended because it consumes too
much disk space
– Improves one query's performance

6-5
Creating Materialized Views:
Syntax Options

CREATE MATERIALIZED VIEW mview_name


[TABLESPACE ts_name]
[PARALLEL (DEGREE n)]
[BUILD {IMMEDIATE|DEFERRED}]
[{ REFRESH {FAST|COMPLETE|FORCE}
[{ON COMMIT|ON DEMAND}]
| NEVER REFRESH } ]
[{ENABLE|DISABLE} QUERY REWRITE]

AS SELECT … FROM …
Creating Materialized Views: Example

CREATE MATERIALIZED VIEW cost_per_year_mv


ENABLE QUERY REWRITE
AS
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
GROUP BY t.week_ending_day
, t.calendar_year
, p.prod_subcategory;

Materialized view created.


Types of Materialized Views

• Materialized views with aggregates


CREATE MATERIALIZED VIEW cust_sales_mv AS
SELECT c.cust_id, s.channel_id,
SUM(amount_sold) AS amount
FROM sales s, customers c
WHERE s.cust_id = c.cust_id
GROUP BY c.cust_id, s.channel_id;

• Materialized views containing only joins


CREATE MATERIALIZED VIEW sales_products_mv AS
SELECT s.time_id, p.prod_name
FROM sales s, products p
WHERE s.prod_id = p.prod_id;

6-8
Refresh Methods

• You can specify how you want your materialized


views to be refreshed from the detail tables by
selecting one of four options:
– COMPLETE
– FAST
– FORCE
– NEVER
• You can view the REFRESH_METHOD in the
ALL_MVIEWS data dictionary view.

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

• For ON DEMAND refresh only


• Three procedures with the DBMS_MVIEW package:
– REFRESH
– REFRESH_ALL_MVIEWS
– REFRESH_DEPENDENT

6-11
Materialized Views: Manual Refresh

Specific materialized views:


Exec DBMS_MVIEW.REFRESH('cust_sales_mv');

Materialized views based on one or more tables:


VARIABLE fail NUMBER;
exec DBMS_MVIEW.REFRESH_DEPENDENT(-
:fail,'CUSTOMERS,SALES');

All materialized views due for refresh:


VARIABLE fail NUMBER;
exec DBMS_MVIEW.REFRESH_ALL_MVIEWS(:fail);

6-12
Query Rewrites

• If you want to use a materialized view instead of


the base tables, a query must be rewritten.
• Query rewrites are transparent to applications.
• Query rewrites do not require special privileges on
the materialized view.
• A materialized view can be enabled or disabled for
query rewrites.

6-13
Query Rewrites

• Use EXPLAIN PLAN or AUTOTRACE to verify that


query rewrites occur.
• Check the query response:
– Fewer blocks are accessed.
– Response time should be significantly better.

6-14
Enabling and Controlling
Query Rewrites

• Query rewrites are available with cost-based


optimization only.
QUERY_REWRITE_ENABLED = {true|false|force}
QUERY_REWRITE_INTEGRITY =
{enforced|trusted|stale_tolerated}

• The following optimizer hints influence query


rewrites:
– REWRITE
– NOREWRITE
– REWRITE_OR_ERROR

6-15
Query Rewrite: Example

EXPLAIN PLAN FOR


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
...
Execution Plan
---------------------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost…)
1 0 MAT_VIEW REWRITE ACCESS (FULL) OF 'costs_per_year_mv' (
MAT_VIEW REWRITE) (Cost…)

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

CREATE MATERIALIZED VIEW cust_orders_mv


ENABLE QUERY REWRITE AS
SELECT c.customer_id, SUM(order_total) AS amt
FROM oe.orders s, oe.customers c
WHERE s.customer_id = c.customer_id
GROUP BY c.customer_id;

SELECT /*+ REWRITE_OR_ERROR */ c.customer_id,


SUM(order_total)AS amt
FROM oe.orders s, oe.customers c
WHERE s.customer_id = c.customer_id
GROUP BY c.customer_id;

ORA-30393: a query block in the statement did


not rewrite
6-18
error.sql
SQL Access Advisor

For a given workload, the SQL Access Advisor:


• Recommends creating the appropriate:
– Materialized views
– Materialized view logs
– Indexes
• Provides recommendations to optimize for :
– Fast refresh
– Query rewrite
• Can be run:
– From Oracle Enterprise Manager by using the SQL
Access Advisor Wizard
– By invoking the DBMS_ADVISOR package

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');

SELECT capability_name, possible, related_text,msgtxt


FROM mv_capabilities_table
WHERE statement_id = '123' ORDER BY seq;

CAPABILITY_NAME P RELATED_TE MSGTXT


------------------ - ---------- --------------------
...
REFRESH_COMPLETE Y
REFRESH_FAST N
REWRITE N
PCT_TABLE N SALES no partition key or
PMARKER in select
list
PCT_TABLE N CUSTOMERS relation is not a
partitioned
table
...

6-24
Materialized View Hints

REWRITE Rewrites a query in terms of


materialized views
REWRITE_OR_ERROR Forces an error if a query rewrite is not
possible
NO_REWRITE Disables query rewrite for the query
block
Summary

In this lesson, you should have learned how to:


• Create materialized views
• Enable query rewrites using materialized views

6-26
Optimizer Statistics
Optimizer Statistics

• Describe the database and the objects in the database


• Information used by the query optimizer to estimate:
– Selectivity of predicates
– Cost of each execution plan
– Access method, join order, and join method
– CPU and input/output (I/O) costs
• Refreshing optimizer statistics whenever they are stale is as
important as gathering them:
– Automatically gathered by the system
– Manually gathered by the user with DBMS_STATS

7-2
Types of Optimizer Statistics

• Table statistics: • Column statistics


– Number of rows – Basic: Number of distinct
– Number of blocks values, number of nulls,
– Average row length average length, min, max
– Histograms (data distribution
• Index Statistics:
when the column data is
– B*-tree level skewed)
– Distinct keys – Extended statistics
– Number of leaf blocks
– Clustering factor
• System statistics
– I/O performance and
utilization
– CPU performance and
utilization

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

Must read all blocks to retrieve all As


Block 1 Block 2 Block 3

A B C A B C A B C

Number of rows (9) A B C


Big clustering factor:
Favor alternative paths
DBA_IND_STATISTICS.CLUSTERING_FACTOR
Small clustering factor:
Favor the
A B C index range scan path
Number of blocks (3)

A A A B B B C C C
Block 1 Block 2 Block 3

Only need to read one block to retrieve all As

7-6
Column Statistics (USER_TAB_COL_STATISTICS)

• Count of distinct values of the column (NUM_DISTINCT)


• Low value (LOW_VALUE) Exact
• High value (HIGH_VALUE) Exact
• Number of nulls (NUM_NULLS)
• Selectivity estimate for nonpopular values (DENSITY)
• Number of histogram buckets (NUM_BUCKETS)
• Type of histogram (HISTOGRAM)

colstat.sql

7-7
Histograms

• The optimizer assumes uniform distributions; this may lead


to suboptimal access plans in the case of data skew.
• Histograms:
– Store additional column distribution information
– Give better selectivity estimates in the case of nonuniform
distributions
• With unlimited resources you could store each different
value and the number of rows for that value.
• This becomes unmanageable for a large number of distinct
values and a different approach is used:
– Frequency histogram (#distinct values ≤ #buckets)
– Height-balanced histogram (#buckets < #distinct values)
• They are stored in DBA_TAB_HISTOGRAMS.

7-8
Frequency Histograms

10 buckets, 10 distinct values

Cumulative cardinality
ENDPOINT NUMBER

40000 # rows for column value


30000

20000

10000

0
1 3 5 7 10 16 27 32 39 49

ENDPOINT VALUE: Column value

Distinct values: 1, 3, 5, 7, 10, 16, 27, 32, 39, 49


Number of rows: 40001

7-9
Viewing Frequency Histograms

BEGIN
DBMS_STATS.gather_table_STATS (OWNNAME=>'OE', TABNAME=>'INVENTORIES',
METHOD_OPT => 'FOR COLUMNS SIZE 20 warehouse_id');
END;

SELECT column_name, num_distinct, num_buckets, histogram


FROM USER_TAB_COL_STATISTICS
WHERE table_name = 'INVENTORIES' AND
column_name = 'WAREHOUSE_ID';

COLUMN_NAME NUM_DISTINCT NUM_BUCKETS HISTOGRAM


------------ ------------ ----------- ---------
WAREHOUSE_ID 9 9 FREQUENCY

SELECT endpoint_number, endpoint_value


FROM USER_HISTOGRAMS
WHERE table_name = 'INVENTORIES' and column_name = 'WAREHOUSE_ID'
ORDER BY endpoint_number;

ENDPOINT_NUMBER ENDPOINT_VALUE
--------------- --------------
36 1
213 2
261 3

7 - 10 frequencyhist.sql
Height-Balanced Histograms

5 buckets, 10 distinct values


(8000 rows per bucket)

Popular value
ENDPOINT VALUE

1 7 10 10 32 49
Same number
of rows per bucket

0 1 2 3 4 5

ENDPOINT NUMBER: Bucket number


Distinct values: 1, 3, 5, 7, 10, 16, 27, 32, 39, 49
Number of rows: 40001

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;

SELECT column_name, num_distinct, num_buckets, histogram


FROM USER_TAB_COL_STATISTICS
WHERE table_name = 'INVENTORIES' AND column_name = 'QUANTITY_ON_HAND';

COLUMN_NAME NUM_DISTINCT NUM_BUCKETS HISTOGRAM


------------------------------ ------------ ----------- ---------------
QUANTITY_ON_HAND 237 10 HEIGHT BALANCED

SELECT endpoint_number, endpoint_value


FROM USER_HISTOGRAMS
WHERE table_name = 'INVENTORIES' and column_name = 'QUANTITY_ON_HAND'
ORDER BY endpoint_number;

ENDPOINT_NUMBER ENDPOINT_VALUE
--------------- --------------
0 0
1 27
2 42
3 57

balancedhist.sql
7 - 12
Histogram Considerations

• Histograms are useful when you have a high degree of skew


in the column distribution.
• Histograms are not useful for:
– Columns which do not appear in the WHERE or JOIN clauses
– Columns with uniform distributions
– Equality predicates with unique columns
• The maximum number of buckets is the least (254,# distinct
values).
• Do not use histograms unless they substantially improve
performance.

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

DBA_STAT_EXTENSIONS VEHICLE SYS_STUF3GLKIOP5F4B0BTTCFTMX0W

MAKE MODEL
4

S(MAKE Λ MODEL)=S(MAKE,MODEL)

7 - 14
Expression Statistics: Overview

CREATE INDEX upperidx ON VEHICLE(upper(MODEL))

VEHICLE
MODEL

VEHICLE
MODEL Still possible

Recommended

VEHICLE DBA_STAT_EXTENSIONS
S(upper( MODEL))=0.01 MODEL
SYS_STU3FOQ$BDH0S_14NGXFJ3TQ50

select dbms_stats.create_extended_stats('jfv','vehicle','(upper(model))') from dual;

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

• System statistics enable the CBO to use CPU and I/O


characteristics.
• System statistics must be gathered on a regular basis; this
does not invalidate cached plans.
• Gathering system statistics equals analyzing system activity
for a specified period of time:
• Procedures:
– DBMS_STATS.GATHER_SYSTEM_STATS
– DBMS_STATS.SET_SYSTEM_STATS
– DBMS_STATS.GET_SYSTEM_STATS
• GATHERING_MODE:
– NOWORKLOAD|INTERVAL
– START|STOP

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

• Start manual system statistics collection in the data


dictionary:
SQL> EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS( -
2 gathering_mode => 'START');

• Generate the workload.


• End the collection of system statistics:
SQL> EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS( -
2 gathering_mode => 'STOP');

7 - 18
Mechanisms for Gathering Statistics

• Automatic statistics gathering


– gather_stats_prog automated task
• Manual statistics gathering
– DBMS_STATS package
• Dynamic sampling
• When statistics are missing:
Selectivity:
Equality 1%
Inequality 5%
Other predicates 5%
Table row length 20
# of index leaf blocks 25
# of distinct values 100
Table cardinality 100
Remote table cardinality 2000

7 - 19
When to Gather Statistics Manually

• Rely mostly on automatic statistics collection:


– Change the frequency of automatic statistics collection to
meet your needs.
– Remember that STATISTICS_LEVEL should be set to
TYPICAL or ALL for automatic statistics collection to work
properly.
• Gather statistics manually for:
– Objects that are volatile
– Objects modified in batch operations
– External tables, system statistics, fixed objects
– Objects modified in batch operations: Gather statistics as part
of the batch operation.
– New objects: Gather statistics right after object creation.

7 - 20
Manual Statistics Gathering

You can use Enterprise Manager and the DBMS_STATS


package to:
• Generate and manage statistics for use by the optimizer:
– Gather/Modify
– View/Name
– Export/Import
– Delete/Lock
• Gather statistics on:
– Indexes, tables, columns, partitions
– Object, schema, or database
• Gather statistics either serially or in parallel
• Gather/Set system statistics (currently not possible in EM)

7 - 21
Manual Statistics Collection: Factors

• Monitor objects for DMLs.


• Determine the correct sample sizes.
• Determine the degree of parallelism.
• Determine if histograms should be used.
• Determine the cascading effects on indexes.
• Procedures to use in DBMS_STATS:
– GATHER_INDEX_STATS
– GATHER_TABLE_STATS
– GATHER_SCHEMA_STATS
– GATHER_DICTIONARY_STATS
– GATHER_DATABASE_STATS
– GATHER_SYSTEM_STATS

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

• Dynamic sampling can be done for tables and indexes:


– Without statistics
– Whose statistics cannot be trusted
• Used to determine more accurate statistics when estimating:
– Table cardinality
– Predicate selectivity
• Feature controlled by:
– The OPTIMIZER_DYNAMIC_SAMPLING parameter
– The OPTIMIZER_FEATURES_ENABLE parameter
– The DYNAMIC_SAMPLING hint
– The DYNAMIC_SAMPLING_EST_CDN hint

7 - 24
Optimizer Dynamic Sampling at Work

• Sampling is done at compile time.


• If a query benefits from dynamic sampling:
– A recursive SQL statement is executed to sample data
– The number of blocks sampled depends on the
OPTIMIZER_DYNAMIC_SAMPLING initialization parameter
• During dynamic sampling, predicates are applied to the
sample to determine selectivity.
• Use dynamic sampling when:
– Sampling time is a small fraction of the execution time
– Query is executed many times
– You believe a better plan can be found

7 - 25
OPTIMIZER_DYNAMIC_SAMPLING

• Dynamic session or system parameter


• Can be set to a value from “0” to “10”
• “0” turns off dynamic sampling
• “1” samples all unanalyzed tables, if an unanalyzed table:
– Is joined to another table or appears in a subquery or
nonmergeable view
– Has no indexes
– Has more than 32 blocks
• “2” samples all unanalyzed tables
• The higher the value the more aggressive application of
sampling
• Dynamic sampling is repeatable if no update activity

7 - 26
Locking Statistics

• Prevents automatic gathering


• Is mainly used for volatile tables:
– Lock without statistics implies dynamic sampling.
BEGIN
DBMS_STATS.DELETE_TABLE_STATS('OE','ORDERS');
DBMS_STATS.LOCK_TABLE_STATS('OE','ORDERS');
END;

– Lock with statistics for representative values.


BEGIN
DBMS_STATS.GATHER_TABLE_STATS('OE','ORDERS');
DBMS_STATS.LOCK_TABLE_STATS('OE','ORDERS');
END;

• The FORCE argument overrides statistics locking.


SELECT stattype_locked FROM dba_tab_statistics;

7 - 27
Summary

In this lesson, you should have learned how to:


• Collect optimizer statistics
• Collect system statistics
• Set statistic preferences
• Use dynamic sampling
• Manipulate optimizer statistics

7 - 28
Using Bind Variables
Cursor Sharing and Different Literal Values

SELECT * FROM jobs WHERE min_salary > 12000;


SELECT * FROM jobs WHERE min_salary > 18000;

SELECT * FROM jobs WHERE min_salary > 7500;

Cursor sharing

Library cache

8-2
Cursor Sharing and Bind Variables

12000 SELECT * FROM jobs WHERE min_salary > :min_sal;

18000 SELECT * FROM jobs WHERE min_salary > :min_sal;

17500 SELECT * FROM jobs WHERE min_salary > :min_sal;

Cursor sharing

Library cache

8-3
Bind Variables in SQL*Plus

SQL> variable job_id varchar2(10)


SQL> exec :job_id := 'SA_REP';

PL/SQL procedure successfully completed.

SQL> select count(*) from employees where job_id = :job_id;

COUNT(*)
----------
30

SQL> exec :job_id := 'AD_VP';

PL/SQL procedure successfully completed.

SQL> select count(*) from employees where job_id = :job_id;

COUNT(*)
----------
2

8-4
Bind Variable Peeking

SELECT * FROM jobs WHERE min_salary > :min_sal 12000

First time
you execute
Plan A

min_sal=12000
Next time
you execute

SELECT * FROM jobs WHERE min_salary > :min_sal 18000

8-5
Bind Variable Peeking

SELECT * FROM jobs WHERE min_salary > :min_sal

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

• Oracle8i introduced the possibility of sharing SQL


statements that differ only in literal values.
• Oracle9i extends this feature by limiting it to similar
statements only, instead of forcing it.
• Similar: Regardless of the literal value, same execution plan
SQL> SELECT * FROM employees
2 WHERE employee_id = 153;

• Not similar: Possible different execution plans for different


literal values
SQL> SELECT * FROM employees
2 WHERE department_id = 50;

8-7
The CURSOR_SHARING Parameter

• The CURSOR_SHARING parameter values:


– FORCE
– EXACT (default)
– SIMILAR
• CURSOR_SHARING can be changed using:
– ALTER SYSTEM
– ALTER SESSION
– Initialization parameter files
• The CURSOR_SHARING_EXACT hint

8-8
Forcing Cursor Sharing: Example

SQL> alter session set cursor_sharing = FORCE;

SELECT * FROM jobs WHERE min_salary > 12000;


SELECT * FROM jobs WHERE min_salary > 18000;
SELECT * FROM jobs WHERE min_salary > 7500;

SELECT * FROM jobs WHERE min_salary > :"SYS_B_0"

System-generated
bind variable

8-9
Adaptive Cursor Sharing: Overview

Adaptive cursor sharing:


• Allows for intelligent cursor sharing only for statements that
use bind variables
• Is used to compromise between cursor sharing and
optimization
• Has the following benefits:
– Automatically detects when different executions would benefit
from different execution plans
– Limits the number of generated child cursors to a minimum
– Automated mechanism that cannot be turned off

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

The following views provide information about adaptive cursor


sharing usage:

V$SQL Two new columns show whether a


cursor is bind sensitive or bind aware.

V$SQL_CS_HISTOGRAM Shows the distribution of the execution


count across the execution history
histogram

V$SQL_CS_SELECTIVITY Shows the selectivity cubes stored for


every predicate containing a bind
variable and whose selectivity is used in
the cursor sharing checks

V$SQL_CS_STATISTICS Shows execution statistics of a cursor


using different bind sets

8 - 12
Adaptive Cursor Sharing: Example

SQL> variable job varchar2(6)


SQL> exec :job := 'AD_ASST'
SQL> select count(*), max(salary) from emp where job_id=:job;

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

In this lesson, you should have learned how to:


• List the benefits of using bind variables
• Use bind peeking
• Use adaptive cursor sharing

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'

• HINTS SHOULD ONLY BE USED AS A LAST


OPTION.
• When you use a hint, it is good practice to also add
a comment about that hint.

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

Single-table hints Specified on one table or view


Specify more than one table or
Multitable hints
view
Query block hints Operate on a single query block

Statement hints Apply to the entire SQL statement

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

• Place hints immediately after the first SQL keyword of


a statement block.
• Each statement block can have only one hint
comment, but it can contain multiple hints.
• Hints apply to only the statement block in which they
appear.
• If a statement uses aliases, hints must reference the
aliases rather than the table names.
• The optimizer ignores hints specified incorrectly
without raising errors.

9-6
Hint Recommendations

• Use hints carefully because they imply a high


maintenance load.
• Be aware of the performance impact of hard-coded
hints when they become less valid.

9-7
Optimizer Hint Syntax: Example

UPDATE /*+ INDEX(p PRODUCTS_PROD_CAT_IX)*/


products p
SET p.prod_min_price =
(SELECT
(pr.prod_list_price*.95)
FROM products pr
WHERE p.prod_id = pr.prod_id)
WHERE p.prod_category = 'Men'
AND p.prod_status = 'available, on stock'
/

9-8
Hint Categories

There are hints for:


• Optimization approaches and goals
• Access paths
• Query transformations
• Join orders
• Join operation
• Additional hints

9-9
Optimization Goals and Approaches

ALL_ROWS Chooses cost-based approach with


a goal of best throughput
FIRST_ROWS(n) Instructs Oracle Server to optimize
an individual SQL statement for fast
response

9_10.sql

9-10
Hints for Access Paths

FULL Performs a full table scan


ROWID Accesses a table by ROWID

INDEX Scans an index in ascending order

INDEX_ASC Scans an index in ascending order

INDEX_COMBINE Explicitly chooses a bitmap access


path

9_11.sql

9-11
Hints for Access Paths

INDEX_JOIN Instructs the optimizer to use an index


join as an access path
INDEX_DESC Chooses an index scan for the
specified table
INDEX_FFS Performs a fast-full index scan
NO_INDEX Disallows using a set of indexes
AND_EQUAL Merges single-column indexes

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

NO_QUERY_TRANSFORMATION Skips all query transformation


USE_CONCAT Rewrites OR into UNION ALL and
disables INLIST processing
NO_EXPAND Prevents OR expansions
REWRITE Rewrites query in terms of
materialized views
NO_REWRITE Turns off query rewrite
UNNEST Merges subquery bodies into
surrounding query block
NO_UNNEST Turns off unnesting

9_15.sql
9-15
Hints for Query Transformation

MERGE Merges a view for each query


NO_MERGE Prevents merging of mergeable views
STAR_ Makes the optimizer use the best
TRANSFORMATION plan in which the transformation can
be used
FACT Indicates that the hinted table should
be considered as a fact table
NO_FACT Indicates that the hinted table should
not be considered as a fact table

9_16.sql
9-16
Hints for Join Orders

ORDERED Causes the Oracle Server to join


tables in the order in which they
appear in the FROM clause
LEADING Uses the specified table as the first
table in the join order

9_17.sql

9-17
Hints for Join Operations

USE_NL Joins the specified table


using a nested loop join
NO_USE_NL Does not use nested loops to
perform the join
USE_MERGE Joins the specified table
using a sort-merge join
NO_USE_MERGE Does not perform sort-merge
operations for the join
USE_HASH Joins the specified table
using a hash join
NO_USE_HASH Does not use hash join

9-18 9_18.sql
Additional Hints

APPEND Enables direct-path INSERT


NOAPPEND Enables regular INSERT
ORDERED_PREDICATES Forces the optimizer to preserve
the order of predicate evaluation
CURSOR_SHARING_EXACT Prevents replacing literals with
bind variables
CACHE Overrides the default caching
specification of the table
PUSH_PRED Pushes join predicate into view
PUSH_SUBQ Evaluates nonmerged subqueries
first
DYNAMIC_SAMPLING Controls dynamic sampling to
improve server performance

9-19
Additional Hints

MONITOR Forces real-time query monitoring


NO_MONITOR Disables real-time query
monitoring
RESULT_CACHE Caches the result of the query or
query fragment
NO_RESULT_CACHE Disables result caching for the
query or query fragment
OPT_PARAM Sets initialization parameter for
query duration

9-20
Hints for Suppressing Index Usage

Hint Description
NO_INDEX Disallows use of any indexes

FULL Forces a full table scan


INDEX or Forces the optimizer to use a
INDEX_COMBINE specific index or a set of listed
indexes

9-21
Hints and Views

• Do not use hints in views.


• Use view-optimization techniques:
– Statement transformation
– Results accessed like a table
• Hints can be used on mergeable views and
nonmergeable views.

9-22
Hints for View Processing

MERGE Merges complex views or subqueries


with the surrounding query
NO_MERGE Does not merge mergeable views

9-23
Global and Local Hints

• Extended hint syntax enables the specifying of (global)


hints through views
• References a table name in the hint with a dot notation

CREATE view city_view AS


SELECT *
FROM customers c
WHERE cust_city like 'S%';

SELECT /*+ index(v.c cust_credit_limit_idx) */


v.cust_last_name, v.cust_credit_limit
FROM city_view v
WHERE cust_credit_limit > 5000;

9-24
9_24.sql
Specifying a Query Block in a Hint

explain plan for


select /*+ FULL(@strange dept) */ ename
from emp e, (select /*+ QB_NAME(strange) */ *
from dept where deptno=10) d
where e.deptno = d.deptno and d.loc = 'C';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL, NULL, 'ALL'));

Plan hash value: 615168685


---------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost(%CPU)|
---------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 41 | 7 (15)|
|* 1 | HASH JOIN | | 1 | 41 | 7 (15)|
|* 2 | TABLE ACCESS FULL| DEPT | 1 | 21 | 3 (0)|
|* 3 | TABLE ACCESS FULL| EMP | 3 | 60 | 3 (0)|
---------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$DB579D14
2 - SEL$DB579D14 / DEPT@STRANGE
3 - SEL$DB579D14 / E@SEL$1

9-25
Specifying a Full Set of Hints

SELECT /*+ LEADING(e2 e1) USE_NL(e1) INDEX(e1


emp_emp_id_pk) USE_MERGE(j) FULL(j) */
e1.first_name, e1.last_name, j.job_id,
sum(e2.salary) total_sal
FROM hr.employees e1, hr.employees e2,
hr.job_history j
WHERE e1.employee_id = e2.manager_id
AND e1.employee_id = j.employee_id
AND e1.hire_date = j.start_date
GROUP BY e1.first_name, e1.last_name, j.job_id
ORDER BY total_sal;

9-26
Summary

In this lesson, you should have learned how to:


• Set the optimizer mode
• Use optimizer hint syntax
• Determine access-path hints
• Analyze hints and their impact on views

9-27
Application Tracing
End-to-End Application Tracing Challenge

Client Client Client Clients


Client OE Client OE Client C4 Client JF/Session 6

CRM ERP CRM CRM ERP CRM

Dedicated Dedicated Dedicated Shared Shared Shared


server server server server server server

Trace Trace Trace Trace Trace Trace


file file file file file file

• I want to retrieve traces from CRM service.


• I want to retrieve traces from client C4.
• I want to retrieve traces from session 6.

10 - 2
End-to-End Application Tracing

• Simplifies the process of diagnosing performance problems


in multitier environments by allowing application workloads
to be seen by:
– Service
– Module
– Action
– Session
– Client
• End-to-End Application Tracing tools:
– Enterprise Manager
– DBMS_APPICATION_INFO, DBMS_SERVICE,
DBMS_MONITOR, DBMS_SESSION
– SQL Trace and TRCSESS utility
– tkprof

10 - 3
Location for Diagnostic Traces
DIAGNOSTIC_DEST

Diagnostic Data Previous Location ADR Location


Foreground process USER_DUMP_DEST $ADR_HOME/trace
traces

Background process BACKGROUND_DUMP_DEST $ADR_HOME/trace


traces

Alert log data BACKGROUND_DUMP_DEST $ADR_HOME/alert&trace

Core dumps CORE_DUMP_DEST $ADR_HOME/cdump

Incident dumps USER|BACKGROUND_DUMP_DES $ADR_HOME/incident/incdir_n


T

V$DIAG_INFO
ADR trace = Oracle Database 10g trace – critical error trace

10 - 4
What Is a Service?

• Is a means of grouping sessions that perform the same kind


of work
• Provides a single-system image instead of a multiple-
instances image
• Is a part of the regular administration tasks that provide
dynamic service-to-instance allocation
• Is the base for High Availability of connections
• Provides a performance-tuning dimension
• Is a handle for capturing trace information

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

• Applications using services can be further qualified by:


– MODULE
– ACTION
– CLIENT_IDENTIFIER
• Set using the following PL/SQL packages:
– DBMS_APPLICATION_INFO
– DBMS_SESSION
• Tracing can be done at all levels:
– CLIENT_IDENTIFIER
– SESSION_ID
– SERVICE_NAMES
– MODULE
– ACTION
– Combination of SERVICE_NAME, MODULE, ACTION

10 - 7
Use Enterprise Manager to Trace Services

10 - 8
Service Tracing: Example

• Trace on service, module, and action:


exec DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE('AP');

exec DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE(-
'AP', 'PAYMENTS', 'QUERY_DELINQUENT');

• Trace a particular client identifier:


exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE
(client_id=>'C4', waits => TRUE, binds => FALSE);

10 - 9
Session Level Tracing: Example

• For all sessions in the database:


EXEC dbms_monitor.DATABASE_TRACE_ENABLE(TRUE,TRUE);

EXEC dbms_monitor.DATABASE_TRACE_DISABLE();

• For a particular session:


EXEC dbms_monitor.SESSION_TRACE_ENABLE(session_id=>
27, serial_num=>60, waits=>TRUE, binds=>FALSE);

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();

• Easily identifying your trace files:


alter session set
tracefile_identifier='mytraceid';

10 - 11
The trcsess Utility
Client Client Client Clients

CRM ERP CRM CRM ERP CRM

Dedicated Dedicated Dedicated Shared Shared Shared


server server server server server server

Trace Trace Trace Trace Trace Trace


file file file file file file

TRCSESS TRCSESS

Trace file Trace file


for CRM service tkprof for one client

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>]

Trace Trace Trace


file file file

TRCSESS

Consolidated
trace file

10 - 13
The trcsess Utility: Example

exec dbms_session.set_identifier('HR session');


First session Second session

exec dbms_session.set_identifier('HR session');

exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE( -
client_id=>'HR session', waits => FALSE, binds => FALSE);
Third session

select * from employees;


/
select * from departments;
/

exec DBMS_MONITOR.CLIENT_ID_TRACE_DISABLE( -
client_id => 'HR session');

trcsess output=mytrace.trc clientid='HR session'


$ORACLE_BASE/diag/rdbms/orcl/orcl/trace/*.trc

10 - 14
SQL Trace File Contents

• Parse, execute, and fetch counts


• CPU and elapsed times
• Physical reads and logical reads
• Number of rows processed
• Misses on the library cache
• Username under which each parse occurred
• Each commit and rollback
• Wait event and bind data for each SQL statement
• Row operations showing the actual execution plan of each
SQL statement
• Number of consistent reads, physical reads, physical writes,
and time elapsed for each operation on a row

10 - 15
SQL Trace File Contents: Example

*** [ Unix process pid: 19687 ]


*** 2008-02-25 15:49:19.820
*** 2008-02-25 15:49:19.820
*** 2008-02-25 15:49:19.820
*** 2008-02-25 15:49:19.820

====================
PARSING IN CURSOR #4 len=23 dep=0 uid=82 oct=3 lid=82 tim=1203929332521849
hv=4069246757 ad='34b6f730' sqlid='f34thrbt8rjt5'
select * from employees
END OF STMT
PARSE #4:c=49993,e=67123,p=28,cr=403,cu=0,mis=1,r=0,dep=0,og=1,tim=1203929332521845
EXEC #4:c=0,e=16,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1203929332521911
FETCH #4:c=1000,e=581,p=6,cr=6,cu=0,mis=0,r=1,dep=0,og=1,tim=1203929332522553
FETCH #4:c=0,e=45,p=0,cr=1,cu=0,mis=0,r=15,dep=0,og=1,tim=1203929332522936

FETCH #4:c=0,e=49,p=0,cr=1,cu=0,mis=0,r=1,dep=0,og=1,tim=1203929333649241
STAT #4 id=1 cnt=107 pid=0 pos=1 obj=70272 op='TABLE ACCESS FULL EMPLOYEES (cr=15
pr=6 pw=6 time=0 us cost=3 size=7276 card=107)'
*** [ Unix process pid: 19687 ]
*** 2008-02-25 15:49:19.820
*** 2008-02-25 15:49:19.820
*** 2008-02-25 15:49:19.820
*** 2008-02-25 15:49:19.820

10 - 16
Formatting SQL Trace Files: Overview

Use the tkprof utility to format your SQL trace files:


• Sort raw trace file to exhibit top SQL statements
• Filter dictionary statements
Trace
Trace
file
Trace Trace Trace Trace Trace
fileTrace
file file file file file
Trace
file
file
TRCSESS

Consolidated Concatenated
trace file tkprof trace file

Report
file

10 - 17
Invoking the tkprof Utility

tkprof inputfile outputfile [waits=yes|no]


[sort=option]
[print=n]
[aggregate=yes|no]
[insert=sqlscritfile]
[sys=yes|no]
[table=schema.table]
[explain=user/password]
[record=statementfile]
[width=n]

mytrace.sql

10 - 18
tkprof Sorting Options

Sort Option Description


prscnt Number of times parse was called
prscpu CPU time parsing
prsela Elapsed time parsing
prsdsk Number of disk reads during parse
prsqry Number of buffers for consistent read during parse
prscu Number of buffers for current read during parse
prsmis Number of misses in the library cache during parse
execnt Number of executes that were called
execpu CPU time spent executing
exeela Elapsed time executing
exedsk Number of disk reads during execute
exeqry Number of buffers for consistent read during execute
execu Number of buffers for current read during execute

10 - 19
tkprof Sorting Options

Sort Option Description


exerow Number of rows processed during execute
exemis Number of library cache misses during execute
fchcnt Number of times fetch was called
fchcpu CPU time spent fetching
fchela Elapsed time fetching
fchdsk Number of disk reads during fetch
fchqry Number of buffers for consistent read during fetch
fchcu Number of buffers for current read during fetch
fchrow Number of rows fetched
userid User ID of user that parsed the cursor

10 - 20
Output of the tkprof Command

• Text of the SQL statement


• Trace statistics (for statement and recursive calls) separated
into three SQL processing steps:

PARSE Translates the SQL statement into an execution plan

EXECUTE Executes the statement


(This step modifies the data for the INSERT, UPDATE,
and DELETE statements.)
FETCH Retrieves the rows returned by a query
(Fetches are performed only for the SELECT
statements.)

10 - 21
Output of the tkprof Command

There are seven categories of trace statistics:

Count Number of times the procedure was executed


CPU Number of seconds to process
Elapsed Total number of seconds to execute

Disk Number of physical blocks read

Query Number of logical buffers read for consistent read

Current Number of logical buffers read in current mode

Rows Number of rows processed by the fetch or execute

10 - 22
Output of the tkprof Command

The tkprof output also includes the following:


• Recursive SQL statements
• Library cache misses
• Parsing user ID
• Execution plan
• Optimizer mode or hint
• Row source operation
...
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 61

Rows Row Source Operation


------- ---------------------------------------------------
24 TABLE ACCESS BY INDEX ROWID EMPLOYEES (cr=9 pr=0 pw=0 time=129 us)
24 INDEX RANGE SCAN SAL_IDX (cr=3 pr=0 pw=0 time=1554 us)(object id …

10 - 23
tkprof Output with No Index: Example

...
select max(cust_credit_limit)
from customers
where cust_city ='Paris'

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- -------
Parse 1 0.02 0.02 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.10 0.09 1408 1459 0 1
------- ------ -------- ---------- ---------- ---------- ---------- -------
total 4 0.12 0.11 1408 1459 0 1

Misses in library cache during parse: 1


Optimizer mode: ALL_ROWS
Parsing user id: 61

Rows Row Source Operation


------- ---------------------------------------------------
1 SORT AGGREGATE (cr=1459 pr=1408 pw=0 time=93463 us)
77 TABLE ACCESS FULL CUSTOMERS (cr=1459 pr=1408 pw=0 time=31483 us)

10 - 24
tkprof Output with Index: Example

...
select max(cust_credit_limit) from customers
where cust_city ='Paris'

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ---------
Parse 1 0.01 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 77 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ---------
total 4 0.01 0.00 0 77 0 1

Misses in library cache during parse: 1


Optimizer mode: ALL_ROWS
Parsing user id: 61

Rows Row Source Operation


------- ---------------------------------------------------
1 SORT AGGREGATE (cr=77 pr=0 pw=0 time=732 us)
77 TABLE ACCESS BY INDEX ROWID CUSTOMERS (cr=77 pr=0 pw=0 time=1760 us)
77 INDEX RANGE SCAN CUST_CUST_CITY_IDX (cr=2 pr=0 pw=0 time=100
us)(object id 55097)

10 - 25
Summary

In this lesson, you should have learned how to:


• Configure the SQL Trace facility to collect session statistics
• Use the TRCSESS utility to consolidate SQL trace files
• Format trace files using the tkprof utility
• Interpret the output of the tkprof command

10 - 26

You might also like