Oracle Performance Optimization Using the Wait Interface – 7, 8i, 9i and Beyond Thursday, April 8th 2004 Gaja Krishna Vaidyanatha Independent Consultant [email protected].

Download Report

Transcript Oracle Performance Optimization Using the Wait Interface – 7, 8i, 9i and Beyond Thursday, April 8th 2004 Gaja Krishna Vaidyanatha Independent Consultant [email protected].

Oracle Performance
Optimization Using the Wait
Interface – 7, 8i, 9i and Beyond
Thursday, April 8th 2004
Gaja Krishna Vaidyanatha
Independent Consultant
[email protected]
Upcoming Book – Unprecedented
Stuff
Oracle Insights : Tales of the
Oaktable
A 12-author Book Project












Dave Ensor
Tim Gorman
Kyle Hailey
Anjo Kolk
Tom Kyte
Jonathan Lewis
Connor McDonald
Cary Millsap
James Morle
Mogens Norgaard
David Ruthven
Gaja Krishna Vaidyanatha
Published by Apress
(http://www.apress.com)
2
Confession#1
I am not an expert…not by
any stretch of the imagination.
Confession#2
I am an engineer not a
scientist.
Confession#3
Advanced Tuning, Turbo-charged
Tuning, Push-Me-For-MorePower Tuning…Lies…Just Plain
Lies…
Or is it called Marketing these
days!!!
Confession#4
There is only one way to
optimize Oracle performance
– The Right Way...Using the
Wait Interface
‘It’s almost ‘duh!’…what is
common sense is not
common practice’
- Steven Covey
Plan of Action
What is Performance Optimization?
What is the Oracle Wait Interface (OWI)?
The Method Behind the Madness
The Guts of OWI
Diagnosing an Oracle performance problem – A Demo
Application Performance Optimization – A DBA’s
Perspective
Oracle Instance/Database Configuration & Optimization
Conclusion
8
What is Performance
Optimization?
Systematic and deliberate effort to achieve a system runtime
goal, by eliminating one or more bottlenecks
The “goal” needs to be clearly defined

Query X runs in 40 minutes and needs to run in less than 4 minutes.
Requires a simple diagnostic method that is repeatable

No expert methods please, we have enough of those
Remember – Keep one thing in clear focus


Reducing logical I/O is the ultimate goal in any performance
tuning engagement
This has a huge positive impact on response time
9
What is Performance
Optimization?
Requires capability to perform in-depth analysis of
the diagnostic data
Facilitate the path to resolving the underlying
problem
There is only one way to optimize Oracle
performance


The RIGHT Way!!!
Everything else is just marketing gimmicks
Advanced Tuning
Turbo Tuning…push me for more power!!!
10
What is the Oracle Wait Interface
(OWI)?
Instrumentation within the Oracle Kernel that provides
execution/wait times for various code paths




Timestamp – t1
Code X
Timestamp – t2
Time spent = t2 – t1
Was introduced in 7.0.12
Helps us find “where is the time spent?”

Resource hogs are usually the bottlenecks
Externalized via a set of V$ views


V$System_Event, V$Session_Event, V$Session_Wait
Trace files generated via event# 10046
The only source of real performance diagnostic data

V$Sysstat, V$Sessstat and such are supplementary data sources
11
The Method Behind the
Madness
The Method Behind the Madness –
Allow me to blow some steam off!!!
Almost every cache-hit ratio out there is
unintelligent

Just flat boring numbers
The most relevant ratio


(Executions below response time goal/Executions
above response time goal) * 100
Check out Jonathan Lewis’s Fan Hit Ratio
Survivor Story
13
The Method Behind the Madness –
The Mantra
Response Time = Service Time + Wait Time
Throughput = Service Time + Wait Time
Service Time = fn (Hardware specs, Laws of Physics)
Wait Time = fn (Wasteful Processing, Resource
Contention, Substance Smoked Before Application
Coding) -- ;-)
You can never eliminate waits

Why would you care for some waits if the application is within
the response time goal?
14
The Method Behind the Madness
1.
2.
3.
Set Tuning Goals
Benchmark current performance (if feasible)
Identify the performance bottleneck
I.
II.
III.
IV.
4.
5.
Gather Oracle Diagnostic Data using OWI – Prong I
Gather OS Diagnostic Data – Prong II
Correlate both data sources
Analyze tkprof trace data (9i and up includes wait data)
Make one change at a time
Rinse and repeat until tuning goal is achieved
This is version-independent and will work from version
7.0.12 and up
15
The Method Behind the Madness –
Set Tuning Goals
Why are you tuning?
How does the business benefit from your effort?

If SQL X runs in 0.3 seconds instead of 0.5, we will close
40% more orders each day
Can you please define what “fast” means?
Example - This SQL statement runs in 45 seconds
and needs to complete within 7 seconds.
Do you suffer from CTD?
16
The Method Behind the Madness
1.
2.
3.
Set Tuning Goals
Benchmark current performance (if feasible)
Identify the performance bottleneck
I.
II.
III.
IV.
4.
5.
Gather Oracle Diagnostic Data using OWI – Prong I
Gather OS Diagnostic Data – Prong II
Correlate both data sources
Analyze tkprof trace data (9i and up includes wait data)
Make one change at a time
Rinse and repeat until tuning goal is achieved
This is version-independent and will work from version
7.0.12 and up
17
The Method Behind the Madness –
Benchmark Current Performance
Timing of tracing/data collection depends on the time duration
of the problem
Record response time before and after a specific change
Check whether TIMED_STATISTICS=TRUE
•
•
•
15% alleged overhead is a myth
Does not show up in trace timing data
Set to FALSE if and only if there is a platform-specific bug
STATISTICS_LEVEL=TYPICAL



Introduced in 9iR2
Valid values are BASIC, TYPICAL, ALL
Control Switch for Performance Data Collection
18
The Method Behind the Madness –
Benchmark Current Performance
For a system-wide Problem
•
Create a snapshot using STATSPACK
•
•
or
Use top, identify the PID and then proceed
STATSPACK requires deleting one or more events from
STATS$IDLE_EVENT
SQL*Net message to client
Analyze reports online on http://www.oraperf.com
For a localized Problem
•
•
Run the SQL statement
May not be possible or feasible to always do this
Effective problem diagnosis “after the fact” can be done only
with long-term historical collections
19
The Method Behind the Madness
1.
2.
3.
Set Tuning Goals
Benchmark current performance (if feasible)
Identify the performance bottleneck
I.
II.
III.
IV.
4.
5.
Gather Oracle Diagnostic Data using OWI – Prong I
Gather OS Diagnostic Data – Prong II
Correlate both data sources
Analyze tkprof trace data (9i and up includes wait data)
Make one change at a time
Rinse and repeat until tuning goal is achieved
This is version-independent and will work from version
7.0.12 and up
20
The Method Behind the Madness –
Identify the performance bottleneck
Gather required diagnostic data (Prong I)

V$System_Event
Conglomerate of all events since instance startup

V$Session_Event
Historical event data for all currently connected sessions

V$Session_Wait
Waits of currently active sessions
1 row/active session
Data here is merged into V$Session in Oracle 10g
21
The Method Behind the Madness –
Identify the performance bottleneck
Gather required diagnostic data (Prong I)

Determine the PID from top (Similar effort on
Windows)
Helps identify top CPU consumers

Sample scenarios – Determining “location of the
pain”
One process is hogging the CPU
 * Pain caused by one PID
22
The Method Behind the Madness –
Identify the performance bottleneck
Gather required diagnostic data (Prong I)

Sample scenarios – Determining “location of the
pain”
Multiple processes are hogging the CPUs
 * Pain caused by multiple PIDs…Pick one PID at a time
Multiple processes are evenly utilizing the CPU, but not
hogging it
 * Pain caused by multiple PIDs…Pick one PID
 * This usually is an system-wide I/O problem
23
The Method Behind the Madness –
Identify the performance bottleneck
Gather required diagnostic data (Prong I) – Data Correlation



Determine the PID from top
Helps identify top CPU consumers
Determine SPID of the server process to be traced
Map the PID to the Oracle Server Process (join v$process,
v$session)
select S.Username, P.Spid, S.Sid, S.Serial#
from V_$SESSION S, V_$PROCESS P
where S.PADDR = P.ADDR
and S.Username = upper('&&oracle_user_name')

Trace the session
alter session set event….. – Prior to Oracle8i
dbms_system.set_ev(…) – Oracle 8i and up
dbms_monitor.* - Oracle 10g and up
24
The Method Behind the Madness –
Why is the OS Prong required?
CPU or memory bottlenecks are not revealed
within OWI
Some memory bottlenecks can cause subcentisecond waits within Oracle

Paging and Latch Free
System-level I/O Bottlenecks
Helps identify bottlenecks external to Oracle
25
The Method Behind the Madness –
Prong II : CPU Bottlenecks
CPU Utilization

sar –u 5 10000
%usr, %sys, %wio, %idle
%wio and %sys typically should be < 10-15%
0% idle is OK, so long as %wio and %sys is not
high
Comparable commands in Windows
CPU Run Queues

Run queue is the only deterministic CPU bottleneck metric
Average run queue <= (2 * (# of CPUs)

vmstat 5 10000 – Reveals system run queue
The column – “r” in the vmstat output is the CPU run queue

top – Runnable provides the CPU run queue
26
The Method Behind the Madness –
Prong II : Memory Bottlenecks
Memory Utilization


vmstat –S 5 10000
sr (scanrate) should be in and around 0
Bug in Solaris 2.6/2.7


swapins and swapouts should be 0
Level of paging should also be at a minimum
(In this day and age, paging should be nonexistent)
Oversized SGAs (to attain high cache-hit ratios) are potential
culprits for paging and swapping
Check for high I/O activity on swapfile devices
27
The Method Behind the Madness –
Prong II : I/O Bottlenecks
I/O Utilization

sar –d 5 10000
Response times of > 20ms on devices indicates
I/O bottlenecks
Response Time = Service Time (AvServ) + Wait Time (AvWait)
Queuing is an indication of high response time and high wait
times
High disk queue numbers + high response times
 I/O contention
I/O requests should be evenly balanced across all
devices

Fewer the devices, better the overall utilization
28
The Method Behind the Madness
1.
2.
3.
Set Tuning Goals
Benchmark current performance (if feasible)
Identify the performance bottleneck(s)
I.
II.
III.
IV.
4.
5.
Gather Oracle Diagnostic Data using OWI – Prong I
Gather OS Diagnostic Data – Prong II
Correlate both data sources
Analyze tkprof trace data (9i and up includes wait data)
Make one change at a time
Rinse and repeat until tuning goal is achieved
This is version-independent and will work from version
7.0.12 and up
29
The Method Behind the Madness –
Making one change at a time
Change should be driven by diagnostic data
Do not make arbitrary changes

Example : Mass changes to init.ora
Remember Newton’s Third Law of Motion

For every action there is an equal and opposite reaction
One of the oldest Texas quotes

If it ain’t broke, don’t fix it!
30
The Method Behind the Madness
1.
2.
3.
Set Tuning Goals
Benchmark current performance (if feasible)
Identify the performance bottleneck(s)
I.
II.
III.
IV.
4.
5.
Gather Oracle Diagnostic Data using OWI – Prong I
Gather OS Diagnostic Data – Prong II
Correlate both data sources
Analyze tkprof trace data (9i and up includes wait data)
Make one change at a time
Rinse and repeat until tuning goal is achieved
This is version-independent and will work from version
7.0.12 and up
31
The Method Behind the Madness Summary
Set tuning goals
Benchmark
Identify bottlenecks
Make one change at a time
Rinse and repeat until
tuning goal is achieved
Two-pronged approach
OWI Diagnostics – Prong I
(V$System_Event,V$Session_Event,
V$Session_Wait)
Perform necessary drilldowns from
OWI to (V$SQL, V$Latch,
V$Session)
OS Diagnostic Data – Prong II
Required for additional
information only if Prong I does
not reveal the problem
32
The Guts of OWI
(Credits : Jonathan Lewis
for some of the trace
events)
OWI
V$System_Event – Wait data since last instance startup
V$Session_Event – Wait data for connected sessions
V$Session_Wait/v$Session – Wait data for current sessions
waiting
For a dynamic problem - Tracing sessions using the 10046
event
Additional sample drilldown views



V$Session (In 10g, we have session-wait information here)
V$Sql
V$Latch
34
V$System_Event
•
Columns
Event
Total_Waits
Total_Timeouts
Time_Waited – in centiseconds
Avg_Wait – in centiseconds
Time_Waited_Micro – in microseconds
35
V$Session_Event
•
•
•
Same as V$System_Event
This is each session’s wait history
Additional Columns
– Sid – Session identifier
– Max_Wait – In centiseconds
•
•
Volatile data, data is lost as sessions log on and
off
Broken in 9iR2 on some platforms
– SID in this view does not match SID in v$session
– It is “one off” – one less than v$session
36
V$Session_Wait – The Hound
Dog
Complex view to understand
Wait statistics are reported as they happen
Reveals the vicinity of the bottleneck…;-)
Columns you should care about
–
Sid – Session Identifier
–
Seq# – Occurrence count for a wait
–
Event – Name of the event
–
P1TEXT..P3TEXT – Description of P1..P3
–
P1..P3 – Location of the bottleneck
–
State – Session state
–
Wait_time – Completed wait (in seconds)
–
Seconds_In_Wait – Wait in Progress (in seconds)
37
V$Session_Wait (P1..P3)
p1 - p3
– Provides location of the wait events
– Example : For “db file sequential read”
p1 is the file#
p2 is the block#
p3 is the number of blocks in the I/O call
–
Example: For “latch free”
p2 is the latch#
Look up the latch with latch# in v$latch
38
V$Session_Wait (State)
WAITING
–
Currently waiting for the event.
WAITED UNKNOWN TIME
–
Timed_Statistics is not set to TRUE, i.e., is set to FALSE.
WAITED SHORT TIME
–
Waited for less than 1 centisecond.
WAITED KNOWN TIME
–
If the resource that is waited upon is gained at a later
time, the state changes from Waiting to Waited Known
Time.
39
V$Session_Wait (Wait_Time)
The value for this column is STATE dependent.
If state = (WAITING or WAITED UNKNOWN TIME or
WAITED SHORT TIME)
then
Wait_Time = Irrelevant;
End If;
If state = (WAITED KNOWN TIME)
then
Wait_Time = Actual wait time, in seconds;
End If;
40
V$Session_Wait (Seconds_In_Wait)
• The value for this column is STATE dependent.
• If STATE = (WAITED UNKNOWN TIME or WAITED
SHORT TIME or WAITED KNOWN TIME) then
Seconds_In_Wait = Irrelevant;
• End If;
• If STATE = (WAITING) then
Seconds_In_Wait = Actual Wait Time In Seconds;
• End If;
41
V$Session_Wait (Seconds_In_Wait)
• If Wait_Time = 0 then
Seconds_In_Wait = Current Wait
Elsif Wait_Time > 0 then
Seconds_In_Wait = Seconds since start of previous wait
End if;
• (Seconds_In_Wait – Wait_Time)/100
- Active # of seconds since end of last wait
• Check Bug Nos. – 2803772, 2843192, 2873528
- Seconds_In_Wait resets on every seq# increment
- Non-zero Wait_Time shows up as “Null Event”.
42
Types of Wait Events
Non-Idle versus Idle
Foreground versus Background
There are obvious exceptions in both categories
Non-Idle is usually foreground related
•
•
•
•
db file sequential read
db file scattered read
SQL*Net message to client
SQL*Net more data to client
Idle is usually background related
•
•
•
pmon timer
smon timer
SQL*Net message from client – Exception, this is for a foreground
43
Event# 10046
Flexible SQL_TRACE
Levels
– 0 = Off = Setting SQL_TRACE = FALSE
– 1 = Statistics = Setting SQL_TRACE = TRUE
–
–
–
4 = Statistics + Bind Variable Values
8 = Statistics + Wait Events
12 = Statistics + Wait Events + Bind Variable Values
BEWARE - At level 8 and above, large amounts of
trace information will be generated
44
Enabling 10046 – dbms_system.* - 8i
PROCEDURE SET_BOOL_PARAM_IN_SESSION
Argument Name
Type
In/Out Default?
------------------------------ ----------------------- ------ -------SID
NUMBER
IN
SERIAL#
NUMBER
IN
PARNAM
VARCHAR2
IN
BVAL
BOOLEAN
IN
PROCEDURE SET_INT_PARAM_IN_SESSION
Argument Name
Type
In/Out Default?
------------------------------ ----------------------- ------ -------SID
NUMBER
IN
SERIAL#
NUMBER
IN
PARNAM
VARCHAR2
IN
INTVAL
BINARY_INTEGER
IN
PROCEDURE SET_EV
Argument Name
Type
In/Out Default?
------------------------------ ----------------------- ------ -------SI
BINARY_INTEGER
IN
SE
BINARY_INTEGER
IN
EV
BINARY_INTEGER
IN
LE
BINARY_INTEGER
IN
NM
VARCHAR2
IN
45
Enabling 10046 – The Recipe
1. Identify the session’s process ID (SPID)
- select S.Username, P.Spid, S.Sid, S.Serial#
from V$SESSION S, V$PROCESS P
where S.PADDR = P.ADDR and S.Username = ‘XXX’;
2. Set timed_statistics to true (if not already set)
exec dbms_system.set_bool_param_in_session(sid, serial#,
'TIMED_STATISTICS', TRUE);
3. Prevent trace file truncation due to default setting of
MAX_DUMP_FILE_SIZE
exec dbms_system.set_int_param_in_session(sid, serial#,
'MAX_DUMP_FILE_SIZE', 2147483647);
4. Turn on trace
exec dbms_system.set_ev(sid, serial#, 10046, 8, '')
5. Run the application
6. Turn off trace
exec dbms_system.set_ev(sid, serial#, 10046, 0, '')
7. Locate trace file in USER_DUMP_DEST using SPID from #1
8. Run TKPROF on trace file
46
Some Useful Diagnostic Events & a
not-so-well-know package
10046 – SQL Tracing and Wait Data Collection
10053 – Optimizer tracing
10032, 10033 – Sort tracing
10128 – Partition tracing
10391 – Parallel Query tracing
10060 – Query Transformations tracing (Query
unnesting/View Merging)
7. 10730 – SQL Statement tracing (Row-level security)
1.
2.
3.
4.
5.
6.
DBMS_OLAP – For diagnosing queries to Materialized Views and Query rewrites
47
Reading the output of TKPROF
call count
Parse
1
Execute 1
Fetch 27
cpu
0.02
0.01
0.24
elapsed
0.02
0.01
0.36
disk
0
0
1230
query
0
0
2342
current
0
0
0
rows
0
0
399
Totals
0.27
0.39
1230
2342
0
399
29
Elapsed = CPU + (Wait for I/O or Context Switch)
Disk = Physical I/O
Query + Current = Logical I/O
48
Getting Oracle’s Plan of Action
Query - SELECT a.id,a.name,b.name
FROM author a, book b
WHERE a.author_id = b.book_author_id
AND a.author_id = 101
ORDER BY b.name;
Reading the Execution Plan



Query Plan
-------------------------------------------------------------------------------1.0 SELECT STATEMENT Statement1 Cost = 148
2.1 SORT ORDER BY (7th)




3.1 FILTER (6th)
4.1 NESTED LOOPS (5th)
5.1 TABLE ACCESS BY ROWID AUTHOR (2nd)
6.1 INDEX UNIQUE SCAN AUTHOR_ID UNIQUE (1st)
5.2 TABLE ACCESS BY ROWID BOOK (4th)
6.2 INDEX RANGE SCAN BOOK_AUTH_ID NON-UNIQUE (3rd)
49
Putting it all together
Multiple snapshots and “deltas” on v$system_event
reveal “db file sequential read” as the wait event with
the highest frequency
This wait event is for “single block reads”
We start our path down to v$session_event and then
to v$session_wait
P1 and P2 reveal the file# and block# of the object
With dba_extents and dba_ data_files, the culprit
segment(s) are singled out
50
Putting it all together
Join v$session_wait with v$sql gets the SQL
executed by the waiting sessions
Using OS prong you collect I/O statistics. Device
response times are sub-optimal

sar –d reveals device response times at 80ms
Data collection and analysis diagnoses the problem
as “index overuse”.
Root cause – Too many RULE Hints
51
What’s new in Oracle 10g ?
- Active Session History!
New source of Oracle database performance data in 10g
An active session is one which is in a user call



Parse
Execute
Fetch
Provides historical information about recently sampled
“active” sessions
ASH = V$SESSION_WAIT++ with History

Note: In 10g V$SESSION_WAIT is integrated with
V$SESSION
It facilitates spot analysis of both foreground and
background sessions
52
Extreme Example #1
8GB SGA (4.5GB Shared Pool)

Pre-tuning state
Init.ora was tuned like crazy.
To attain a high library cache-hit ratio memory was periodically added (in
vain).
Bad response times with online queries.
System was experiencing severe parsing hiccups.



Bottleneck - Severe shared pool latch contention
Cause - Lack of bind variable usage
Post-tuning state - On fixing the application, shared pool was
shrunk to 256MB. Pre-tuning state symptoms vanished.
53
Extreme Example #2
6GB SGA (4GB Database Buffer Cache)

Pre-tuning State
Tuned the heck out of Init.ora parameters.
Cache-hit ratios were nice and balmy (90s).
Terrible response times.
High-levels of CPU usage.



Bottleneck – Severe contention for the cache buffers chains and
cache buffers lru chain latches. Moderate contention on db file
sequential read and buffer busy waits.
Cause - Correlated sub-queries, queries forced to use indexes,
lack of enough freelists many concurrent insert tables
Post-tuning State - Fixed the application, added more freelists
and freelists groups to the relevant tables, DB cache sized to 1GB
54
The Method & the Madness –
Useful Sites
•
•
•
•
•
www.orapub.com - Craig Shallahamer’s website
www.hotsos.com - Cary Millsap’s website
www.evdbt.com - Tim Gorman’s website
www.jlcomp.demon.co.uk - Jonathan Lewis
www.scaleabilities.co.uk - James Morle
55
The Method & the Madness – Useful
Papers & Books
• The YAPP Paper – By Anjo Kolk, Shari Yamaguchi &
Jim Viscusi
• James Morle’s “Scaling Oracle8i”
• Jonathan Lewis’s “Practical Oracle8i”
• Cary Millsap’s “Optimizing Oracle Performance”
• Tom Kyte’s “Effective Oracle by Design”
• Oracle Performance Tuning 101 – Yours Truly et. al
56
Diagnosing an Oracle
Performance Problem – A
Demo
Diagnosing an Oracle Performance
Problem – A Demo
View script toolkit
Run an I/O-intensive PL/SQL program
Use scripts to identify performance problem
58
Application Performance
Optimization – A DBA’s
Perspective
(Credits : Wolfgang
Breitling & Tim Gorman
on the Optimizer
Section)
Application Performance
Optimization – A DBA’s Perspective
What is the 80-20 rule?
Optimization Methodologies
Controlling the Optimization Method
Controlling the Optimizer’s Behavior
Using Hints
Calculation of object statistics – Why, How, How Much and
How Often?
Indexing Strategies

When should you rebuild your fragmented indexes?
Join Strategies
Managing Database Latching
Some low-hanging fruit in SQL Land
60
What is the 80-20 rule?
- My Perspective
80% of the world’s problems are NOT created by a
DBA - ;-)

There is a nasty corollary that can be derived from this
Oracle Instance Configuration and System
Optimization will provide < 20% impact
20% (or less) of your SQL will inflict 80% of more of
the pain in your system
80% or more of the I/O on your system is generated
by SQL on < 20% of the objects on the system
61
Optimization Methodologies
Rule





Rigid
Preferred method prior to Oracle 7.3.4
Stable across releases (except in 10g)
De-supported in 10g
Does not need any statistics
Cost





Flexible
Preferred method in Oracle 8.0 and higher
Requires object-level statistics
By default, is naïve with its assumptions
Utilizes new functionality in the database across different releases
62
Optimization Methodologies –
Rule
A bunch of rules - 15 basic rules
Rule #15 - Full Table Scan
Rule#10 – Access by a Composite Index Prefix
Rule#9 – Access by a Single-Column Index or Index
Merge
Rule#8 – Access by a Composite Index (An index
with more than 1 column) – entire key
Rule#1 - Access by ROWID
63
Optimization Methodologies –
Cost
Basic Premise - Execute SQL in the least expensive
way
Requires statistics to determine cost of the plan
Cost = XXXX


Prior to 9iR2 it was the cost of performing I/O
In 9iR2, the CPU cost is also factored in
Need to explicitly set DBMS_STATS.SET_SYSTEM_STATS
Stats are stored in SYS.AUX_STATS$

Affected by DB_FILE_MULTIBLOCK_READ_COUNT
64
Optimization Methodologies –
Cost
Statistics can be - ESTIMATEd or COMPUTEd


ANALYZE is rumored to be on the de-support train
In 9i and up use DBMS_STATS
Early releases of 8i was buggy especially with bitmapped
indexes. Worth a shot.

For Oracle Applications use FND_STATS or the new
equivalent
Use histograms in version 7.3 and up on skewed
data but only on SQL with “hard-coded values”
65
Oracle 9i Optimizer Changes
Histograms are used even with bind variables
This is done with BIND VARIABLE VALUE PEEKING



This is done at the FIRST PARSE of the cursor
If bind variable values change, the plan does not change
UNTIL the SQL is aged out
So based on the bind-variable value, the plan may not be
optimal
66
Oracle 9i – More data on your
SQL
Enhanced statistics in V$SQL and V$SQLAREA
V$SQLAREA – Some interesting columns




Fetches
CPU_Time
Elapsed_Time
Child_Latch
V$SQL – Some interesting columns




Fetches
Plan_Hash_Value
CPU_Time
Elapsed_Time
In 10g, there is a replacement for SQL_Hash_Value =
SQL_ID
67
Oracle 9i – More data on your
SQL
PLAN_TABLE



Create new PLAN_TABLE after each upgrade –
utlxplan.sql
Contains the execution plan for SQL statements for
EXPLAIN PLAN requests
New Columns
CPU_COST
IO_COST
TEMP_SPACE
ACCESS_PREDICATES (Start and Stop values for Indexes)
FILTER_PREDICATES
68
Oracle 9i – More data on your
SQL
V$SQL_PLAN_STATISTICS



Provides statistics at the row-source level and also
cumulative values
STATISTICS_LEVEL = ALL
Statspack Snap Level > 5
69
Oracle 9i – New Access Paths
INDEX_JOIN



Small indexes with all columns to resolve the query
without visiting the table
In 8i _INDEX_JOIN_ENABLED=FALSE
In 9i, it defaults to TRUE
Index Skip Scan

No longer require the leading column in the index to be
referenced in the WHERE clause
70
Controlling the Optimization
Method
At the Instance Level – OPTIMIZER_MODE



FIRST_ROWS, ALL_ROWS, CHOOSE, RULE
CHOOSE + STATISTICS = ALL_ROWS
Preferred Setting = CHOOSE
Setting to ALL_ROWS prior to 9iR1 can cause
statistics collection on the dictionary objects of
SYS
This can cause deadlocks and significant delays
as queries to the Oracle Dictionary is optimized
using RULE-based.
71
Controlling the Optimization
Method
At the Session Level – alter session….
At the Statement Level - /*+ HINT */
Changing initialization parameters



DB_FILE_MULTIBLOCK_READ_COUNT
HASH_MULTIBLOCK_IO_COUNT
HASH_AREA_SIZE
Setting Work-area Policy to AUTO and setting
PGA_AGGREGATE_SIZE provides better stability against
session-level parameters that affect the optimizer

Note PGA_AGGREGATE_SIZE does not limit PL/SQL tables
72
Controlling the Optimizer’s
Behavior
Default values of some of the Optimizer-related parameters (OPTIMIZER_*)
require modification when “execution plans” go south-bound.




OPTIMIZER_INDEX_CACHING
OPTIMIZER_INDEX_COST_ADJ
OPTIMIZER_MAX_PERMUTATIONS
OPTIMIZER_DYNAMIC_SAMPLING
In Oracle 9i, the following are required if you run into bug#2992537

EVENT 10076 – Ensure cartesian products are costed
alter session set events = ‘10076, trace name context forever’;



_ORDERED_NESTED_LOOP = FALSE – Ensure INDEX_FFS is cheaper than a
range scan
_TABLE_SCAN_COST_PLUS_ONE = FALSE – Ensure INDEX_FFS(single cost) is
cheaper than a range scan
_OPTIMIZER_NEW_JOIN_CARD_COMPUTATION = FALSE – Ensure cost
calculated is close to that of Oracle 817
In Oracle 8 and before it was as easy as setting OPTIMIZER_SEARCH_LIMIT = 1
Now it is _OPTIMIZER_SEARCH_LIMIT and the mininum value is 3
73
Controlling the Optimizer’s
Behavior
Useful for tuning packaged applications
Useful for tuning environments that require both
hash and nested loop joins
Please test first before deploying in production

Testing can be done at the session-level
Read Tim Gorman’s paper – “Searching for
intelligent life in the Oracle Optimizer” at
http://www.evdbt.com
Read Wolfgang Breitling’s paper – “What is new in
the Oracle 9i CBO” at http://www.centrexcc.com
74
Controlling the Optimizer’s Behavior
– OPTIMIZER_INDEX_CACHING
Tells the optimizer the probability that it will find an index block
in the cache
Controls optimizer propensity to pick an index for SQL
statement (usually using the nested loops join method)


Defaults to 0
Range of values - 0 – 100
When set to a high value (90 or higher), the optimize is
encouraged to use nested loops over other join methods
This parameter should be changed on all transactional
systems
75
Controlling the Optimizer’s Behavior –
OPTIMIZER_INDEX_COST_ADJ
Controls the optimizer’s propensity to use index
scans

Functionality similar to OPTIMIZER_INDEX_CACHING
Defaults to 100
Range of values - 1- 10000
Need to determine the appropriate value on a perdatabase basis
76
Controlling the Optimizer’s Behavior –
OPTIMIZER_INDEX_COST_ADJ
Calculating OPTIMIZER_INDEX_COST_ADJ







SELECT EVENT, AVERAGE_WAIT
FROM V$SYSTEM_EVENT
WHERE EVENT LIKE ‘db file s%’;
EVENT
AVERAGE_WAITS
========================= ==============
db file sequential read
.33178629
db file scattered read
2.190087
In the above example, the average single-block I/O requests takes
only 15% of the average multi-block I/O. On this system
set OPTIMIZER_INDEX_COST_ADJ to 15.
Source - Tim Gorman’s paper
77
Controlling the Optimizer’s Behavior –
OPTIMIZER_MAX_PERMUTATIONS
Number of plan permutations that the optimizer
chooses from.

Choice of driving table is key for query performance
Defaults to 80000 - Driving table is usually the
smallest table
When set < 80000 - Driving table is determined from
8 different plans
The plan with the lowest cost is picked
The default is 2000 in Oracle 9i and up
78
Controlling the Optimizer’s Behavior –
OPTIMIZER_DYNAMIC_SAMPLING
New parameter in Oracle 9i
Normally used for unanalyzed tables, but there are
exceptions
Assists in better estimation of cardinality and
selectivity
Relevant for long-running queries (over a few
seconds)
When OPTIMIZER_FEATURES_ENABLE is set to <
9.0.2, there will be no dynamic sampling
79
Controlling the Optimizer’s Behavior –
OPTIMIZER_DYNAMIC_SAMPLING
Range of values 0-10







0 – No dynamic sampling
1 – No dynamic sampling if query has less than 2 tables, table has
no indexes, has not been analyzed, a full-scan is deemed expensive
2 – Dynamic sampling on all un-analyzed tables, # of sampled
blocks=32
3 – #2 + for tables where selectivity estimation was done
4 – #3 + single table predicates that refer 2 or more columns in the
WHERE clause
5 thru 9 – Same as 4, but with sampled blocks=64, 128, 256, 1028,
4096
10 – Same as 4, but all blocks in the table are sampled
If the number of blocks at level 5-9 > 50% of the total blocks,
every block is sampled
80
10053 Trace File
Analysis
( Credits : Peter Bach of
the OakTable)
Determining what the Optimizer
is doing ***
Setting 10053



dbms_system.set_ev (…)
Valid levels – 1 or 2
Unlike other events level 2 produces less than 1
Looking at the output
Dissecting the plethora of information that is being
presented
Read Wolfgang Breitling’s paper on
http://www.centrex.com

A Look under the Hood of CBO: The 10053 Event
82
The SQL
select
offer.code_label, sda.index1_value, count(*)
from
service_history sh,
reference_code market,
service_da_array sda,
reference_code offer
where
sh.service_id = sda.service_id and
sh.service_status_code = 3 and
to_date('15/12/2003 12:00:00', 'dd/mm/yyyy hh24:mi:ss')
between sh.effective_start_date and sh.effective_end_date and
market.reference_type_id = 903285 and
market.reference_code = sh.general_1 and
market.code_label in ('MINNEAPOLIS') and
sda.derived_attribute_id = 907438 and
to_date('15/12/2003 12:00:00', 'dd/mm/yyyy hh24:mi:ss')
between sda.effective_start_date and sda.effective_end_date and
offer.reference_type_id = 905238 and
offer.reference_code = sda.index1_value
group by
offer.code_label, sda.index1_value;
83
The Old Execution Plan &
Autotrace Output
Execution Plan
---------------------------------------------------------0
SELECT STATEMENT Optimizer=CHOOSE (Cost=1333 Card=1 Bytes=101)
1 0 SORT (GROUP BY) (Cost=1333 Card=1 Bytes=101)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'SERVICE_! HISTORY' (Cost=2 Card=9974 Bytes=279272)
3 2
NESTED LOOPS (Cost=1260 Card=1 Bytes=101)
4 3
NESTED LOOPS (Cost=1258 Card=1 Bytes=73)
5 4
MERGE JOIN (CARTESIAN) (Cost=3 Card=1 Bytes=42)
6 5
TABLE ACCESS (BY INDEX ROWID) OF 'REFERENCE_CODE' (Cost=2 Card=1 Bytes=21)
7 6
INDEX (RANGE SCAN) OF 'I_REFERENCE_CODE_REF_TYPE' (NON-UNIQUE) (Cost=1 Card=26)
8 5
BUFFER (SORT) (Cost=1 Card=1 Bytes=21)
9 8
TABLE ACCESS (BY INDEX ROWID) OF 'REFERENCE_CODE' (Cost=1 Card=1 Bytes=21)
10 9
INDEX (RANGE SCAN) OF 'I_REFERENCE_CODE_REF_TYPE' (NON-UNIQUE)
11 4
TABLE ACCESS (BY INDEX ROWID) OF 'SERVICE_DA_ARRAY' (Cost=1255 Card=50 Bytes=1550)
12 11
INDEX (RANGE SCAN) OF 'I_SERVICE_DA_ARRAY_DA' (NON-UNIQUE)
13 3
INDEX (RANGE SCAN) OF 'P_SERVICE_HISTORY' (UNIQUE) (Cost=1 Card=1)
Statistics
---------------------------------------------------------0 recursive calls
0 db block gets
8977230 consistent gets
0 physical reads
1556 redo size
772 bytes sent via SQL*Net to client
652 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
5 rows processed
84
10053 Output
GENERAL PLANS
***********************
Join order[1]: REFERENCE_CODE [MARKET] REFERENCE_CODE [OFFER]
SERVICE_DA_ARRAY [SDA] SERVICE_HISTORY [SH]
Now joining: REFERENCE_CODE [OFFER] *******
NL Join
Outer table: cost: 2 cdn: 1 rcz: 18 resp: 2
Inner table: REFERENCE_CODE
Access path: tsc Resc: 110
Join: Resc: 112 Resp: 112
OPTIMIZER PERCENT INDEX CACHING = 75
Access path: index (join stp)
Index: I_REFERENCE_CODE_REF_TYPE
TABLE: REFERENCE_CODE
RSC_CPU: 0 RSC_IO: 1
IX_SEL: 0.0000e+00 TB_SEL: 2.1968e-04
Join: resc: 3 resp: 3
Join cardinality: 0 = outer (0) * inner (26) * sel (1.0000e+00) [flag=0]
Grouping column cardin! ality [CODE_LABEL] 26
Grouping column cardinality [INDEX1_VAL] 176
Best NL cost: 3 resp: 3
Join result: cost: 3 cdn: 1 rcz: 36
85
10053 Output
Now joining: SERVICE_DA_ARRAY [SDA] *******
NL Join
Outer table: cost: 3 cdn: 1 rcz: 36 resp: 3
Inner table: SERVICE_DA_ARRAY
Access path: tsc Resc: 2402
Join: Resc: 2405 Resp: 2405
OPTIMIZER PERCENT INDEX CACHING = 75
Access path: index (no sta/stp keys)
Index: I_SERVICE_DA_ARRAY
TABLE: SERVICE_DA_ARRAY
RSC_CPU: 0 RSC_IO: 7166
IX_SEL: 1.0000e+00 TB_SEL: 5.1224e-03
Join: resc: 7169 resp: 7169
OPTIMIZER PERCENT INDEX CACHING = 75
Access path: index (join stp)
Index: I_SERVICE_DA_ARRAY_DA
TABLE: SERVICE_DA_ARRAY
RSC_CPU: 0 RSC_IO: 1255
IX_SEL:&nbs! p; 0.0000e+00 TB_SEL: 1.2500e-01
Join: resc: 1258 resp: 1258
Join cardinality: 0 = outer (0) * inner (8753) * sel (5.6818e-03) [flag=0]
Grouping column cardinality [CODE_LABEL] 26
Grouping column cardinality [INDEX1_VAL] 176
Best NL cost: 1258 resp: 1258
86
10053 Output
SM Join
Outer table:
resc: 3 cdn: 1 rcz: 36 deg: 1 resp: 3
Inner table: SERVICE_DA_ARRAY
resc: 1561 cdn: 8753 rcz: 31 deg: 1 resp: 1561
using join:1 distribution:2 #groups:1
SORT resource
Sort statistics
Sort width:
598 Area size: 1048576 Max Area size:
Blocks to Sort:
1 Row size:
50 Rows:
1
Initial runs:
1 Merge passes:
1 IO Cost / pass:
Total IO sort cost: 73
Total CPU sort cost: 0
Total Temp space used: 0
SORT resource
Sort statistics
Sort width:
598 Area size: 1048576 Max Area size:
Blocks to Sort:
25 Row size:
45 Rows:
8753
Initial runs:
1 Merge passes:
1 IO Cost / pass:
Total IO sort cost: 97
Total CPU sort cost: 0
Total Temp space used: 0
Merge join Cost: 1734 Resp: 1734
104857600 Degree: 1
145
104857600 Degree: 1
169
87
10053 Output
Join cardinality: 0 = outer (0) * inner (8753) * sel (5.6818e-03)
Grouping column cardinality [CODE_LABEL] 26
Grouping column cardinality [INDEX1_VAL] 176
Best NL cost: 1258 resp: 1258
SM Join
Outer table:
resc: 3 cdn: 1 rcz: 36 deg: 1 resp: 3
Inner table: SERVICE_DA_ARRAY
resc: 1561 cdn: 8753 rcz: 31 deg: 1 resp: 1561
using join:1 distribution:2 #groups:1
SORT resource
Sort statistics
Sort width:
598 Area size: 1048576 Max Area size:
Blocks to Sort:
1 Row size:
50 Rows:
1
Initial runs:
1 Merge passes:
1 IO Cost / pass:
Total IO sort cost: 73
Total CPU sort cost: 0
Total Temp space used: 0
SORT resource
Sort statistics
Sort width:
598 Area size: 1048576 Max Area size:
Blocks to Sort:
25 Row size:
45 Rows:
8753
Initial runs:
1 Merge passes:
1 IO Cost / pass:
Total IO sort cost: 97
Total CPU sort cost: 0
Total Temp space used: 0
Merge join Cost: 1734 Resp: 1734
[flag=0]
104857600 Degr! ee: 1
145
104857600 Degree: 1
169
88
10053 Output
HA Join
Outer table:
resc: 3 cdn: 1 rcz: 36 deg: 1 resp: 3
Inner table: SERVICE_DA_ARRAY
resc: 1561 cdn: 8753 rcz: 31 deg: 1 resp: 1561
using join:8 distribution:2 #groups:1
Hash join one ptn Resc: 1 ! Deg: 1
hash_area: 128
(max=12800) buildfrag: 1
probefrag: 23
ppasses: 1
Hash join Resc: 1565 Resp: 1565
Join result: cost: 1258 cdn: 1 rcz: 67
89
The New Execution Plan & Autotrace Output
–10076 and the 3 underscore parameters are
set
Execution Plan
---------------------------------------------------------&! nbsp; 0
SELECT STATEMENT Optimizer=CHOOSE (Cost=1747 Card=12 Bytes=1212)
1 0 SORT (GROUP BY) (Cost=1747 Card=12 Bytes=1212)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'REFERENCE_CODE' (Cost=1 Card=26 Bytes=546)
3 2
NESTED LOOPS (Cost=1674 Card=12 Bytes=1212)
4 3
NESTED LOOPS (Cost=1596 Card=78 Bytes=6240)
5 4
HASH JOIN (Cost=1442 Card=77 Bytes=3773)
6 5
TABLE ACCESS (BY INDEX ROWID) OF 'REFERENCE_CODE' (Cost=2 Card=1 Bytes=21)
7 6
INDEX (RANGE SCAN) OF 'I_REFERENCE_CODE_REF_TYPE' (NON-UNIQUE) (Cost=1 Card=26)
8 5
TABLE ACCESS (FULL) OF 'SERVICE_HISTORY' (Cost=1439 Card=9974 Bytes=279272)
9 4
TABLE ACCESS (BY INDEX ROWID) OF 'SERVICE_DA_ARRAY' (Cost=2 Card=1 Bytes=31)
10 9
INDEX (RANGE SCAN) OF 'I_SERVICE_DA_ARRAY' (NON-UNIQUE) (Cost=1 Card=1)
11 3
INDEX (RANGE SCAN) OF 'I_REFERENCE_CODE_REF_TYPE' (NON-UNIQUE)
Statistics
---------------------------------------------------------14 recursive calls
0 db block gets
12395 consistent gets
0 physical reads
0 redo size
772 bytes sent via SQL*Net to client
652 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
5 rows processed
90
Using Hints
Modifying the Optimizer’s Behavior will reduce the number of
times you will need to use hints
Hints to the optimizer is equivalent of “application-level hardcoding”.
Across releases, hints pose an additional administrative
overhead of performing regression testing.
Across releases, the Optimizer has gotten very smart.
Stored Outlines  Stored Hints

Time for a magical performance demo
AVOID USING HINTS AS MUCH POSSIBLE!!!
91
Calculation of Object Statistics
The Burning Question – How often should I analyze
and collect stats?
Standard Answer – As often as your data changes

That is the WRONG answer
Reasonable Answer – As often as the statistical
composition of your data changes
It does not matter if you pump in 1,000,000 rows
everyday

Collect object statistics when the “statistical distribution
changes”
92
Calculation of Object Statistics
Why can’t I just analyze everyday?



ANALYZE invalidates all of the object’s SQL in the cache
That initiates a “hard parse” the next time around of
every SQL statement
If your system is already suffering from shared pool latch
and library cache latch problems, the pain of re-parsing
every SQL in the cache, will outweigh the benefit of new
statistics
Setting the MONITORING attribute has limited value

Change is measured with a static percentage – 20%???
93
Indexing Strategies
The columns of an index should be ordered based
on access patterns NOT distinct values
There are a zillion types of indexes today

Enlighten yourselves and your developers
Contrary to some papers, bitmapped indexes should
be used primarily for read-intensive applications

Locking is done at the extent-level in the bitmaps
Use PARALLELISM for creation and access
Use NOLOGGING for creation
94
Indexing Strategies
If PGA_AGGREGATE_SIZE is not used,
use large SORT_AREA_SIZE and
SORT_AREA_RETAINED_SIZE for index creations
Indexes can be rebuilt online and in-place today
Don’t make index rebuilding a “regular maintenance task”
every week
Rebuild only when there is a need, here are some symptoms




Application Response Time for a given query using a said index
access is unacceptable
There is trace data to corroborate that Index I/O is the key issue
The number of blocks physically read is a significant number when
compared to the total number of rows returned
Clustering Factor of the index is bad and the query performs well
defined range scans.
95
Join Strategies
The normal joins



Nested Loops
Sort-Merge
Hash
Hash Joins are great for the following scenario



Table A (small, say with 1000 rows)
Table B (big, say 1,000,000 rows)
SQL has a WHERE clause predicate that processes
most of Table B
96
Managing Database Latching
A latch is a piece of code run within the Oracle
executable where access is serialized


With a few exceptions, one and only one process can run
this code at any given time
Examples :
Reading a block in the DB Cache
Writing a block in the DB Cache
Moving blocks in the LRU List
Hard parsing a SQL statement
Soft parsing a SQL statement
Allocating space in the redo log buffer
Writing redo entries in the redo log buffer
97
Managing Database Latching
Wasteful demand for latches in the database can be
usually managed by the following




Reducing logical I/O demand for SQL
Avoiding unnecessary updates to tables
Designing and coding SQL that use bind variable
Using SESSION_CACHED_CURSORS
98
Some low-hanging fruit in SQL
Land
SQL-intensive code in PL/SQL
Compute-intensive code in Java/C/C++
Don’t code SQL and PL/SQL like Pascal

Replacing simple PL/SQL (if…then…else..end if) with DECODE
when possible
Reduce the number of context switches between SQL and
PL/SQL

Design your code to do as much in SQL
Use Bind Variables


Hard-coding values usually is a bad practice
Prior to 9i, you may use this to force the optimizer to use histograms
99
Some low-hanging fruit in SQL
Land
Analytical functions may look complicated, but can provide
very powerful programming capabilities
Making the code in triggers just a call to a procedure

Put all the code in the procedure
Use X$DUAL with a view on top of it instead of DUAL
Use Set Operators (MINUS, INTERSECT)


After all, we are still a relational database
Equivalent Functionality of an Outer-join between Table A and Table
B implemented using the MINUS set operaiton
Select blah1, blah2 from A
MINUS
Select blah3, blah4 from B; -- What is in A that is NOT in B
100
Some low-hanging fruit in SQL
Land
Indexes on foreign key columns for master-detail
transactional tables
Using non-unique indexes for UNIQUE constraints


Helps if you turn constraints ON and OFF
With this, the index is NOT dropped
Using the NOVALIDATE option with ENABLE of a
constraint
Creating hash clusters with 1 table

For read-only tables that are “look-up tables”
101
Great literary works on good
application design and coding
Tom Kyte’s “Effective Oracle by Design”
John Beresniewicz’s “Oracle Built-In Packages”
Steven Feuerstein’s “Oracle PL/SQL Programming &
Oracle PL/SQL Best Practices”
Guy Harrison’s “High Performance Tuning”
102
Oracle Instance
Configuration &
Optimization
Back to the Basics – Why are we
optimizing the Instance?
What are the wait events in your database?
Are you suffering from CTD?
Are you running your life on cache-hit ratios?
Is it time for a drink or two?
Friendly Advice - Don’t touch anything without
corroborating wait events that warrant a
configuration change
104
Oracle Architecture Overview
System Global Area
Database Buffer Cache
PMON
L
Main
R
U
Aux.
SMON
Dnn
Misc. Buffers
Repl.
Dirty
Shared Pool Area
RECO
Dictionary
Cache
SNPnn
Server Process
Redo
Log
Buffer
Snn
Misc. Queues
Pnn
Bootstrap Segment
Library
Cache
LCKnn
PGA
DBWR
CKPT
LGWR
ARCH
User Process
/u01
/u02
/u03
DATA
INDX
SYSTEM
/u04
RBS
/u05
TEMP
/u06
/u07
LOG1A
LOG1B
/u08
LOG2A
/u09
LOG2B
/u03
CNTRL1
/u04
CNTRL2
/u10
Archived
Redo
Logs
$ORACLE_
HOME/dbs
initSID.ora
105
What happens when you press
“Enter”?
SQL Statement Processing





Parse
Define
Bind
Execute
Fetch (For SELECT only)
106
SQL Statement Processing Parse
Steps in Parsing






Syntax Check
Object Resolution
Security Check
Build Parse Tree & Execution Plan
Store Parse Tree & Execution Plan in the Shared SQL
Area (Lib. Cache)
In 9i and up, bind variable value peeking is performed
Hard vs. Soft Parse
107
SQL Statement Processing Define
Resolve and map data types on the client and the
server
SQL*Net is involved
ARRAYSIZE negotiated
108
SQL Statement Processing - Bind
All bind variables(:v_id, :v_name etc.) are bound with
their current values
SQL is not hard-parsed for varying values
Facilitates re-use of SQL
109
SQL Statement Processing Execute
Execution Plan is applied on the SGA
Data is read or written to
If SQL is DML then
Redo & Rollback is generated;
Transactional operations are performed;
End If;
110
SQL Statement Processing Fetch
Data is fetched for SELECTs only
Number of fetches is subject to ARRAYSIZE

ARRAYSIZE has a direct impact on the amount of logical
I/O in your database
Perform array fetches and PL/SQL array processing when
possible


SQL*Plus - SET ARRAYSIZE n
Forms - Set the Records Fetched Block Property Sheet
111
Memory Allocation &
Management
Configure no more than 50% of the memory on the box to all
Oracle SGAs


In 10g, there will be an equivalent for the SGA too
The feature is called Auto SGA Tuning
Lock the memory for the SGA


This slows the paging daemon, utilizes less resources
Platform specific – MLOCK_SGA = TRUE or equivalent
Account memory for the filesystem buffer cache and the
operating system
Give the rest for Oracle PGAs


If 9i and up use PGA_AGGREGATE_SIZE
For prior releases use reasonable sort and hash area sizes
112
Memory Allocation &
Management
SQL lives in the Shared Pool


Configure SHARED_POOL_SIZE
Configure SHARED_POOL_RESERVED_SIZE for
systems with large PL/SQL packages
Java in the database lives in the Java Pool

Configure JAVA_POOL_SIZE
If using MTS, RMAN or Parallel Query

Configure LARGE_POOL_SIZE
All of this is automatically managed in 10g
113
Memory Allocation &
Management
Data lives in the database buffer cache
Configured with DB_BLOCK_SIZE and the various
DB_*CACHE parameters


Controls the size of a database block size
Every database should be at least 8K
Larger blocksizes provide



~40% increase query performance
Shorter Indexes
More data in each block
Use the formula DB_BLOCK_SIZE = F-S blocksize >= O-S
pagesize

This affects not only memory but also how I/O is performed
Buffer cache management has changed in 8i
114
Memory Allocation &
Management
Change journals in the database are first recorded to
the redo log buffer

-
-
Configure LOG_BUFFER
Size is based on the waits, bigger is definitely
not better
512K - 1Mb. is good for most environments
Badly sized redo log files can sometimes reflect
in waits for redo log buffer space allocation
115
Design your database for
performance
Pick the right database block size, in 9i there is support
for multiple block size
Block-level storage configuration


INITRANS, MAXTRANS, PCTUSED, PCTFREE, FREELISTS AND
FREELISTS GROUPS
Try Automatic Segment Space Management (ASSM)
in 9i – Given the lack of maturity, there are bugs
Adequate freelists and freelists groups need to be configure
for “concurrent” insert-intensive tables
In 8i and up use only locally-managed tablespaces


Extent management, space management is easier
Your INSERT statements will incur less “recursive SQL” for space
management
116
Design your database for
performance
Use locally-managed temporary tablespaces

Remember the files show up in DBA_TEMP_FILES
Use Global Temporary Tables for time-sensitive reporting

This will prevent tons of unnecessary redo generation
If you monitor the filesystem space, make your tablespaces
AUTOEXTEND
Avoid the RAID5 storage configuration for write-intensive
applications


RAID 10 is the preferred and cheaper option in the long run
Check out BAARF
117
Design your database for
performance
Use Automatic Undo Management from 9i and up
Prior to 9i, avoid using OPTIMAL for rollback
segment configuration

Disks are cheap, ORA-1555s and burning CPU cycles
are not
Remember, latch contention is caused due to
inefficient application design


Latches serialize code access within the Oracle
executable
Any contention for latches usually indicate bad SQL
118
Design your database for
performance
The main CPU consumers within your Oracle
database are


Logical I/O
Parsing
Reducing logical I/O positively affects query
performance, resource contention and performance
scalability
Reducing logical I/O will have the single-most
positive effect on response time
119
Thanks & References – Sorted in
Ascending Alphabetical Order of Last
Name
Steve Adams
John Beresniewicz
Wolfgang Breitling
Dave Ensor
Tim Gorman
Kyle Hailey
Anjo Kolk
Tom Kyte
Jonathan Lewis
Connor McDonald
Cary Millsap
James Morle
Mogens Norgaard
Craig Shallahamer
And many more in the OakTable (http:www.oaktable.net)
120
Conclusion
Oracle Performance Tuning is not wizardry or witchcraft
Response time and business drivers are key to any
performance optimization engagement
If you go after the “wait events” you will be successful in
unearthing the bottlenecks
Laundry list tuning that use a plethora of cache-hit
ratios is a waste of time
Oracle 10g makes the life of a DBA easier, but don’t worry
your job is still pretty secure
Don’t let CTD get the best of you
Good luck and may the force be with you!!
121