SQL Tuning
Presented to NAM
12-Feb-2016
By Kuldeep Singh
Introduction
SQL Tuning is Hard
Providing a Framework
Helps develop your own processes
There is no magic tool
Tools cannot reliably tune SQL statements
Tuning requires the involvement of you and other technical
and functional members of team
Introduction
How to speed up a slow query?
Find a better way to run the query
Cause the database to run the query your way
How does a database run a SQL query?
Join order
Join method
Access method
Challenges
Requires Expertise in Many Areas
Technical Plan, Data Access, SQL Design
Business What is the Purpose of SQL?
Tuning Takes Time
Large Number of SQL Statements
Each Statement is Different
Low Priority in Some Companies
Vendor Applications
Focus on Hardware or System Issues
Never Ending
Database Tuning Options
Hardware Solution (determine bottleneck)
More Memory
Faster or additional Processors
Faster Disk IO (possibly via RAID)
More Network Bandwidth
Software Solution
Database/Instance Tuning(Location of files, block size, db
buffer cache size, etc)
Object Tuning (Index creation, table reorganization, etc)
SQL Tuning (application tuning)
Identify End-to-End
Business Aspects
Who registered yesterday for SQL Tuning
Who uses this information?
Why does the business need to know this?
How often is the information needed?
Technical Information
Review Tables, Indexes, Triggers, Views, etc
Understand Relationships
Know the Data (High Level)
End-to-End Process
Understand Application Architecture
What Portion of the Total Time is Database
Wait Event Information
V$SESSION
V$SESSION_WAIT
SID
USERNAME
SQL_ID
PROGRAM
MODULE
ACTION
PLAN_HASH_VALUE
ROW_WAIT_OBJ#
SID
EVENT
P1, P1RAW, P2, P2RAW, P3, P3RAW
STATE (WAITING, WAITED)
Oracle 10g added this info to V$SESSION
V$SQL
V$SQLAREA
V$SQL_PLAN
SQL_ID
SQL_ID
SQL_ID
SQL_FULLTEXT
EXECUTIONS
PLAN_HASH_VALUE
PARSE_CALLS
BUFFER_GETS
DISK_READS
DBA_OBJECTS
OBJECT_ID
OBJECT_NAME
OBJECT_TYPE
Wait Event Information
SELECT s.sql_id, sql.sql_text, sql.plan_hash_value,
DECODE(s.state, 'WAITING', s.event, 'CPU/LogicalIO')
waitevent,
s.p1, s.p2, s.p3
FROM v$session s
JOIN v$sql sql ON (
s.sql_id = sql.sql_id AND s.sql_address = sql.address
)
WHERE program = AND s.sid =
AND <whatever else you know>
Wait Time Scenario
Which scenario is worse?
SQL Statement 1
Executed 100 times
Caused 100 minutes of wait time for end user
Waited 99% of time on db file sequential read
SQL Statement 2
Executed 1 time
Caused 100 minutes of wait time for end user
Waited 99% on enq: TX row lock contention
Gather - Metrics
Get baseline metrics
How long does it take now
What is acceptable (10 sec, 2 min, 1 hour)
Collect Wait Time Metrics How Long
Locking / Blocking
I/O problem, Latch contention
May be multiple issues
All have different resolutions
Document everything in simple language
Gather Execution Plan
Execution Plan
V$SQL_PLAN
Do not use EXPLAIN PLAN
DBMS_XPLAN
Bind Values
V$SQL_BIND_CAPTURE
Tracing
Table and Index Statistics
ERD
Execution Plan
-----------------------------------------------------------------------------| Id
| Operation
| Name
| Rows
| Bytes | Cost
-----------------------------------------------------------------------------|
0 | SELECT STATEMENT
95 |
1 |
1 |
167 |
95 |
2 |
1 |
138 |
94 |
3 |
7 |
357 |
87 |
4 |
| VW_SQ_1
201 |
7035 |
87 |
|*
5 |
6 |
201 |
3417 |
87 |
|*
7 |
|*
8 |
| REGISTRATION | 80000 |
1328K|
76 |
|*
9 |
|* 10 |
|* 11 |
|
12 |
|* 13 |
NESTED LOOPS
NESTED LOOPS
NESTED LOOPS
VIEW
FILTER
HASH GROUP BY
FILTER
TABLE ACCESS FULL
INDEX UNIQUE SCAN
| SYS_C0036920 |
1 |
16 |
0 |
1 |
87 |
1 |
| SYS_C0036919 |
1 |
0 |
1 |
29 |
1 |
| SYS_C0036918 |
1 |
0 |
TABLE ACCESS BY INDEX ROWID| CLASS
INDEX UNIQUE SCAN
TABLE ACCESS BY INDEX ROWID | STUDENT
INDEX UNIQUE SCAN
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - filter((MAX("SIGNUP_DATE")>=TRUNC(SYSDATE@!-1) AND
MAX("SIGNUP_DATE")<=TRUNC(SYSDATE@!)))
7 - filter(TRUNC(SYSDATE@!-1)<=TRUNC(SYSDATE@!))
8 - filter("CANCELLED"='N')
9 - access("R1"."STUDENT_ID"="STUDENT_ID" AND "R1"."CLASS_ID"="CLASS_ID" AND
"SIGNUP_DATE"="VW_COL_1")
filter(("SIGNUP_DATE">=TRUNC(SYSDATE@!-1) AND "SIGNUP_DATE"<=TRUNC(SYSDATE@!)))
10 - filter(UPPER("C"."NAME)='SQL TUNING')
11 - access("CLASS_ID"="C"."CLASS_ID")
13 - access("S"."STUDENT_ID"="STUDENT_ID")
Response time
Sum of service time + wait time
Processing strategy has key effect on response time
Eg: Sequential processing
In a queue, wait time for a job = sum of service time of all
previous jobs
If queue gets longer parallel processing required
Response time in Sequential and
Parallel processing
Wait time
jobs
Service time
time
jobs
Oracle tuning methodology
Tune business rules
Tune data design
Tune application design
Tune logical structure
Tune database operations
Tune access paths
Tune memory allocation
Tune I/O and physical structure
Tune resource contention
Access Methods
Access method = way that data is
retrieved from table
Index scan small number of rows
accessed
Full scan larger number of rows
accessed
Modifying the Access Method
Set Initialization Parameter
optimizer_index_caching
optimizer_index_cost_adj
db_file_multiblock_read_count
Hints
Full
Index
I/O and physical design
Use multiple disks + parallel controllers
Optimise block size
Use extents large enough for indexes
Use raw device
Resource contention
Block contention
Shared pool contention
Lock contention
All these can be diagnosed with Oracle
stats
Common Sense Indexing
Dont always need indexes
table with few columns
static data
small tables
appended tables (SQL*Loader)
How to index
single column surrogate sequences
dont override PK and FKs
avoid nullable columns
The Optimizer
An optimizer determines the best way to execute the SQL
query. Oracle has two optimizers.
The Oracle rules based optimizer follows a strict set of rules
when determining how to execute the query. For example,
one rule is that all available indexes should be used.
The Oracle cost based optimizer looks at statistics, such as
the number of rows in a table or the variance of values in a
column, to determine the best way to execute the SQL
statement. For example, the cost based optimizer may
choose to ignore an index if it sees that the table is very
small and will be completely pulled into memory with a
single block (page) read anyway.
Oracle Optimizer Modes
RULE
Uses the rules based optimizer only.
CHOOSE
Uses the cost based optimizer if any
statistics are available for the query tables.
FIRST_ROWS Uses the cost based optimizer but biases
the execution plan toward retrieving the
first rows to the user as fast as possible.
This is the default for the CHOOSE mode.
ALL_ROWS
Uses the cost based optimizer but biases
the execution plan toward minimizing the
total retrieval time, even if that means a
longer delay before the first rows are returned
to the user.
Changing Optimizer Modes
For session:
Alter session set optimizer_mode = <mode>
Alter session set optimizer_mode = RULE
For Query:
Select /*+ <mode> */ first, last from students;
Select /*+ FIRST_ROWS */ first, last from students;
Select /*+ FIRST_ROWS(50) */ first, last from students;
Select /*+ RULE */ first, last from students;
Select /*+ CHOOSE */ first, last from students;
Select /*+ ALL_ROWS */ first, last from students;
Index Decision
Should the Index Be used?
- what is table size
- what is column(s) selectivity
(if you are selecting >20%
dont bother with the index)
Is the optimizer making the correct decision?
Join Order
Small tables or Tables with High Selectivity should be joined before large
tables or tables with low selectivity.
Monitor
Monitor the improvement
Be able to prove that tuning made a difference
Take new metrics measurements
Compare them to initial readings
Brag about the improvements no one else will
Monitor for next tuning opportunity
Tuning is iterative
There are always room for improvements
Make sure you tune things that make a difference
Thank you