1
DB Performance
with
Graphics
With Kyle Hailey
Product Manger for DB Optimizer
OracleMonitor.com
2
Who is Kyle Hailey
• 1990 Oracle
– 90 support
– 92 Ported v6
– 93 France
– 95 Benchmarking
– 98 ST Real World Performance
• 2000 Dot.Com
• 2001 Quest
• 2002 Oracle OEM 10g
• 2006 Independent
• 2008 Embarcadero
– DB Optimizer
Success!
First successful OEM design
3
Launch: Pressure
Midnight before
January 28, 1986
Lives are on the line
Thanks to Edward Tufte
4
Copyright 2006
Kyle Hailey
13 Pages Faxed
5
Copyright 2006
Kyle Hailey
Original Engineering data
only showed damage
“damages at the hottest and
coldest temperature”
- management
6
Copyright 2006
Kyle Hailey
Congressional Hearings Evidence
7
Copyright 2006
Kyle Hailey
Clearer
1. Include successes
2. Mark Differences
3. Normalize same temp
4. Scale known vs unknown
55 65 75
60 70 80
4
8
12
4
8
12
30 40 50
35 45
X
8
Copyright 2006
Kyle Hailey
Difficult
• NASA Engineers Fail
• Congressional Investigators Fail
• Data Visualization is Difficult
But …
Lack of Clarity can be devastating
9
Solutions
• Clear Identification
– Know how to identify problems and issues
• Access to details
– Provide solutions and/or information to address the issues
• Graphics
– Easy understanding, effective communication and discussion
10
First Step: Graphics
“The humans … are exceptionally good at
parsing visual information, especially
when that information is coded by color
and/or _____ .”
Knowledge representation in cognitive science. Westbury, C. & Wilensky, U. (1998)
motion
11
Why Use Graphics
You can't imagine how many times I was told that nobody wanted or would
use graphics …
-- Jef Raskin, the creator of the Macintosh
Infocus – (overhead projectors) sited a
study that humans can parse graphical
information 400,000 times faster than
textual data
1212 10/30/10
Counties in US
• 3101 Counties in US
• 50 pages
13
“If I can't picture it, I can't understand it”
Anscombe's Quartet
I II III IV
x y x y x y x y
10 8.04 10 9.14 10 7.46 8 6.58
8 6.95 8 8.14 8 6.77 8 5.76
13 7.58 13 8.74 13 12.74 8 7.71
9 8.81 9 8.77 9 7.11 8 8.84
11 8.33 11 9.26 11 7.81 8 8.47
14 9.96 14 8.1 14 8.84 8 7.04
6 7.24 6 6.13 6 6.08 8 5.25
4 4.26 4 3.1 4 5.39 19 12.5
12 10.84 12 9.13 12 8.15 8 5.56
7 4.82 7 7.26 7 6.42 8 7.91
5 5.68 5 4.74 5 5.73 8 6.89
Average 9 7.5 9 7.5 9 7.5 9 7.5
Standard Deviation 3.31 2.03 3.31 2.03 3.31 2.03 3.31 2.03
Linear Regression 1.33 1.33 1.33 1.33
- Albert Einstein
14
Graphics for Anscombe’s Quartet
15
What is a day in the life look like
for a DBA who has performance
issues?
Tuning the Database
Complex
Averages
Anscombe's Quartet
I II III IV
x y x y x y x y
Average 9 7.5 9 7.5 9 7.5 9 7.5
Standard Deviation 3.31 2.03 3.31 2.03 3.31 2.03 3.31 2.03
Linear Regression 1.33 1.33 1.33 1.33
16
LOAD
Top
Activity
SQL Events Sessions
Get Details
Click here
Max CPU
(yard stick)
How Can We Open the Black Box?
17
How do we get our data?
Database
User 1
User 2
User 3
User 4
Active Sessions
=
1
2
3
4
Graph represents # of sessions active, but also represents amount of time active in the database
For Every Active Session there is a user (or application) waiting
Sample v$session : fast and light weight
We collect
• session
• SQL
• State (CPU, IO, LOCK, Other Waits)
• and many other columns
Multi-dimensional fine grain data. Difficult to use w/o graphics
18
AWR collects
06/05/08
25
34
36
38
45
F1qcyh20550cf
fj6gjgsshtxyx
0cjsxw5ndqdbc
8t8as9usk11qw
dr1rkrznhh95b
10dkqv3kr8xa5
38zhkf4jdyff4
298wmz1kxjs1m
CPU
Enq: TX – row lock contention
SQL*Net break/reset to client
db file scattered read
db file sequential read
SQL (v$sqlstats)
Sessions (v$sesstat)
Waits (v$system_event)
Which session executed which SQL?
Which SQL was block on a wait event ?
AWR ( and Statspack)
Can’t answer!
Old Method
19
After sampling Multi-dimensional
06/05/08
25 34 36 38 45 63 65 87
F1qcyh20550cf
fj6gjgsshtxyx
0cjsxw5ndqdbc
8t8as9usk11qw
dr1rkrznhh95b
10dkqv3kr8xa5
38zhkf4jdyff4
298wmz1kxjs1m
CPU
Enq: TX
–
row
lock
contention
SQ
L*N
et break/reset to
client
db
file
scattered
read
db
file
sequential read
IO
Application
SQL
Sessions
W
aits
Statistics
Service
Scott System
User
Program
Sys
Sqlplus SQL*Forms
GL OE
Package
Procedure
Plan
Child #
Module
Action
File, block, object
p1, p2, p3
Sampling
V$SESSION
20
DB Optimizer shows it all
Copyright 2006 Kyle Hailey
21
21
10/30/10
Average Active Sessions (AAS)
Use CPU count as yardstick:
 AAS < 1
Database is not blocked
 AAS ~= 0
Database basically idle
Problems are in the APP not DB
 AAS >> # of CPUS
There is a bottleneck
22
Interpreting the Load Chart
1. Application
– Code inefficient?
1. Database
– Configured correctly?
1. Machine
– Is the machine
undersized?
1. SQL
– Inefficient SQL?
Chart answers this question and
assists with solutions
Who’s problem is it ?
23
1. Application Issues
insert into foo values ('a');
commit;
insert into foo values ('a');
commit;
insert into foo values ('a');
commit;
insert into foo values ('a');
commit;
insert into foo values ('a');
commit;
insert into foo values ('a');
commit;
insert into foo values ('a');
commit;
4 concurrent
sessions run :
24
2. Database issue
begin
for i in 1..1000 loop
insert into foo values ('a');
end loop;
end;
/
Commit;
4 concurrent
sessions run :
25
3. Machine Undersized
26
4. SQL needs Tuning
27
Tuning SQL Complexity
PARSING IN CURSOR #2 len=53 dep=0 uid=61 oct=3
lid=61 tim=1151519905950403 hv=2296704914
ad='4e50010c'
SELECT 'Hello, world; today is ' || SYSDATE FROM dual
END OF STMT
PARSE
#2:c=4000,e=1540,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,
tim=1151519905950397
BINDS #2:
EXEC
#2:c=0,e=58,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1
151519906034782
WAIT #2: nam='SQL*Net message to client' ela= 2 driver
id=1650815232 #bytes=1 p3=0 obj#=-1
tim=1151519906034809
FETCH
#2:c=0,e=29,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,tim=1
151519906034864
WAIT #2: nam='SQL*Net message from client' ela= 215
driver id=1650815232 #bytes=1 p3=0 obj#=-1
tim=1151519906035133
FETCH
#2:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=11
51519906035165
WAIT #2: nam='SQL*Net message to client' ela= 1 driver
id=1650815232 #bytes=1 p3=0 obj#=-1
tim=1151519906035188
WAIT #2: nam='SQL*Net message from client' ela= 192
driver id=1650815232 #bytes=1 p3=0 obj#=-1
tim=1151519906035400
STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='FAST DUAL
(cr=0 pr=0 pw=0 time=3 us)
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows
|
--------------------------------------------------------------------------------------------
-
| 1 | HASH GROUP BY | | 1 | 1 | 1
|
|* 2 | FILTER | | 1 | | 1909
|
|* 3 | TABLE ACCESS BY INDEX ROWID | PS_RETROPAYPGM_TBL | 1 | 1 | 3413
|
| 4 | NESTED LOOPS | | 1 | 165 | 6827
|
|* 5 | HASH JOIN | | 1 | 165 | 3413
|
|* 6 | HASH JOIN | | 1 | 165 | 3624
|
| 7 | TABLE ACCESS BY INDEX ROWID | WB_JOB | 1 | 242 | 2895
|
| 8 | NESTED LOOPS | | 1 | 233 | 2897
|
| 9 | TABLE ACCESS BY INDEX ROWID| PS_PAY_CALENDAR | 1 | 1 | 1
|
|* 10 | INDEX RANGE SCAN | PS0PAY_CALENDAR | 1 | 1 | 1
|
|* 11 | INDEX RANGE SCAN | WBBJOB_B | 1 | 286 | 2895
|
|* 12 | TABLE ACCESS FULL | WB_RETROPAY_EARNS | 1 | 27456 |
122K|
| 13 | TABLE ACCESS FULL | PS_RETROPAY_RQST | 1 | 13679 | 13679
|
|* 14 | INDEX RANGE SCAN | PS#RETROPAYPGM_TBL | 3413 | 1 | 3413
|
| 15 | SORT AGGREGATE | | 1791 | 1 | 1791
|
| 16 | FIRST ROW | | 1791 | 1 | 1579
|
|* 17 | INDEX RANGE SCAN (MIN/MAX) | WB_JOB_F | 1791 | 1 | 1579
|
| 18 | SORT AGGREGATE | | 1539 | 1 | 1539
|
| 19 | FIRST ROW | | 1539 | 1 | 1539
|
|* 20 | INDEX RANGE SCAN (MIN/MAX) | WB_JOB_G | 1539 | 1 | 1539
Trace file Execution Plan
Complexity !
28
Visual SQL Tuning
29
Tuning SQL
• Indexes
– Missing indexes
• Table Stats
– Stale statistics
• Histograms
– Recommendations
• Execution Plan
– DB Optimizer automatically finds better plans
• Visual SQL Tuning diagrams
30
VST Steps
1. Tables
– drawn as nodes
1. Joins
– drawn as connector lines
1. Filters
– mark on each table with filter in where clause
30 10/30/10
31
How to VST: Tables and Joins
SELECT C.Phone_Number, C.Honorific, C.First_Name, C.Last_Name,
C.Suffix, C.Address_ID, A.Address_ID, A.Street_Address_Line1,
A.Street_Address_Line2, A.City_Name, A.State_Abbreviation,
A.ZIP_Code, OD.Deferred_Shipment_Date, OD.Item_Count,
ODT.Text, OT.Text, P.Product_Description, S.Shipment_Date
FROM Orders O, Order_Details OD, Products P, Customers C, Shipments S,
Addresses A, Code_Translations ODT, Code_Translations OT
WHERE UPPER(C.Last_Name) LIKE :Last_Name||'%'
AND UPPER(C.First_Name) LIKE :First_Name||'%'
AND OD.Order_ID = O.Order_ID
AND O.Customer_ID = C.Customer_ID
AND OD.Product_ID = P.Product_ID(+)
AND OD.Shipment_ID = S.Shipment_ID(+)
AND S.Address_ID = A.Address_ID(+)
AND O.Status_Code = OT.Code
AND OT.Code_Type = 'ORDER_STATUS'
AND OD.Status_Code = ODT.Code
AND ODT.Code_Type = 'ORDER_DETAIL_STATUS'
AND O.Order_Date > :Now - 366
ORDER BY C.Customer_ID, O.Order_ID DESC, S.Shipment_ID, OD.Order_Detail_ID;
Copyright 2006
Kyle Hailey
Tables
Orders O,
Order_Details OD,
Products P,
Customers C,
Shipments S,
Addresses A,
Code_Translations ODT,
Code_Translations OT
Joins
OD.Order_ID = O.Order_ID
O.Customer_ID = C.Customer_ID
OD.Product_ID = P.Product_ID(+)
OD.Shipment_ID =
S.Shipment_ID(+)
S.Address_ID = A.Address_ID(+)
O.Status_Code = OT.Code
OD.Status_Code = ODT.Code
Dan Tow – SQL TUNING
Filters
WHERE UPPER(C.Last_Name) LIKE :Last_Name||'%'
AND UPPER(C.First_Name) LIKE :First_Name||'%'
AND OT.Code_Type = 'ORDER_STATUS'
AND O.Order_Date > :Now – 366
AND ODT.Code_Type = 'ORDER_DETAIL_STATUS'
32
Layout tables and connections
Tables
Orders O,
Order_Details OD,
Products P,
Customers C,
Shipments S,
Addresses A,
Code_Translations ODT,
Code_Translations OT
Joins
OD.Order_ID = O.Order_ID
O.Customer_ID = C.Customer_ID
OD.Product_ID = P.Product_ID(+)
OD.Shipment_ID = S.Shipment_ID(+)
S.Address_ID = A.Address_ID(+)
O.Status_Code = OT.Code
OD.Status_Code = ODT.Code
F
S
A
OD
P
ODT
C
OT
O
33
Unstructured
Copyright 2006
Kyle Hailey
Joins
OD.Order_ID = O.Order_ID
O.Customer_ID = C.Customer_ID
OD.Product_ID = P.Product_ID(+)
OD.Shipment_ID = S.Shipment_ID(+)
S.Address_ID = A.Address_ID(+)
O.Status_Code = OT.Code
OD.Status_Code = ODT.Code
Neater, but can you do anything with it?
What’s the optimal execution path?
S
A
OD
P ODT
C
OT
O
34
Parents and Children
Copyright 2006
Kyle Hailey
Joins
OD.Order_ID = O.Order_ID
O.Customer_ID = C.Customer_ID
OD.Product_ID = P.Product_ID(+)
OD.Shipment_ID = S.Shipment_ID(+)
S.Address_ID = A.Address_ID(+)
O.Status_Code = OT.Code
OD.Status_Code = ODT.Code
ODT
OD
P
C
A
O
S
OT
Primary Key (unique index)
No index or non-unique
Master
Detail
Structure
the
tree
35
VST – filters and best path
Parent
Child
Parent
Child
Concept:
1. Start at most selective filter
2. Join down first, before joining upwards
Filters
WHERE UPPER(C.Last_Name) LIKE :Last_Name||'%'
AND UPPER(C.First_Name) LIKE :First_Name||'%'
AND OT.Code_Type = 'ORDER_STATUS‘
AND ODT.Code_Type = 'ORDER_DETAIL_STATUS'
AND O.Order_Date > :Now – 366
 Filters help determine best path
F
F
30%
0.02%
100% * (select count(*) from TAB where condition)
---------------------------
(select count(*) from Tab)
S
A
OD
P ODT
C OT
O
36
F
F
30%
0.02%
S
A
OD
P ODT
C OT
O
VST – best path
Note: Oracle only
joins in one table
to the previous
result set
F
F
37
Cartesian
SELECT
A.BROKER_ID BROKER_ID,
A.BROKER_LAST_NAME BROKER_LAST_NAME,
A.BROKER_FIRST_NAME BROKER_FIRST_NAME,
A.YEARS_WITH_FIRM YEARS_WITH_FIRM,
C.OFFICE_NAME OFFICE_NAME,
SUM (B.BROKER_COMMISSION)
TOTAL_COMMISSIONS
FROM
BROKER A,
CLIENT_TRANSACTION B,
OFFICE_LOCATION C,
INVESTMENT I
WHERE
A.BROKER_ID = B.BROKER_ID AND
A.OFFICE_LOCATION_ID =
C.OFFICE_LOCATION_ID
GROUP BY
A.BROKER_ID,
A.BROKER_LAST_NAME,
A.BROKER_FIRST_NAME,
A.YEARS_WITH_FIRM,
C.OFFICE_NAME;
38
Implied Cartesian
select
c.client_first_name, c.client_last_name,
ct.action, ct.price,
b.broker_last_name, b.broker_first_name,
o.office_name
from
client_transaction ct,
client c,
broker b,
office_location o
where
ct.price > 100
and b.broker_id=ct.broker_id
and c.broker_id = b.broker_id
and o.office_location_id = b.office_location_id
39
Diagram work for Many to One
What about many to many?
40
Unstructured
Copyright 2006
Kyle Hailey
Joins
OD.Order_ID = O.Order_ID
O.Customer_ID = C.Customer_ID
OD.Product_ID = P.Product_ID(+)
OD.Shipment_ID = S.Shipment_ID(+)
S.Address_ID = A.Address_ID(+)
O.Status_Code = OT.Code
OD.Status_Code = ODT.Code
S
A
OD
P ODT
C OT
O
S
A
OD
P ODT
C
OT
O
v
v
v
v
v
v
v
v
v
v
v
v
v
v
F
F
30%
0.02%
41
Many-to-One vs Many-to-Many
Predicate Filter
1
2
3
B -> C -> A go to A or C?
Now what?
42
Adding Constraints
SELECT COUNT (*)
FROM
b,
c,
a
WHERE
b.val2 = 100 AND
a.val1 = b.id AND
b.val1 = c.id;
58 logical reads
alter table c add constraint c_pk unique (id);
alter table b add constraint b_pk unique (id);
7 logical reads
43
Join sizes
Join Sizes
Use the Join
sizes to
determine path of
least resistance
44
Look at 3 queries
• Query 1 runs more than 24 hours
• Query 2 outer joins and scalar subqueries
• Query 3 create path not available to Oracle
45
Query 1 : Over 24 hours to run
SELECT
A0.zuchinis,
A0.brocoli,
C0.Oranges
FROM
(
SELECT
A1.planted_date,
A1.pears,
A1.zuchinis,
A1.brocoli
FROM
FOO.A A1,
(
SELECT
zuchinis,
brocoli
FROM FOO.A A2
WHERE
pears = 'M' AND
planted_date + 0 >= ADD_MONTHS ((SELECT
MAX (planted_date)
FROM FOO.B B1
WHERE
pears = 'M'
),
- 11)
GROUP BY
zuchinis,
brocoli
HAVING COUNT (*) = 12
)
i2
WHERE
A1.planted_date = (SELECT
MAX (planted_date)
FROM FOO.B B2
WHERE
pears = 'M'
) AND
A1.pears = 'M' AND
A1.zuchinis = i2.zuchinis (+) AND
A1.brocoli = i2.brocoli (+)
UNION
SELECT
A4.planted_date,
A4.pears,A4.zuchinis,A4.brocoli
FROM FOO.A A4
WHERE
A4.planted_date >'01-OCT-08' and A4.planted_date <'03-OCT-08' AND
A4.pears = 'D' AND
A4.green_beans = '1'
AND NOT EXISTS (SELECT
*
FROM FOO.A A5
WHERE
pears = 'M' AND
planted_date = (SELECT
MAX (planted_date)
FROM FOO.B B3
WHERE
pears = 'M'
) AND
A4.zuchinis = A5.zuchinis AND
A4.brocoli = A5.brocoli)
)
b,
FOO.A A0,
FOO.C C0,
FOO.D D0,
FOO.E E0
WHERE
A0.planted_date >'01-OCT-08' and
A0.planted_date <'03-OCT-08' AND
A0.pears = 'D' AND
A0.green_beans = '1' AND
A0.zuchinis = b.zuchinis AND
A0.brocoli = b.brocoli AND
A0.planted_date = C0.planted_date AND
A0.pears = C0.pears AND
A0.zuchinis = C0.zuchinis AND
A0.brocoli = C0.brocoli AND
A0.planted_date = D0.planted_date AND
A0.pears = D0.pears AND
A0.harvest_size = D0.harvest_size AND
C0.Oranges = D0.Oranges AND
C0.apples = D0.apples AND
(D0.lemons = 0 OR
D0.lemons IS NULL) AND
A0.planted_date = E0.planted_date AND
A0.pears = E0.pears AND
A0.harvest_size = E0.harvest_size AND
C0.Oranges = E0.Oranges AND
C0.apples = E0.apples AND
(E0.lemons = 0 OR
E0.lemons IS NULL)
ORDER BY
A0.zuchinis, A0.brocoli;
46
Visual SQL Diagram
9 secs
47
Default vs Tuned
Default
Tuned
48
Comparing Plans : 24 hours to 5 mins
NL
NL
NL
NL
HJ
HJ
NL
NL
49
Q2
49 10/30/10
SELECT CASE WHEN M.NYC IS NULL THEN (SELECT /*+ qb_name(qb1) */ MAX (Kona)
FROM foo.F
WHERE harvest_date = to_date('08/10/2008','dd/mm/yyyy')
AND Argentina = TRIM ('D') AND Norway = F_OUTER.Norway
ELSE M.NYC END AS NYC,
CASE WHEN F_OUTER.Perth IS NULL THEN NULL
ELSE (SELECT /*+ qb_name(qb2) */ Georgia FROM foo.P
WHERE harvest_date = to_date('08/10/2008','dd/mm/yyyy')
AND Argentina = TRIM ('D') AND Paris = F_OUTER.Perth)
END AS richard,
CASE WHEN F_OUTER.Aruba IS NULL THEN NULL
ELSE (SELECT /*+ qb_name(qb3) */ Georgia FROM foo.P
WHERE harvest_date = to_date('08/10/2008','dd/mm/yyyy')
AND Argentina = TRIM ('D') AND Paris = F_OUTER.Aruba)
END AS Jody,
CASE WHEN F_OUTER.Portland IS NULL THEN NULL
ELSE (SELECT /*+ qb_name(qb4) */ Georgia FROM foo.P
WHERE harvest_date = to_date('08/10/2008','dd/mm/yyyy')
AND Argentina = TRIM ('D') AND Paris = F_OUTER.Portland)
END AS Tom
FROM foo.F F_OUTER, foo.M , foo.J , foo.N ,
(SELECT /*+ qb_name(qb5) */ H.SF, Oregon, H.Haiti, K.Bermuda, L.Denmark
FROM (foo.H LEFT OUTER JOIN foo.K
ON H.harvest_date = K.harvest_date
AND H.Argentina = K.Argentina AND H.SF = K.SF
AND K.Dallas = '001')
LEFT OUTER JOIN FOo.L
ON H.harvest_date = L.harvest_date
AND H.Argentina = L.Argentina AND H.SF = L.SF
WHERE H.harvest_date = to_date('08/10/2008','dd/mm/yyyy')
AND H.Argentina = TRIM ('D')) extra
WHERE F_OUTER.harvest_date = M.harvest_date(+)
AND F_OUTER.Argentina = M.Argentina(+)
AND F_OUTER.Norway = M.Norway(+)
AND M.Norway(+) = M.Texas(+)
AND F_OUTER.harvest_date = to_date('08/10/2008','dd/mm/yyyy')
AND F_OUTER.Argentina = TRIM ('D')
AND M.harvest_date(+) = to_date('08/10/2008','dd/mm/yyyy')
AND M.Argentina(+) = TRIM ('D')
AND F_OUTER.Norway = F_OUTER.Hawaii
AND F_OUTER.harvest_date = J.harvest_date(+)
AND F_OUTER.Argentina = J.Argentina(+)
AND F_OUTER.Norway = J.Texas(+)
AND J.harvest_date(+) = to_date('08/10/2008','dd/mm/yyyy')
AND J.Argentina(+) = TRIM ('D')
AND F_OUTER.Iraq = extra.SF(+)
AND F_OUTER.harvest_date = N.harvest_date(+)
Two important qualities:
• All outer joins to F_OUTER
• 4 subqueries in select
select
50
Q2
10/30/10
12
825
845
682348
select
51
Q2
51 10/30/10
The subqueries in the select clause look like
select CASE WHEN F.f1 IS NULL
THEN NULL
ELSE (SELECT X.f2
FROM X
WHERE code_vl = F.f1)
END AS f0
from F;
and should be merged into the query like:
select CASE WHEN F.f1 IS NULL
THEN NULL
ELSE ( X.f2)
END AS f0
from F , X
where code_vl(+) = F.f1;
select CASE WHEN F.f1 IS NULL
THEN NULL
ELSE (SELECT X.f2
FROM X
WHERE code_vl = F.f2)
END AS f0
from F;
select CASE WHEN F.f1 IS NULL
THEN NULL
ELSE ( X.f2)
END AS f0
from F , X
where code_vl(+) = F.f1;
52
Q3
52 10/30/10
SELECT DISTINCT *
FROM
FOO.a a, FOO.c c, FOO.d d, FOO.g g
WHERE
a.planted_date > '01-OCT-08' AND
a.planted_date < '03-OCT-08' AND
a.pears = 'D' AND a.green_beans = '1' AND
a.planted_date = c.planted_date AND
a.pears = c.pears AND
a.zuchinis = c.zuchinis AND
a.brocoli = c.brocoli AND
a.planted_date = d.planted_date AND
a.pears = d.pears AND
a.harvest_size = d.harvest_size AND
c.oranges = d.oranges AND
c.apples = d.apples AND
(d.lemons = 0 OR d.lemons IS NULL) AND
a.planted_date = g.planted_date AND
a.pears = g.pears AND
a.harvest_size = g.harvest_size AND
c.oranges = g.oranges AND
c.apples = g.apples AND
(g.lemons = 0 OR g.lemons IS NULL) AND
a.zuchinis = '0236' AND
d.apples = g.apples AND
d.oranges = g.oranges
ORDER BY a.zuchinis, a.brocoli;
53
Q3: Transitivity
53 10/30/10
1,126,402
7,136,362
54
Q3
54 10/30/10
SELECT * FROM
(
SELECT /*+ NO_MERGE */ c.apples, c.oranges, a.harvest_size
FROM a, c
WHERE
a.planted_date = TO_DATE ('02/10/2008', 'dd/mm/yyyy') AND
a.pears = 'D' AND
a.green_beans = '1' AND
a.planted_date = c.planted_date AND
a.pears = c.pears AND
a.zuchinis = c.zuchinis AND
a.brocoli = c.brocoli AND
a.zuchinis = '0236'
) X,
(
SELECT /*+ NO_MERGE */ d.apples, d.oranges, d.harvest_size
FROM d, g
WHERE
d.planted_date = TO_DATE ('02/10/2008', 'dd/mm/yyyy') AND
g.planted_date = TO_DATE ('02/10/2008', 'dd/mm/yyyy') AND
g.apples = d.apples AND
d.oranges = g.oranges AND
d.pears = 'D' AND
g.pears = 'D' AND
g.pears = d.pears AND
g.harvest_size = d.harvest_size AND
(d.lemons = 0 OR d.lemons IS NULL) AND
(g.lemons = 0 OR g.lemons IS NULL)
) Y
WHERE
X.oranges = Y.oranges AND
X.apples = Y.apples AND
X.harvest_size = Y.harvest_size;
This final version runs in
elapsed 0.33 secs and 12K logical reads
down from an original
elapsed 4.5 secs and 1M logical reads
55
What tools to use to create VST diagrams?
• Paper
– Modifications messy and difficult
• PowerPoint
– Can move things around
– Sticky connectors
– Easy to modify
• DB Optimizer
– Automatic and still modifiable
56
Visual SQL Tuning (VST)
Table Sizes
Join Sizes
Filter Ratios
Exists
57
VST Steps Summary
1.Diagram tables
2.Draw connectors for each join
3.Calculate filter ratios
4.Find the table sizes
5.Calculate two table join sizes
Execution Path
• Start at the most selective join filter
• Join to keep the running result set size small
Many to Many relationships = problems
57 10/30/10
Parent
Child
Parent
Child
F
F
30%
0.02%
S
A
OD
P ODT
C OT
O
58
Copyright 2006
Kyle Hailey
Do You Want?
Engineering Data?
Engineering Data?
59
Copyright 2006
Kyle Hailey
Do You Want?
Pretty Pictures
Pretty Pictures
60
Copyright 2006
Kyle Hailey
Do You Want?
Clean and Clear
Clean and Clear
? ? ? ? ? ?
61
Copyright 2006
Kyle Hailey
Imagine Trying to Drive your Car
And is updated once and hour
And is updated once and hour
Or would you like it to look …
Would you want your dashboard to look like :
62
Copyright 2006
Kyle Hailey
Or This
63
Summary
1.Database - AAS
– Profile database
– Use wait interface and graphics
– Identify machine, application, database or SQL
1.SQL - VST
– Indexes, stats, execution path
– Visual SQL Tuning
64
Bibliography
http://www.simple-talk.com/sql/performance/designing-efficient-sql-a-visual-approach/
Refactoring SQL Applications – Stephane Faroult
Troubleshooting Oracle Performance – Christian Antognini
SQL Tuning – Dan Tow
Cost-Based Oracle Fundamentals – Jonathan Lewis
65
Visual SQL Tuning (VST)
Industry Exclusive
66
DB Optimizer XE Key Features
Profile
Tune
Load Test
SQL IDE
67
DB Optimizer XE Key Features
Profile
Tune
Load Test
SQL IDE
68
DB Optimizer XE Key Features
Profile
Tune
Load Test
SQL IDE
69
DB Optimizer XE Key Features
Profile
Tune
Load Test
SQL IDE
70
Review of Functionality
Profile
Tune
Load Test
SQL IDE
Only tool on the market with these
features integrated
71
Thank You
Kyle Hailey
http://oraclemonitor.com
72
Appendix
• Diagramming
– Simple joins and inline views
– Outer joins
– Exists/not exists (in/not in)
– Correlated aggregate sub-queries
• Hints
– LEADING
– USE_NL
– USE_HASH
– INDEX
– NO_MERGE
• Execution Order
• Machine Health
• VST method with Statistics
73
Basic Joins
Many to
single value
Cartesian
Cartesian
Safe
Dangerous
M
74
Simple queries and sub-queries
74
A
B
select * from A, B where b.f1=a.f1
Non-correlated sub-query
select * from A,(select b.f1 from B) c
where c.f1=a.f1
Simple join
select * from A where a.f1 =
(select max(b.f1) from B )
Special case: non correlated sub-query returns one row
A B
A
B
A B
Unique index on b.f1
No unique indexes Unique index on
Both b.f1 and a.f1
M
75
Outer Joins
75 10/30/10
Outer Joins
76
Correlated scalar sub-queries
76 10/30/10
Correlated aggregate subquery:
select ename from emp a where a.sal >
(select avg(sal)
from emp b
where a.deptno=b.deptno)
A
B
Scalar Subqueries
select ename, (select avg(sal)
from emp b
where a.deptno=b.deptno)
from emp a;
77
Exists and Not In
77 10/30/10
SELECT d.*
FROM dept d WHERE exists (
SELECT null FROM emp e WHERE e.deptno=d.deptno);
SELECT d.*
FROM dept d WHERE d.deptno in (
SELECT deptno FROM emp e );
select distinct d.* from dept1 d ,emp e
where e.deptno = d.deptno;
SELECT d.*
FROM dept d WHERE not exists (
SELECT null FROM emp e WHERE e.deptno=d.deptno);
SELECT d.*
FROM dept d WHERE d.deptno not in (
SELECT deptno FROM emp e where e.deptno is not null )
or d.deptno is null;
select d.* from dept1 d left outer join emp e
on e.deptno = d.deptno where e.deptno is null;
E
N
78
HINTS
• ORDERED - good on 9i
• Leading(tab_alias , table_alias … ) – 10g format
• USE_NL(table_alias) – Inner Table (not driving)
• USE_HASH(table_alias) – 2cd table, probe into
• INDEX(tab_alias index_name)
• NO_MERGE
Oracle first decides join order then join type
(example http://www.adp-gmbh.ch/blog/2008/01/17.php)
78 10/30/10
79
Visual SQL Tuning (VST) diagrams
79 10/30/10
HJ NL
i
io
HJ
NL
Makes comparison of execution plans easy
Better yet, it will help us find the best execution path
80
SELECT
O.ORDER_ID,
LINE_ITEM_ID,
PRODUCT_ID,
UNIT_PRICE,
QUANTITY,
ORDER_MODE,
ORDER_STATUS,
ORDER_TOTAL,
SALES_REP_ID,
PROMOTION_ID,
C.CUSTOMER_ID,
CUST_FIRST_NAME,
CUST_LAST_NAME,
CREDIT_LIMIT,
CUST_EMAIL,
ORDER_DATE
FROM
ORDERS O,
ORDER_ITEMS OI,
CUSTOMERS C
WHERE
O.ORDER_ID = OI.ORDER_ID AND
O.CUSTOMER_ID = C.CUSTOMER_ID AND
O.ORDER_STATUS <= 4
VST vs Explain Plan
80 10/30/10
i
MJ
HJ
HJ
NL
81
i
MJ
HJ
Bad Plans vs Good Plan
81 10/30/10
HJ
NL
82
Comparing Plans : 24 hours to 5 mins
NL
NL
NL
NL
HJ
HJ
NL
NL
83
When to Tune
1. Machine
a) CPU
• Response times skewed
• 100% CPU might be fine
• Users wait in queue (run queue) => machine underpowered
a) Memory
• Paging
• Wait times skewed (ex : latch free)
• Erratic response times ( ex : ls )
1. Oracle
1) Waits > CPU ?
• tune waits
1) CPU > 100% ?
• tune top CPU SQL
1) Else
• It’s the application
Oracle Load
(AAS)
Top Session Top Wait Top SQL
SQL Detail Session Detail File Detail
Object Detail Wait Detail
Host
AAS >
#CPU
AAS > 1
Waits >
CPU
CPU >
Waits
CPU
Memory
84
Machine
Make sure the machine is healthy before tuning Oracle
• CPU => use run queue, < 2 * #CPU
• Memory => page out
VMSTAT
85
Summary
1.Machine - vmstat
– Memory, CPU (we can see IO response in Oracle)
1.Database - AAS
– Use wait interface and graphics
– Identify machine, application, database or SQL
1.SQL - VST
– Indexes, stats, execution path
– Visual SQL Tuning
86
Solution to Many to Many
Table Sizes
Filter Ratios
Join Sizes
87
VST Steps
Objects:
1. Tables : drawn as nodes
2. Joins : drawn as connector lines
3. Filters : mark on each table with filter in where clause
Statistics:
1.Table sizes
2. Join sizes
3. Calculate filter percentages
– filter ratio = number of rows returned with filter / number of rows
87 10/30/10
88
Google Directions
• Compare two sets of directions
• (optionally show graphical set of directions)
• Show map
• Show map with traffic flow, read, yellow, green
89
How Can We Open the Black Box?
OEM ASHMON/SASH DB Optimizer
•Powerful - Identifies issues quickly and powerfully
•Interactive - Allows exploring the data
•Easy - Understandable by everyone, DBA, Dev and Managers !
90
Copyright 2006
Kyle Hailey
Clearer
1. Include successes
2. Remove Irrelevant
3. Normalize same temp
4. Scale known vs unknown
55 65 75
60 70 80
4
8
12
4
8
12
30 40 50
35 45
X

Hailey_Database_Performance_Made_Easy_through_Graphics.pdf

  • 1.
    1 DB Performance with Graphics With KyleHailey Product Manger for DB Optimizer OracleMonitor.com
  • 2.
    2 Who is KyleHailey • 1990 Oracle – 90 support – 92 Ported v6 – 93 France – 95 Benchmarking – 98 ST Real World Performance • 2000 Dot.Com • 2001 Quest • 2002 Oracle OEM 10g • 2006 Independent • 2008 Embarcadero – DB Optimizer Success! First successful OEM design
  • 3.
    3 Launch: Pressure Midnight before January28, 1986 Lives are on the line Thanks to Edward Tufte
  • 4.
  • 5.
    5 Copyright 2006 Kyle Hailey OriginalEngineering data only showed damage “damages at the hottest and coldest temperature” - management
  • 6.
  • 7.
    7 Copyright 2006 Kyle Hailey Clearer 1.Include successes 2. Mark Differences 3. Normalize same temp 4. Scale known vs unknown 55 65 75 60 70 80 4 8 12 4 8 12 30 40 50 35 45 X
  • 8.
    8 Copyright 2006 Kyle Hailey Difficult •NASA Engineers Fail • Congressional Investigators Fail • Data Visualization is Difficult But … Lack of Clarity can be devastating
  • 9.
    9 Solutions • Clear Identification –Know how to identify problems and issues • Access to details – Provide solutions and/or information to address the issues • Graphics – Easy understanding, effective communication and discussion
  • 10.
    10 First Step: Graphics “Thehumans … are exceptionally good at parsing visual information, especially when that information is coded by color and/or _____ .” Knowledge representation in cognitive science. Westbury, C. & Wilensky, U. (1998) motion
  • 11.
    11 Why Use Graphics Youcan't imagine how many times I was told that nobody wanted or would use graphics … -- Jef Raskin, the creator of the Macintosh Infocus – (overhead projectors) sited a study that humans can parse graphical information 400,000 times faster than textual data
  • 12.
    1212 10/30/10 Counties inUS • 3101 Counties in US • 50 pages
  • 13.
    13 “If I can'tpicture it, I can't understand it” Anscombe's Quartet I II III IV x y x y x y x y 10 8.04 10 9.14 10 7.46 8 6.58 8 6.95 8 8.14 8 6.77 8 5.76 13 7.58 13 8.74 13 12.74 8 7.71 9 8.81 9 8.77 9 7.11 8 8.84 11 8.33 11 9.26 11 7.81 8 8.47 14 9.96 14 8.1 14 8.84 8 7.04 6 7.24 6 6.13 6 6.08 8 5.25 4 4.26 4 3.1 4 5.39 19 12.5 12 10.84 12 9.13 12 8.15 8 5.56 7 4.82 7 7.26 7 6.42 8 7.91 5 5.68 5 4.74 5 5.73 8 6.89 Average 9 7.5 9 7.5 9 7.5 9 7.5 Standard Deviation 3.31 2.03 3.31 2.03 3.31 2.03 3.31 2.03 Linear Regression 1.33 1.33 1.33 1.33 - Albert Einstein
  • 14.
  • 15.
    15 What is aday in the life look like for a DBA who has performance issues? Tuning the Database Complex Averages Anscombe's Quartet I II III IV x y x y x y x y Average 9 7.5 9 7.5 9 7.5 9 7.5 Standard Deviation 3.31 2.03 3.31 2.03 3.31 2.03 3.31 2.03 Linear Regression 1.33 1.33 1.33 1.33
  • 16.
    16 LOAD Top Activity SQL Events Sessions GetDetails Click here Max CPU (yard stick) How Can We Open the Black Box?
  • 17.
    17 How do weget our data? Database User 1 User 2 User 3 User 4 Active Sessions = 1 2 3 4 Graph represents # of sessions active, but also represents amount of time active in the database For Every Active Session there is a user (or application) waiting Sample v$session : fast and light weight We collect • session • SQL • State (CPU, IO, LOCK, Other Waits) • and many other columns Multi-dimensional fine grain data. Difficult to use w/o graphics
  • 18.
    18 AWR collects 06/05/08 25 34 36 38 45 F1qcyh20550cf fj6gjgsshtxyx 0cjsxw5ndqdbc 8t8as9usk11qw dr1rkrznhh95b 10dkqv3kr8xa5 38zhkf4jdyff4 298wmz1kxjs1m CPU Enq: TX– row lock contention SQL*Net break/reset to client db file scattered read db file sequential read SQL (v$sqlstats) Sessions (v$sesstat) Waits (v$system_event) Which session executed which SQL? Which SQL was block on a wait event ? AWR ( and Statspack) Can’t answer! Old Method
  • 19.
    19 After sampling Multi-dimensional 06/05/08 2534 36 38 45 63 65 87 F1qcyh20550cf fj6gjgsshtxyx 0cjsxw5ndqdbc 8t8as9usk11qw dr1rkrznhh95b 10dkqv3kr8xa5 38zhkf4jdyff4 298wmz1kxjs1m CPU Enq: TX – row lock contention SQ L*N et break/reset to client db file scattered read db file sequential read IO Application SQL Sessions W aits Statistics Service Scott System User Program Sys Sqlplus SQL*Forms GL OE Package Procedure Plan Child # Module Action File, block, object p1, p2, p3 Sampling V$SESSION
  • 20.
    20 DB Optimizer showsit all Copyright 2006 Kyle Hailey
  • 21.
    21 21 10/30/10 Average Active Sessions(AAS) Use CPU count as yardstick:  AAS < 1 Database is not blocked  AAS ~= 0 Database basically idle Problems are in the APP not DB  AAS >> # of CPUS There is a bottleneck
  • 22.
    22 Interpreting the LoadChart 1. Application – Code inefficient? 1. Database – Configured correctly? 1. Machine – Is the machine undersized? 1. SQL – Inefficient SQL? Chart answers this question and assists with solutions Who’s problem is it ?
  • 23.
    23 1. Application Issues insertinto foo values ('a'); commit; insert into foo values ('a'); commit; insert into foo values ('a'); commit; insert into foo values ('a'); commit; insert into foo values ('a'); commit; insert into foo values ('a'); commit; insert into foo values ('a'); commit; 4 concurrent sessions run :
  • 24.
    24 2. Database issue begin fori in 1..1000 loop insert into foo values ('a'); end loop; end; / Commit; 4 concurrent sessions run :
  • 25.
  • 26.
  • 27.
    27 Tuning SQL Complexity PARSINGIN CURSOR #2 len=53 dep=0 uid=61 oct=3 lid=61 tim=1151519905950403 hv=2296704914 ad='4e50010c' SELECT 'Hello, world; today is ' || SYSDATE FROM dual END OF STMT PARSE #2:c=4000,e=1540,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1, tim=1151519905950397 BINDS #2: EXEC #2:c=0,e=58,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1 151519906034782 WAIT #2: nam='SQL*Net message to client' ela= 2 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1151519906034809 FETCH #2:c=0,e=29,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,tim=1 151519906034864 WAIT #2: nam='SQL*Net message from client' ela= 215 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1151519906035133 FETCH #2:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=11 51519906035165 WAIT #2: nam='SQL*Net message to client' ela= 1 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1151519906035188 WAIT #2: nam='SQL*Net message from client' ela= 192 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1151519906035400 STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=3 us) -------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | -------------------------------------------------------------------------------------------- - | 1 | HASH GROUP BY | | 1 | 1 | 1 | |* 2 | FILTER | | 1 | | 1909 | |* 3 | TABLE ACCESS BY INDEX ROWID | PS_RETROPAYPGM_TBL | 1 | 1 | 3413 | | 4 | NESTED LOOPS | | 1 | 165 | 6827 | |* 5 | HASH JOIN | | 1 | 165 | 3413 | |* 6 | HASH JOIN | | 1 | 165 | 3624 | | 7 | TABLE ACCESS BY INDEX ROWID | WB_JOB | 1 | 242 | 2895 | | 8 | NESTED LOOPS | | 1 | 233 | 2897 | | 9 | TABLE ACCESS BY INDEX ROWID| PS_PAY_CALENDAR | 1 | 1 | 1 | |* 10 | INDEX RANGE SCAN | PS0PAY_CALENDAR | 1 | 1 | 1 | |* 11 | INDEX RANGE SCAN | WBBJOB_B | 1 | 286 | 2895 | |* 12 | TABLE ACCESS FULL | WB_RETROPAY_EARNS | 1 | 27456 | 122K| | 13 | TABLE ACCESS FULL | PS_RETROPAY_RQST | 1 | 13679 | 13679 | |* 14 | INDEX RANGE SCAN | PS#RETROPAYPGM_TBL | 3413 | 1 | 3413 | | 15 | SORT AGGREGATE | | 1791 | 1 | 1791 | | 16 | FIRST ROW | | 1791 | 1 | 1579 | |* 17 | INDEX RANGE SCAN (MIN/MAX) | WB_JOB_F | 1791 | 1 | 1579 | | 18 | SORT AGGREGATE | | 1539 | 1 | 1539 | | 19 | FIRST ROW | | 1539 | 1 | 1539 | |* 20 | INDEX RANGE SCAN (MIN/MAX) | WB_JOB_G | 1539 | 1 | 1539 Trace file Execution Plan Complexity !
  • 28.
  • 29.
    29 Tuning SQL • Indexes –Missing indexes • Table Stats – Stale statistics • Histograms – Recommendations • Execution Plan – DB Optimizer automatically finds better plans • Visual SQL Tuning diagrams
  • 30.
    30 VST Steps 1. Tables –drawn as nodes 1. Joins – drawn as connector lines 1. Filters – mark on each table with filter in where clause 30 10/30/10
  • 31.
    31 How to VST:Tables and Joins SELECT C.Phone_Number, C.Honorific, C.First_Name, C.Last_Name, C.Suffix, C.Address_ID, A.Address_ID, A.Street_Address_Line1, A.Street_Address_Line2, A.City_Name, A.State_Abbreviation, A.ZIP_Code, OD.Deferred_Shipment_Date, OD.Item_Count, ODT.Text, OT.Text, P.Product_Description, S.Shipment_Date FROM Orders O, Order_Details OD, Products P, Customers C, Shipments S, Addresses A, Code_Translations ODT, Code_Translations OT WHERE UPPER(C.Last_Name) LIKE :Last_Name||'%' AND UPPER(C.First_Name) LIKE :First_Name||'%' AND OD.Order_ID = O.Order_ID AND O.Customer_ID = C.Customer_ID AND OD.Product_ID = P.Product_ID(+) AND OD.Shipment_ID = S.Shipment_ID(+) AND S.Address_ID = A.Address_ID(+) AND O.Status_Code = OT.Code AND OT.Code_Type = 'ORDER_STATUS' AND OD.Status_Code = ODT.Code AND ODT.Code_Type = 'ORDER_DETAIL_STATUS' AND O.Order_Date > :Now - 366 ORDER BY C.Customer_ID, O.Order_ID DESC, S.Shipment_ID, OD.Order_Detail_ID; Copyright 2006 Kyle Hailey Tables Orders O, Order_Details OD, Products P, Customers C, Shipments S, Addresses A, Code_Translations ODT, Code_Translations OT Joins OD.Order_ID = O.Order_ID O.Customer_ID = C.Customer_ID OD.Product_ID = P.Product_ID(+) OD.Shipment_ID = S.Shipment_ID(+) S.Address_ID = A.Address_ID(+) O.Status_Code = OT.Code OD.Status_Code = ODT.Code Dan Tow – SQL TUNING Filters WHERE UPPER(C.Last_Name) LIKE :Last_Name||'%' AND UPPER(C.First_Name) LIKE :First_Name||'%' AND OT.Code_Type = 'ORDER_STATUS' AND O.Order_Date > :Now – 366 AND ODT.Code_Type = 'ORDER_DETAIL_STATUS'
  • 32.
    32 Layout tables andconnections Tables Orders O, Order_Details OD, Products P, Customers C, Shipments S, Addresses A, Code_Translations ODT, Code_Translations OT Joins OD.Order_ID = O.Order_ID O.Customer_ID = C.Customer_ID OD.Product_ID = P.Product_ID(+) OD.Shipment_ID = S.Shipment_ID(+) S.Address_ID = A.Address_ID(+) O.Status_Code = OT.Code OD.Status_Code = ODT.Code F S A OD P ODT C OT O
  • 33.
    33 Unstructured Copyright 2006 Kyle Hailey Joins OD.Order_ID= O.Order_ID O.Customer_ID = C.Customer_ID OD.Product_ID = P.Product_ID(+) OD.Shipment_ID = S.Shipment_ID(+) S.Address_ID = A.Address_ID(+) O.Status_Code = OT.Code OD.Status_Code = ODT.Code Neater, but can you do anything with it? What’s the optimal execution path? S A OD P ODT C OT O
  • 34.
    34 Parents and Children Copyright2006 Kyle Hailey Joins OD.Order_ID = O.Order_ID O.Customer_ID = C.Customer_ID OD.Product_ID = P.Product_ID(+) OD.Shipment_ID = S.Shipment_ID(+) S.Address_ID = A.Address_ID(+) O.Status_Code = OT.Code OD.Status_Code = ODT.Code ODT OD P C A O S OT Primary Key (unique index) No index or non-unique Master Detail Structure the tree
  • 35.
    35 VST – filtersand best path Parent Child Parent Child Concept: 1. Start at most selective filter 2. Join down first, before joining upwards Filters WHERE UPPER(C.Last_Name) LIKE :Last_Name||'%' AND UPPER(C.First_Name) LIKE :First_Name||'%' AND OT.Code_Type = 'ORDER_STATUS‘ AND ODT.Code_Type = 'ORDER_DETAIL_STATUS' AND O.Order_Date > :Now – 366  Filters help determine best path F F 30% 0.02% 100% * (select count(*) from TAB where condition) --------------------------- (select count(*) from Tab) S A OD P ODT C OT O
  • 36.
    36 F F 30% 0.02% S A OD P ODT C OT O VST– best path Note: Oracle only joins in one table to the previous result set F F
  • 37.
    37 Cartesian SELECT A.BROKER_ID BROKER_ID, A.BROKER_LAST_NAME BROKER_LAST_NAME, A.BROKER_FIRST_NAMEBROKER_FIRST_NAME, A.YEARS_WITH_FIRM YEARS_WITH_FIRM, C.OFFICE_NAME OFFICE_NAME, SUM (B.BROKER_COMMISSION) TOTAL_COMMISSIONS FROM BROKER A, CLIENT_TRANSACTION B, OFFICE_LOCATION C, INVESTMENT I WHERE A.BROKER_ID = B.BROKER_ID AND A.OFFICE_LOCATION_ID = C.OFFICE_LOCATION_ID GROUP BY A.BROKER_ID, A.BROKER_LAST_NAME, A.BROKER_FIRST_NAME, A.YEARS_WITH_FIRM, C.OFFICE_NAME;
  • 38.
    38 Implied Cartesian select c.client_first_name, c.client_last_name, ct.action,ct.price, b.broker_last_name, b.broker_first_name, o.office_name from client_transaction ct, client c, broker b, office_location o where ct.price > 100 and b.broker_id=ct.broker_id and c.broker_id = b.broker_id and o.office_location_id = b.office_location_id
  • 39.
    39 Diagram work forMany to One What about many to many?
  • 40.
    40 Unstructured Copyright 2006 Kyle Hailey Joins OD.Order_ID= O.Order_ID O.Customer_ID = C.Customer_ID OD.Product_ID = P.Product_ID(+) OD.Shipment_ID = S.Shipment_ID(+) S.Address_ID = A.Address_ID(+) O.Status_Code = OT.Code OD.Status_Code = ODT.Code S A OD P ODT C OT O S A OD P ODT C OT O v v v v v v v v v v v v v v F F 30% 0.02%
  • 41.
    41 Many-to-One vs Many-to-Many PredicateFilter 1 2 3 B -> C -> A go to A or C? Now what?
  • 42.
    42 Adding Constraints SELECT COUNT(*) FROM b, c, a WHERE b.val2 = 100 AND a.val1 = b.id AND b.val1 = c.id; 58 logical reads alter table c add constraint c_pk unique (id); alter table b add constraint b_pk unique (id); 7 logical reads
  • 43.
    43 Join sizes Join Sizes Usethe Join sizes to determine path of least resistance
  • 44.
    44 Look at 3queries • Query 1 runs more than 24 hours • Query 2 outer joins and scalar subqueries • Query 3 create path not available to Oracle
  • 45.
    45 Query 1 :Over 24 hours to run SELECT A0.zuchinis, A0.brocoli, C0.Oranges FROM ( SELECT A1.planted_date, A1.pears, A1.zuchinis, A1.brocoli FROM FOO.A A1, ( SELECT zuchinis, brocoli FROM FOO.A A2 WHERE pears = 'M' AND planted_date + 0 >= ADD_MONTHS ((SELECT MAX (planted_date) FROM FOO.B B1 WHERE pears = 'M' ), - 11) GROUP BY zuchinis, brocoli HAVING COUNT (*) = 12 ) i2 WHERE A1.planted_date = (SELECT MAX (planted_date) FROM FOO.B B2 WHERE pears = 'M' ) AND A1.pears = 'M' AND A1.zuchinis = i2.zuchinis (+) AND A1.brocoli = i2.brocoli (+) UNION SELECT A4.planted_date, A4.pears,A4.zuchinis,A4.brocoli FROM FOO.A A4 WHERE A4.planted_date >'01-OCT-08' and A4.planted_date <'03-OCT-08' AND A4.pears = 'D' AND A4.green_beans = '1' AND NOT EXISTS (SELECT * FROM FOO.A A5 WHERE pears = 'M' AND planted_date = (SELECT MAX (planted_date) FROM FOO.B B3 WHERE pears = 'M' ) AND A4.zuchinis = A5.zuchinis AND A4.brocoli = A5.brocoli) ) b, FOO.A A0, FOO.C C0, FOO.D D0, FOO.E E0 WHERE A0.planted_date >'01-OCT-08' and A0.planted_date <'03-OCT-08' AND A0.pears = 'D' AND A0.green_beans = '1' AND A0.zuchinis = b.zuchinis AND A0.brocoli = b.brocoli AND A0.planted_date = C0.planted_date AND A0.pears = C0.pears AND A0.zuchinis = C0.zuchinis AND A0.brocoli = C0.brocoli AND A0.planted_date = D0.planted_date AND A0.pears = D0.pears AND A0.harvest_size = D0.harvest_size AND C0.Oranges = D0.Oranges AND C0.apples = D0.apples AND (D0.lemons = 0 OR D0.lemons IS NULL) AND A0.planted_date = E0.planted_date AND A0.pears = E0.pears AND A0.harvest_size = E0.harvest_size AND C0.Oranges = E0.Oranges AND C0.apples = E0.apples AND (E0.lemons = 0 OR E0.lemons IS NULL) ORDER BY A0.zuchinis, A0.brocoli;
  • 46.
  • 47.
  • 48.
    48 Comparing Plans :24 hours to 5 mins NL NL NL NL HJ HJ NL NL
  • 49.
    49 Q2 49 10/30/10 SELECT CASEWHEN M.NYC IS NULL THEN (SELECT /*+ qb_name(qb1) */ MAX (Kona) FROM foo.F WHERE harvest_date = to_date('08/10/2008','dd/mm/yyyy') AND Argentina = TRIM ('D') AND Norway = F_OUTER.Norway ELSE M.NYC END AS NYC, CASE WHEN F_OUTER.Perth IS NULL THEN NULL ELSE (SELECT /*+ qb_name(qb2) */ Georgia FROM foo.P WHERE harvest_date = to_date('08/10/2008','dd/mm/yyyy') AND Argentina = TRIM ('D') AND Paris = F_OUTER.Perth) END AS richard, CASE WHEN F_OUTER.Aruba IS NULL THEN NULL ELSE (SELECT /*+ qb_name(qb3) */ Georgia FROM foo.P WHERE harvest_date = to_date('08/10/2008','dd/mm/yyyy') AND Argentina = TRIM ('D') AND Paris = F_OUTER.Aruba) END AS Jody, CASE WHEN F_OUTER.Portland IS NULL THEN NULL ELSE (SELECT /*+ qb_name(qb4) */ Georgia FROM foo.P WHERE harvest_date = to_date('08/10/2008','dd/mm/yyyy') AND Argentina = TRIM ('D') AND Paris = F_OUTER.Portland) END AS Tom FROM foo.F F_OUTER, foo.M , foo.J , foo.N , (SELECT /*+ qb_name(qb5) */ H.SF, Oregon, H.Haiti, K.Bermuda, L.Denmark FROM (foo.H LEFT OUTER JOIN foo.K ON H.harvest_date = K.harvest_date AND H.Argentina = K.Argentina AND H.SF = K.SF AND K.Dallas = '001') LEFT OUTER JOIN FOo.L ON H.harvest_date = L.harvest_date AND H.Argentina = L.Argentina AND H.SF = L.SF WHERE H.harvest_date = to_date('08/10/2008','dd/mm/yyyy') AND H.Argentina = TRIM ('D')) extra WHERE F_OUTER.harvest_date = M.harvest_date(+) AND F_OUTER.Argentina = M.Argentina(+) AND F_OUTER.Norway = M.Norway(+) AND M.Norway(+) = M.Texas(+) AND F_OUTER.harvest_date = to_date('08/10/2008','dd/mm/yyyy') AND F_OUTER.Argentina = TRIM ('D') AND M.harvest_date(+) = to_date('08/10/2008','dd/mm/yyyy') AND M.Argentina(+) = TRIM ('D') AND F_OUTER.Norway = F_OUTER.Hawaii AND F_OUTER.harvest_date = J.harvest_date(+) AND F_OUTER.Argentina = J.Argentina(+) AND F_OUTER.Norway = J.Texas(+) AND J.harvest_date(+) = to_date('08/10/2008','dd/mm/yyyy') AND J.Argentina(+) = TRIM ('D') AND F_OUTER.Iraq = extra.SF(+) AND F_OUTER.harvest_date = N.harvest_date(+) Two important qualities: • All outer joins to F_OUTER • 4 subqueries in select select
  • 50.
  • 51.
    51 Q2 51 10/30/10 The subqueriesin the select clause look like select CASE WHEN F.f1 IS NULL THEN NULL ELSE (SELECT X.f2 FROM X WHERE code_vl = F.f1) END AS f0 from F; and should be merged into the query like: select CASE WHEN F.f1 IS NULL THEN NULL ELSE ( X.f2) END AS f0 from F , X where code_vl(+) = F.f1; select CASE WHEN F.f1 IS NULL THEN NULL ELSE (SELECT X.f2 FROM X WHERE code_vl = F.f2) END AS f0 from F; select CASE WHEN F.f1 IS NULL THEN NULL ELSE ( X.f2) END AS f0 from F , X where code_vl(+) = F.f1;
  • 52.
    52 Q3 52 10/30/10 SELECT DISTINCT* FROM FOO.a a, FOO.c c, FOO.d d, FOO.g g WHERE a.planted_date > '01-OCT-08' AND a.planted_date < '03-OCT-08' AND a.pears = 'D' AND a.green_beans = '1' AND a.planted_date = c.planted_date AND a.pears = c.pears AND a.zuchinis = c.zuchinis AND a.brocoli = c.brocoli AND a.planted_date = d.planted_date AND a.pears = d.pears AND a.harvest_size = d.harvest_size AND c.oranges = d.oranges AND c.apples = d.apples AND (d.lemons = 0 OR d.lemons IS NULL) AND a.planted_date = g.planted_date AND a.pears = g.pears AND a.harvest_size = g.harvest_size AND c.oranges = g.oranges AND c.apples = g.apples AND (g.lemons = 0 OR g.lemons IS NULL) AND a.zuchinis = '0236' AND d.apples = g.apples AND d.oranges = g.oranges ORDER BY a.zuchinis, a.brocoli;
  • 53.
  • 54.
    54 Q3 54 10/30/10 SELECT *FROM ( SELECT /*+ NO_MERGE */ c.apples, c.oranges, a.harvest_size FROM a, c WHERE a.planted_date = TO_DATE ('02/10/2008', 'dd/mm/yyyy') AND a.pears = 'D' AND a.green_beans = '1' AND a.planted_date = c.planted_date AND a.pears = c.pears AND a.zuchinis = c.zuchinis AND a.brocoli = c.brocoli AND a.zuchinis = '0236' ) X, ( SELECT /*+ NO_MERGE */ d.apples, d.oranges, d.harvest_size FROM d, g WHERE d.planted_date = TO_DATE ('02/10/2008', 'dd/mm/yyyy') AND g.planted_date = TO_DATE ('02/10/2008', 'dd/mm/yyyy') AND g.apples = d.apples AND d.oranges = g.oranges AND d.pears = 'D' AND g.pears = 'D' AND g.pears = d.pears AND g.harvest_size = d.harvest_size AND (d.lemons = 0 OR d.lemons IS NULL) AND (g.lemons = 0 OR g.lemons IS NULL) ) Y WHERE X.oranges = Y.oranges AND X.apples = Y.apples AND X.harvest_size = Y.harvest_size; This final version runs in elapsed 0.33 secs and 12K logical reads down from an original elapsed 4.5 secs and 1M logical reads
  • 55.
    55 What tools touse to create VST diagrams? • Paper – Modifications messy and difficult • PowerPoint – Can move things around – Sticky connectors – Easy to modify • DB Optimizer – Automatic and still modifiable
  • 56.
    56 Visual SQL Tuning(VST) Table Sizes Join Sizes Filter Ratios Exists
  • 57.
    57 VST Steps Summary 1.Diagramtables 2.Draw connectors for each join 3.Calculate filter ratios 4.Find the table sizes 5.Calculate two table join sizes Execution Path • Start at the most selective join filter • Join to keep the running result set size small Many to Many relationships = problems 57 10/30/10 Parent Child Parent Child F F 30% 0.02% S A OD P ODT C OT O
  • 58.
    58 Copyright 2006 Kyle Hailey DoYou Want? Engineering Data? Engineering Data?
  • 59.
    59 Copyright 2006 Kyle Hailey DoYou Want? Pretty Pictures Pretty Pictures
  • 60.
    60 Copyright 2006 Kyle Hailey DoYou Want? Clean and Clear Clean and Clear ? ? ? ? ? ?
  • 61.
    61 Copyright 2006 Kyle Hailey ImagineTrying to Drive your Car And is updated once and hour And is updated once and hour Or would you like it to look … Would you want your dashboard to look like :
  • 62.
  • 63.
    63 Summary 1.Database - AAS –Profile database – Use wait interface and graphics – Identify machine, application, database or SQL 1.SQL - VST – Indexes, stats, execution path – Visual SQL Tuning
  • 64.
    64 Bibliography http://www.simple-talk.com/sql/performance/designing-efficient-sql-a-visual-approach/ Refactoring SQL Applications– Stephane Faroult Troubleshooting Oracle Performance – Christian Antognini SQL Tuning – Dan Tow Cost-Based Oracle Fundamentals – Jonathan Lewis
  • 65.
    65 Visual SQL Tuning(VST) Industry Exclusive
  • 66.
    66 DB Optimizer XEKey Features Profile Tune Load Test SQL IDE
  • 67.
    67 DB Optimizer XEKey Features Profile Tune Load Test SQL IDE
  • 68.
    68 DB Optimizer XEKey Features Profile Tune Load Test SQL IDE
  • 69.
    69 DB Optimizer XEKey Features Profile Tune Load Test SQL IDE
  • 70.
    70 Review of Functionality Profile Tune LoadTest SQL IDE Only tool on the market with these features integrated
  • 71.
  • 72.
    72 Appendix • Diagramming – Simplejoins and inline views – Outer joins – Exists/not exists (in/not in) – Correlated aggregate sub-queries • Hints – LEADING – USE_NL – USE_HASH – INDEX – NO_MERGE • Execution Order • Machine Health • VST method with Statistics
  • 73.
    73 Basic Joins Many to singlevalue Cartesian Cartesian Safe Dangerous M
  • 74.
    74 Simple queries andsub-queries 74 A B select * from A, B where b.f1=a.f1 Non-correlated sub-query select * from A,(select b.f1 from B) c where c.f1=a.f1 Simple join select * from A where a.f1 = (select max(b.f1) from B ) Special case: non correlated sub-query returns one row A B A B A B Unique index on b.f1 No unique indexes Unique index on Both b.f1 and a.f1 M
  • 75.
  • 76.
    76 Correlated scalar sub-queries 7610/30/10 Correlated aggregate subquery: select ename from emp a where a.sal > (select avg(sal) from emp b where a.deptno=b.deptno) A B Scalar Subqueries select ename, (select avg(sal) from emp b where a.deptno=b.deptno) from emp a;
  • 77.
    77 Exists and NotIn 77 10/30/10 SELECT d.* FROM dept d WHERE exists ( SELECT null FROM emp e WHERE e.deptno=d.deptno); SELECT d.* FROM dept d WHERE d.deptno in ( SELECT deptno FROM emp e ); select distinct d.* from dept1 d ,emp e where e.deptno = d.deptno; SELECT d.* FROM dept d WHERE not exists ( SELECT null FROM emp e WHERE e.deptno=d.deptno); SELECT d.* FROM dept d WHERE d.deptno not in ( SELECT deptno FROM emp e where e.deptno is not null ) or d.deptno is null; select d.* from dept1 d left outer join emp e on e.deptno = d.deptno where e.deptno is null; E N
  • 78.
    78 HINTS • ORDERED -good on 9i • Leading(tab_alias , table_alias … ) – 10g format • USE_NL(table_alias) – Inner Table (not driving) • USE_HASH(table_alias) – 2cd table, probe into • INDEX(tab_alias index_name) • NO_MERGE Oracle first decides join order then join type (example http://www.adp-gmbh.ch/blog/2008/01/17.php) 78 10/30/10
  • 79.
    79 Visual SQL Tuning(VST) diagrams 79 10/30/10 HJ NL i io HJ NL Makes comparison of execution plans easy Better yet, it will help us find the best execution path
  • 80.
  • 81.
    81 i MJ HJ Bad Plans vsGood Plan 81 10/30/10 HJ NL
  • 82.
    82 Comparing Plans :24 hours to 5 mins NL NL NL NL HJ HJ NL NL
  • 83.
    83 When to Tune 1.Machine a) CPU • Response times skewed • 100% CPU might be fine • Users wait in queue (run queue) => machine underpowered a) Memory • Paging • Wait times skewed (ex : latch free) • Erratic response times ( ex : ls ) 1. Oracle 1) Waits > CPU ? • tune waits 1) CPU > 100% ? • tune top CPU SQL 1) Else • It’s the application Oracle Load (AAS) Top Session Top Wait Top SQL SQL Detail Session Detail File Detail Object Detail Wait Detail Host AAS > #CPU AAS > 1 Waits > CPU CPU > Waits CPU Memory
  • 84.
    84 Machine Make sure themachine is healthy before tuning Oracle • CPU => use run queue, < 2 * #CPU • Memory => page out VMSTAT
  • 85.
    85 Summary 1.Machine - vmstat –Memory, CPU (we can see IO response in Oracle) 1.Database - AAS – Use wait interface and graphics – Identify machine, application, database or SQL 1.SQL - VST – Indexes, stats, execution path – Visual SQL Tuning
  • 86.
    86 Solution to Manyto Many Table Sizes Filter Ratios Join Sizes
  • 87.
    87 VST Steps Objects: 1. Tables: drawn as nodes 2. Joins : drawn as connector lines 3. Filters : mark on each table with filter in where clause Statistics: 1.Table sizes 2. Join sizes 3. Calculate filter percentages – filter ratio = number of rows returned with filter / number of rows 87 10/30/10
  • 88.
    88 Google Directions • Comparetwo sets of directions • (optionally show graphical set of directions) • Show map • Show map with traffic flow, read, yellow, green
  • 89.
    89 How Can WeOpen the Black Box? OEM ASHMON/SASH DB Optimizer •Powerful - Identifies issues quickly and powerfully •Interactive - Allows exploring the data •Easy - Understandable by everyone, DBA, Dev and Managers !
  • 90.
    90 Copyright 2006 Kyle Hailey Clearer 1.Include successes 2. Remove Irrelevant 3. Normalize same temp 4. Scale known vs unknown 55 65 75 60 70 80 4 8 12 4 8 12 30 40 50 35 45 X