2007-11-251
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning
Tamilselvan G
B
e
a
c
o
n
I
n
f
o
t
e
c
h
C
o
r
p
o
r
a
t
i
o
n
C
l
a
s
s
-
4
2007-11-252
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning
Index
1. Aggregate Functions
Rollup
Cube
2 Analytic Functions
ROW_NUMBER SUM
RANK FIRST_VALUE
DENSE_RANK LAST_VALUE
COUNT Ratio_To_Report
LEAD LAG
NTILE AVG
3. Most Influential Init.ora Parameters
OPTIMIZER_INDEX_CACHING
OPTIMIZER_INDEX_COST_ADJ
2007-11-253
Beacon Infotech Corporation
www.oracleact.com
Overview of Rollup and Cube
Rollup Details:
ROLLUP's action is straightforward: it creates subtotals which "roll up" from the most
detailed level to a grand total, following a grouping list specified in the ROLLUP clause.
ROLLUP takes as its argument an ordered list of grouping columns. First, it calculates
the standard aggregate values specified in the GROUP BY clause. Then, it creates
progressively higher-level subtotals, moving from right to left through the list of grouping
columns. Finally, it creates a grand total.
CUBE Details:
CUBE takes a specified set of grouping columns and creates subtotals for all possible
combinations of them. In terms of multi-dimensional analysis, CUBE generates all the
subtotals that could be calculated for a data cube with the specified dimensions. If you
have specified CUBE(col1, col2, col3 ), the result set will include all the values that would
be included in an equivalent ROLLUP statement plus additional combinations.
Both the functions were introduced in Oracle 8.1.5
Oracle Performance Tuning 1. Rollup and Cube
2007-11-254
Beacon Infotech Corporation
www.oracleact.com
Difference between Rollup and Cube
Oracle Performance Tuning 1. Rollup and Cube
SQL> select decode(grouping(state),1,'ALL STATES',STATE),
2 decode(grouping(product),1,'ALL PRODUCTS',PRODUCT),
3 SUM(SALES)
4 from abc_sales group by rollup(state,product)
SQL> /
DECODE(GRO DECODE(GROUP SUM(SALES)
---------- ------------ ----------
FL TV 200
FL COMP 220
FL PHONE 20
FL ALL PRODUCTS 440
GA TV 100
GA COMP 200
GA PHONE 70
GA ALL PRODUCTS 370
ALL STATES ALL PRODUCTS 810
9 rows selected.
SQL> select * from abc_sales;
SDATE ST PRODUCT SALES
-------------------- -- ---------- ----------
07-MAY-2006 21:27:18 GA TV 100
06-MAY-2006 21:27:18 GA PHONE 40
05-MAY-2006 21:27:18 GA PHONE 30
05-MAY-2006 21:27:18 GA COMP 200
04-MAY-2006 21:27:18 FL TV 200
02-MAY-2006 21:27:18 FL PHONE 20
03-MAY-2006 21:27:18 FL COMP 220
7 rows selected.
2007-11-255
Beacon Infotech Corporation
www.oracleact.com
Difference between Rollup and Cube
Oracle Performance Tuning 1. Rollup and Cube
SQL> select decode(grouping(state),1,'ALL STATES',STATE),
2 decode(grouping(product),1,'ALL PRODUCTS',PRODUCT),
3 SUM(SALES)
4 from abc_sales group by cube(state,product)
SQL> /
DECODE(GRO DECODE(GROUP SUM(SALES)
---------- ------------ ----------
ALL STATES ALL PRODUCTS 810
ALL STATES TV 300 ------- Extra row
ALL STATES COMP 420 ------- Extra row
ALL STATES PHONE 90 ------- Extra row
FL ALL PRODUCTS 440
FL TV 200
FL COMP 220
FL PHONE 20
GA ALL PRODUCTS 370
GA TV 100
GA COMP 200
GA PHONE 70
12 rows selected.
In cube, we will
get the total of
2
nd
columns
used in the
cube function.
2007-11-256
Beacon Infotech Corporation
www.oracleact.com
Rollup Example
Oracle Performance Tuning 1. Rollup and Cube
SQL> select * from cust_order where rownum < 10;
ORDER_ID ORDER_DAT CUST_ID ORDER_QTY SUPPLIED_QTY ORDER_MESS
---------- --------- ---------- ---------- ------------ ----------
1 18_JAN-05 1001 16 5 X
2 17_JAN-05 1001 14 5 X
3 01_JAN-02 1001 20 5 X
4 01_JAN-03 1001 15 5 X
5 01_JAN-04 1001 12 5 X
6 01_JAN-02 1001 17 5 X
7 12_JAN-05 1001 10 5 X
8 01_JAN-03 1001 16 5 X
9 01_JAN-02 1001 13 5 X
..
SQL> select count(*) from cust_order ;
COUNT(*)
----------
127,791
SQL> select table_name, blocks, avg_row_len from user_tables
where table_name like 'CUS%' ;
TABLE_NAME BLOCKS AVG_ROW_LEN
------------------------------ ---------- -----------------------
CUSTOMER 1 19
CUST_ORDER 14200 729
SQL> DESC CUSTOMER
Name Null? Type
-------------------------- -------------- ------------------
CUST_ID NOT NULL NUMBER(38)
CUST_FNAME VARCHAR2(20)
CUST_LNAME VARCHAR2(20)
SQL> select * from customer;
CUST_ID CUST_FNAME CUST_LNAME
---------- -------------------- --------------------
1001 SCOTT TOM
1002 PETER DAVID
1003 ELLISON BOBBY
SQL> DESC CUST_ORDER
Name Null? Type
-------------------------- -------- ------------------
ORDER_ID NUMBER(38)
ORDER_DATE DATE
CUST_ID NUMBER(38)
ORDER_QTY NUMBER(38)
SUPPLIED_QTY NUMBER(38)
ORDER_MESS CHAR(700)
2007-11-257
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 1. Rollup and Cube
select *
from ( select /*+ ordered */
cust_fname, cust_lname, to_char(b.cust_id) as cust,
sum(order_qty) ord_tot, sum(supplied_qty) ord_supp
from cust_order a, customer b
where b.cust_id = a.cust_id
group by cust_fname, cust_lname, to_char(b.cust_id)
UNION
select /*+ Ordered */ '', '', 'Report Total' as cust,
sum(order_qty) ord_tot, sum(supplied_qty) ord_supp
from cust_order a, customer b
where b.cust_id = a.cust_id
)
order by 1 NULLS LAST
CUST_FNAME CUST_LNAME CUST ORD_TOT ORD_SUPP
-------------------- -------------------- ----------------- ---------- ----------
ELLISON BOBBY 1003 639105 127791
PETER DAVID 1002 638318 170388
SCOTT TOM 1001 639977 212985
Report Total 1917400 511164
# of LIO = 28,409 Elapsed Time = 1.49 Seconds
S
Q
L
W
I
T
H
O
U
T
R
O
L
L
U
P
2007-11-258
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 1. Rollup and Cube
select *
From (
select decode(grouping(cust_fname),1, '*All First Name', cust_fname) FNAME,
decode(grouping(cust_lname),1, '*All Last Name', cust_lname) LNAME,
decode(grouping(b.cust_id), 1, '*Report Total', b.cust_id) custid,
sum(order_qty) ord_tot,
sum(supplied_qty) ord_supp
from cust_order a, customer b
where b.cust_id = a.cust_id
group by rollup(cust_fname, cust_lname, b.cust_id)
) c
where (c.custid = '*Report Total' and
c.lname = '*All Last Name' and
c.fname = '*All First Name' ) OR
(c.custid != '*Report Total' )
FNAME LNAME CUSTID ORD_TOT ORD_SUPP
-------------------- -------------------- --------------- ---------- ----------
PETER DAVID 1002 638318 170388
SCOTT TOM 1001 639977 212985
ELLISON BOBBY 1003 639105 127791
*All First Name *All Last Name *Report Total 1917400 511164
# of LIO = 14,474 Elapsed Time = 0.70 Seconds
S
Q
L
W
I
T
H
R
O
L
L
U
P
Even though
I reduced the
elapsed time
by half, I am
not satisfied.
Can any one
further
reduce the
elapsed time
by half?
2007-11-259
Beacon Infotech Corporation
www.oracleact.com
Overview of Analytic Functions
One of the coolest things happened in Oracle 8.1.6 was the introduction
of Analytic Function.
Prior to Oracle 8.1.6, Developers wrote complex SQL statements for some
of the following reports:
1. TOP-N Sales Reps by States
2. Ratio to Total
3. Moving Average (Moving Window calculation)
4. Accessing previous and next rows in a group
5. First/Last Row within a Group (Window)
6. Ranking and Percentile
7. Liner Regression Statistics
With the help of new Analytic Functions, today we can write more
scalable application code that not only outperform the old SQL code,
but also solve complex business requirements.
Oracle Performance Tuning 2. Analytic Functions
2007-11-2510
Beacon Infotech Corporation
www.oracleact.com
How it works
Oracle Performance Tuning 2. Analytic Functions
Joins, WHERE, GROUP BY and Having
Partitions Created;
Analytic Function applied for each row on
each partition
Final ORDER BY
Example: Slicing the rows into 4 groups
select state, sale_amt, ntile(4) over (order by sum(sale_amt)) ntile4
from ana_sales
group by state, sale_amt
/
Output is:
ST SALE_AMT NTILE4
-- ---------- ----------
AL 0 1
FL 10 1
NY 80 1
GA 100 1
NY 120 2
GA 200 2
FL 220 2
GA 300 2
FL 330 3
GA 400 3
FL 450 3
GA 500 3
FL 510 4
NY 910 4
NY 730 4
15 rows selected.
Processing Order
2007-11-2511
Beacon Infotech Corporation
www.oracleact.com
How it works
Oracle Performance Tuning 2. Analytic Functions
Syntax : Analytic_Function(argument1, argument2.)
OVER ( PARTITION clause ORDER BY clause WINDOW clause)
Window Clause
2007-11-2512
Beacon Infotech Corporation
www.oracleact.com
How it works
Oracle Performance Tuning 2. Analytic Functions
Where
Analytic_Function is the name of the function such MIN, MAX,ROW_NUMBER, RANK,
DENSE_RANK etc.
Arguments can be 0,1,2,3. (No more than 3 arguments is allowed. )
query_partition_clause
Use the PARTITION BY clause to partition the query result set into groups based on one or more
value_expr. If you omit this clause, then the function treats all rows of the query result set as a
single group.
Order_by_clause
Use the order_by_clause to specify how data is ordered within a partition. For all analytic functions
except PERCENTILE_CONT and PERCENTILE_DISC (which take only a single key), you can order
the values in a partition on multiple keys, each defined by a value_expr and each qualified by an
ordering sequence.
Within each function, you can specify multiple ordering expressions. Doing so is especially useful
when using functions that rank values, because the second expression can resolve ties between
identical values for the first expression.
2007-11-2513
Beacon Infotech Corporation
www.oracleact.com
How it works
Oracle Performance Tuning 2. Analytic Functions
windowing_clause
Some analytic functions allow the windowing_clause.
ROWS | RANGE These keywords define for each row a window (a physical or logical set of rows)
used for calculating the function result. The function is then applied to all the rows in the window.
The window moves through the query result set or partition from top to bottom.
ROWS specifies the window in physical units (rows).
RANGE specifies the window as a logical offset.
You cannot specify this clause unless you have specified the order_by_clause. Some window
boundaries defined by the RANGE clause let you specify only one expression in the
order_by_clause.
The value returned by an analytic function with a logical offset is always deterministic. However,
the value returned by an analytic function with a physical offset may produce nondeterministic
results unless the ordering expression results in a unique ordering. You may have to specify
multiple columns in the order_by_clause to achieve this unique ordering.
BETWEEN ... AND Use the BETWEEN ... AND clause to specify a start point and end point for the
window. The first expression (before AND) defines the start point and the second expression (after
AND) defines the end point.
If you omit BETWEEN and specify only one end point, then Oracle considers it the start point, and the end
point defaults to the current row.
2007-11-2514
Beacon Infotech Corporation
www.oracleact.com
How it works
Oracle Performance Tuning 2. Analytic Functions
windowing_clause
UNBOUNDED PRECEDING Specify UNBOUNDED PRECEDING to indicate that the window starts at
the first row of the partition. This is the start point specification and cannot be used as an end point
specification.
UNBOUNDED FOLLOWING Specify UNBOUNDED FOLLOWING to indicate that the window ends at
the last row of the partition. This is the end point specification and cannot be used as a start point
specification.
CURRENT ROW As a start point, CURRENT ROW specifies that the window begins at the current
row or value (depending on whether you have specified ROW or RANGE, respectively). In this case
the end point cannot be value_expr PRECEDING.
As an end point, CURRENT ROW specifies that the window ends at the current row or value
(depending on whether you have specified ROW or RANGE, respectively). In this case the start
point cannot be value_expr FOLLOWING.
value_expr PRECEDING or value_expr FOLLOWING For RANGE or ROW:
If value_expr FOLLOWING is the start point, then the end point must be value_expr FOLLOWING.
If value_expr PRECEDING is the end point, then the start point must be value_expr PRECEDING.
If you are defining a logical window defined by an interval of time in numeric format, then you may
need to use conversion functions.
2007-11-2515
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
FAQ
Frequently asked questions are:
How can I get TOP-N rows by some set of columns?
How can I get 2
nd
highest paid sales rep in our company?
How can I print total of the report along with each row?
When analytic functions were not available, these questions were
difficult to answer.
Now, Analytic Functions can answer all types of those questions
very easily.
2007-11-2516
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.1 TOP-N Rows --- Understand the question clearly.
Consider the following request:
ABC corporation had many sales reps in many states and wanted to give bonus to its
top 3 sales reps by state.
This is a ambiguous question because of repeated values, there may be 4 or 5 Sales
Reps who all made same figures. In that situation what shall the developer do?
I can come out with many interpretations with this request:
1. What Shall I do if all the reps in a state made 0 sales? Can I include those guys in
the report?
2. List out set of sales reps who made the top 3 sales by state
3. List out up to 3 people who made the top sales. If 4 or more reps happen to make
the largest sales, the answer would be no rows. If 2 reps make the highest sales
and 2 reps make the same second highest, the answer will be only 2 reps
(highest). Or does the ABC Corp want all 4 reps?
4. Sort the sales reps by salary from greatest to lowest with in a state. List out the
first 3 reps (or less if less than 3 reps work in a state).
2007-11-2517
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.1 TOP-N Rows --- Case 1
What Shall I do if all the reps in a state made 0 sales?
I need to know before I start writing a SQL statement. So, let us worry about it now.
1.1 TOP-N Rows - Case 2 List out set of
sales reps who made the top 3
sales by state
Let us build the table.
SQL> desc ana_sales
Name Null? Type
------------------- -------- --------------
STATE CHAR(2)
ENAME VARCHAR2(10)
SALE_AMT NUMBER(6,2)
SOMETXT1 VARCHAR2(3000)
SOMETXT2 VARCHAR2(3000)
SQL> SELECT STATE, ENAME, SALE_AMT FROM ANA_SALES;
ST ENAME SALE_AMT
-- ---------- ----------
GA Tamil 100
GA Tom 200
GA Scott 300
GA Veera 400
GA Kumar 500
FL Bush 10
FL Gore 220
FL Ellison 330
FL Gates 450
FL Ravi 510
NY Alex 80
NY Mike 120
NY Lux 730
NY Mary 730
NY Kristine 910
AL Ann 0
AL Arasu 0
AL Ram 0
AL Gopi 0
19 rows selected.
2007-11-2518
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.1 TOP-N Rows --- Case 2
SQL> get top-1
1 select *
2 from (select state, ename, sale_amt,
3 dense_rank()
4 over ( partition by state
5 order by sale_amt desc) dr
6 from ana_sales
7 where sale_amt > 0 )
8 where dr
2007-11-2519
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.1 TOP-N Rows --- Case 3
List out up to 3 people who made the top sales. If 4 or more reps happen to make
the largest sales, the answer would be no rows. If 2 reps make the highest sales
and 2 reps make the same second highest, the answer will be only 2 reps
(highest). Or does the ABC Corp want all 4 reps?
SQL> get top-3
1 select *
2 from (select state, ename, sale_amt,
3 count(*)
4 over ( partition by state
5 order by sale_amt desc
6 range unbounded preceding) cnt
7 from ana_sales
8 where sale_amt > 0 )
9 where cnt
2007-11-2520
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.1 TOP-N Rows --- Case 4
Sort the sales reps by salary from greatest to lowest with in a state. List
out the first 3 reps (or less if less than 3 reps work in a state).
I updated the sale_amt to 500 for all guys in NY state and see what we get .
SQL> get top-4
1 select *
2 from (select state, ename, sale_amt,
3 row_number()
4 over ( partition by state
5 order by sale_amt desc
6 ) rn
7 from ana_sales
8 where sale_amt > 0 )
9 where rn
2007-11-2521
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.2 ROWNUM , RANK , and DENSE_RANK
SQL> select state, ename, sale_amt,
2 dense_rank() over ( partition by state order by sale_amt desc) dr ,
3 rank() over ( partition by state order by sale_amt desc) ra ,
4 row_number() over ( partition by state order by sale_amt desc) rn
5* from ana_sales where sale_amt > 0
6 /
ST ENAME SALE_AMT DR RA RN
-- ---------- ---------- ------- ------ --------
FL Ravi 510 1 1 1
FL Gates 450 2 2 2
FL Ellison 330 3 3 3
FL Gore 220 4 4 4
FL Bush 10 5 5 5
GA Kumar 500 1 1 1
GA Veera 400 2 2 2
GA Scott 300 3 3 3
GA Tom 200 4 4 4
GA Tamil 100 5 5 5
NY Lux 500 1 1 1
NY Mary 500 1 1 2
NY Kristine 500 1 1 3
NY Alex 300 2 4 4
NY Mike 300 2 4 5
15 rows selected.
The difference between RANK
and DENS_RANK:
RANK will skip number if
repeated values are found
within a group.
Dense_Rank will assign
continuous number.
2007-11-2522
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.3 LAG & LEAD - Accessing Previous row and next row
Most useful analytic functions.
SQL> select rdate, faren,
2 lag(faren) over(order by rdate ) lag,
3 lead(faren) over(order by rdate ) lead
4 from ana_lag_lead
5* order by rdate
SQL> /
RDATE FAREN LAG LEAD
-------------------- ------ ---- -----
07-MAY-2006 00:00:00 55 56
08-MAY-2006 00:00:00 56 55 52
09-MAY-2006 00:00:00 52 56 53
10-MAY-2006 00:00:00 53 52 59
11-MAY-2006 00:00:00 59 53 50
12-MAY-2006 00:00:00 50 59 52
13-MAY-2006 00:00:00 52 50 51
14-MAY-2006 00:00:00 51 52 45
15-MAY-2006 00:00:00 45 51
9 rows selected.
SQL> select * from ana_lag_lead ;
RDATE FAREN
-------------------- ------
07-MAY-2006 00:00:00 55
08-MAY-2006 00:00:00 56
09-MAY-2006 00:00:00 52
10-MAY-2006 00:00:00 53
11-MAY-2006 00:00:00 59
12-MAY-2006 00:00:00 50
13-MAY-2006 00:00:00 52
14-MAY-2006 00:00:00 51
15-MAY-2006 00:00:00 45
9 rows selected.
2007-11-2523
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.4 AVG and RANGE Average Most useful analytic functions.
SQL> select rdate, price,
2 avg(price) over(order by rdate RANGE between 1 preceding and 1 following) range_avg,
3 avg(price) over(order by rdate ROWS between 2 preceding and 2 following) rows_avg,
4 sum(price) over(order by rdate ROWS UNBOUNDED PRECEDING) CUM_SUM
5 from GOLD_PRICE
6* order by rdate
SQL> /
RDATE PRICE RANGE_AVG ROWS_AVG CUM_SUM
-------------------- ---------- --------- -------- ----------
07-MAY-2006 00:00:00 720 725.00 736.67 720
08-MAY-2006 00:00:00 730 736.67 757.50 1450
09-MAY-2006 00:00:00 760 770.00 760.00 2210
10-MAY-2006 00:00:00 820 783.33 780.00 3030
11-MAY-2006 00:00:00 770 803.33 786.00 3800
12-MAY-2006 00:00:00 820 783.33 788.00 4620
13-MAY-2006 00:00:00 760 783.33 772.00 5380
14-MAY-2006 00:00:00 770 756.67 772.50 6150
15-MAY-2006 00:00:00 740 755.00 756.67 6890
9 rows selected.
2007-11-2524
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.5 FIRST_VALUE and LAST_VALUE
The following example illustrates the use of LAST_VALUE function:
select emplid, pay_date,
last_value(pay_date) over
(partition by emplid
order by emplid, pay_date
rows between CURRENT ROW AND UNBOUNDED FOLLOWING) AS lv
from t1 order by emplid, pay_date;
EMPLID PAY_DATE LV
A1 31-JAN-2000 31-MAY-2000
A1 28-FEB-2000 31-MAY-2000
A1 31-MAR-2000 31-MAY-2000
A1 31-MAY-2000 31-MAY-2000
B1 31-JAN-2000 31-JUL-2000
B1 31-MAR-2000 31-JUL-2000
B1 31-JUL-2000 31-JUL-2000
C1 31-JAN-2000 31-DEC-2000
C1 28-FEB-2000 31-DEC-2000
C1 31-MAR-2000 31-DEC-2000
C1 31-DEC-2000 31-DEC-2000
D1 31-JAN-2000 31-OCT-2000
D1 31-MAR-2000 31-OCT-2000
D1 31-OCT-2000 31-OCT-2000
SELECT * FROM T1 ;
EMPLID PAY_DATE
--------------- -----------
A1 31-JAN-2000
A1 28-FEB-2000
A1 31-MAR-2000
A1 31-MAY-2000
B1 31-JAN-2000
B1 31-MAR-2000
B1 31-JUL-2000
C1 31-JAN-2000
C1 28-FEB-2000
C1 31-MAR-2000
C1 31-DEC-2000
D1 31-JAN-2000
D1 31-MAR-2000
D1 31-OCT-2000
14 rows selected.
2007-11-2525
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.6 Ratio To Report
SELECT PRODUCT, SALES ,
TO_CHAR((RATIO_TO_REPORT(SALES) OVER())*100,999.99)
AS SALES_PER
FROM SALES ;
PRODUCT SALES SALES_PER
-------------------- ---------- -------
P1 280 16.67
P2 400 23.81
P3 200 11.90
P4 300 17.86
P5 190 11.31
P6 310 18.45
SQL>DESC SALES
Name Null? Type
------------ -------- ---------------------
PRODUCT VARCHAR2(20)
SALES NUMBER
SQL>SELECT * FROM SALES ;
PRODUCT SALES
-------------------- ----------
P1 280
P2 400
P3 200
P4 300
P5 190
P6 310
2007-11-2526
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.6 Some Practical Example - Getting 3 consecutive rows
MIKE 15-JUN-2005 00:00:00 CHEMISTRY 30
MIKE 15-JUL-2005 00:00:00 CHEMISTRY 20
MIKE 15-AUG-2005 00:00:00 CHEMISTRY 35
MIKE 15-SEP-2005 00:00:00 CHEMISTRY 26
MIKE 15-OCT-2005 00:00:00 CHEMISTRY 72
MIKE 15-NOV-2005 00:00:00 CHEMISTRY 40
MIKE 15-DEC-2005 00:00:00 CHEMISTRY 50
21 rows selected.
School Policy:
The principal of a school declared that
any student scored less than 40 in 3
consecutive months would be declared
Failed in that academic year. He asked
the teacher to prepare a list of students.
SQL> select * from marks;
NAME TEST_DATE SUBJECT MARKS
---------- -------------------- --------- ----------
DAVID 15-JUN-2005 00:00:00 CHEMISTRY 60
DAVID 15-JUL-2005 00:00:00 CHEMISTRY 30
DAVID 15-AUG-2005 00:00:00 CHEMISTRY 35
DAVID 15-SEP-2005 00:00:00 CHEMISTRY 36
DAVID 15-OCT-2005 00:00:00 CHEMISTRY 62
DAVID 15-NOV-2005 00:00:00 CHEMISTRY 50
DAVID 15-DEC-2005 00:00:00 CHEMISTRY 40
SCOTT 15-JUN-2005 00:00:00 CHEMISTRY 60
SCOTT 15-JUL-2005 00:00:00 CHEMISTRY 70
SCOTT 15-AUG-2005 00:00:00 CHEMISTRY 45
SCOTT 15-SEP-2005 00:00:00 CHEMISTRY 66
SCOTT 15-OCT-2005 00:00:00 CHEMISTRY 62
SCOTT 15-NOV-2005 00:00:00 CHEMISTRY 30
SCOTT 15-DEC-2005 00:00:00 CHEMISTRY 35
2007-11-2527
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.6 Some Practical Example - Getting 3 consecutive rows using count()
1 select distinct name , subject
2 from (
3 select name, subject, test_date, marks,
4 count(fail_ind)
5 over(partition by name, subject order by test_date
6 rows between 2 preceding and current row) as preceding,
7 count(fail_ind)
8 over(partition by name, subject order by test_date
9 rows between current row and 2 following) as following
10 from (
11 select name, subject, test_date, marks,
12 (CASE when marks < 40 then 1 END ) fail_ind
13 from marks)
14 )
15 where preceding = 3 or following = 3
16 /
NAME SUBJECT
---------- ---------
DAVID CHEMISTRY
MIKE CHEMISTRY
2007-11-2528
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.6 Some Practical Example - Getting 3 consecutive rows using count()
SQL> select name, subject, test_date, marks,
2 count(fail_ind)
3 over(partition by name, subject order by test_date
4 rows between 2 preceding and current row) as preceding,
5 count(fail_ind)
6 over(partition by name, subject order by test_date
7 rows between current row and 2 following) as following
8 from (
9 select name, subject, test_date, marks,
10 (CASE when marks < 40 then 1 END ) fail_ind
11* from marks)
SQL> /
Let us see the output of the SQL statement.
2007-11-2529
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.6 Some Practical Example - Getting 3 consecutive rows using count()
NAME SUBJECT TEST_DATE MARKS PRECEDING FOLLOWING
---------- --------- --------- ---------- ---------- ----------
DAVID CHEMISTRY 15-JUN-05 60 0 2
DAVID CHEMISTRY 15-JUL-05 30 1 3
DAVID CHEMISTRY 15-AUG-05 35 2 2
DAVID CHEMISTRY 15-SEP-05 36 3 1
DAVID CHEMISTRY 15-OCT-05 62 2 0
DAVID CHEMISTRY 15-NOV-05 50 1 0
DAVID CHEMISTRY 15-DEC-05 40 0 0
MIKE CHEMISTRY 15-JUN-05 30 1 3
MIKE CHEMISTRY 15-JUL-05 20 2 3
MIKE CHEMISTRY 15-AUG-05 35 3 2
MIKE CHEMISTRY 15-SEP-05 26 3 1
MIKE CHEMISTRY 15-OCT-05 72 2 0
MIKE CHEMISTRY 15-NOV-05 40 1 0
MIKE CHEMISTRY 15-DEC-05 50 0 0
SCOTT CHEMISTRY 15-JUN-05 60 0 0
SCOTT CHEMISTRY 15-JUL-05 70 0 0
SCOTT CHEMISTRY 15-AUG-05 45 0 0
SCOTT CHEMISTRY 15-SEP-05 66 0 1
SCOTT CHEMISTRY 15-OCT-05 62 0 2
SCOTT CHEMISTRY 15-NOV-05 30 1 2
SCOTT CHEMISTRY 15-DEC-05 35 2 1
21 rows selected.
2007-11-2530
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.6 Some Practical Example - Getting 3 consecutive rows using lag and lead
1 select distinct name, subject
2 from (
3 select name, subject, test_date, marks,
4 lag(marks,1) over (partition by name, subject order by test_date) pr_marks,
5 lag(marks,2) over (partition by name, subject order by test_date) pr_to_pr_marks,
6 lead(marks,1) over (partition by name, subject order by test_date) ne_marks,
7 lead(marks,2) over (partition by name, subject order by test_date) ne_to_ne_marks
8 from marks
9 )
10 where (marks < 40 and pr_marks < 40 and pr_to_pr_marks < 40)
11 OR
12 (marks < 40 and ne_marks < 40 and ne_to_ne_marks < 40)
13 /
NAME SUBJECT
---------- ---------
DAVID CHEMISTRY
MIKE CHEMISTRY
2007-11-2531
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 2. Analytic Functions
1.7 Other Functions available
1. CUME_DIST - The CUME_DIST function (defined as the inverse of percentile in some
statistical books) computes the position of a specified value relative to a set of values. The
order can be ascending or descending. Ascending is the default. The range of values for
CUME_DIST is from greater than 0 to 1. To compute the CUME_DIST of a value x in a set S
of size N, you use the formula:
2 PERCENT_RANK - PERCENT_RANK is similar to CUME_DIST, but it uses rank values
rather than row counts in its numerator. Therefore, it returns the percent rank of a value
relative to a group of values. The function is available in many popular spreadsheets.
PERCENT_RANK of a row is calculated as:
(rank of row in its partition - 1) / (number of rows in the partition - 1)
3 Linear Regression Functions
The regression functions support the fitting of an ordinary-least-squares regression line to a set of
number pairs. You can use them as both aggregate functions or windowing or reporting
functions.
The functions are as follows:
REGR_COUNT Function , REGR_AVGY and REGR_AVGX Functions
REGR_SLOPE and REGR_INTERCEPT Functions , REGR_R2 Function
REGR_SXX, REGR_SYY, and REGR_SXY Functions
4. A LOT OF STATISTICAL Functions MEDIAN, STATS_MOD, ANOVA, COVAR, STD_DEV etc
2007-11-2532
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 3. Most Influential Init.ora Parameters
OPTIMIZER_INDEX_CACHING and OPTIMIZER_INDEX_COST_ADJ are the most important
parameters among all the init.ora parameters. The Cost based optimizer extensively uses
these 2 parameters values during the cost calculation for arriving the optimum execution
plan.
Depending upon the type of the work (OLTP, DSS , DW) , you can change these values either at the
instance level or at the session level, and the impact is highly visible.
Oracle Database Performance Tuning Guide 10g Release 2 (10.2) Part Number B14211-01
OPTIMIZER_INDEX_CACHING
This parameter controls the costing of an index probe in conjunction with a nested loop. The
range of values 0 to 100 for OPTIMIZER_INDEX_CACHING indicates percentage of index
blocks in the buffer cache, which modifies the optimizer's assumptions about index caching
for nested loops and IN-list iterators. A value of 100 infers that 100% of the index blocks are
likely to be found in the buffer cache and the optimizer adjusts the cost of an index probe or
nested loop accordingly. Use caution when using this parameter because execution plans
can change in favor of index caching.
OPTIMIZER_INDEX_COST_ADJ
This parameter can be used to adjust the cost of index probes. The range of values is 1 to 10000.
The default value is 100, which means that indexes are evaluated as an access path based on
the normal costing model. A value of 10 means that the cost of an index access path is one-
tenth the normal cost of an index access path.
2007-11-2533
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 3. Most Influential Init.ora Parameters
It is very easy to understand the impact of the first parameter, OPTIMIZER_INDEX_CACHING. It
tells the optimizer what percentage of index blocks are available in the buffer cache. And it
directly affects the cost calculation.
However, the 2nd parameter, OPTIMIZER_INDEX_COST_ADJ confuses many DBAs and
developers because the range of values accepted is 1 through 10000. Many experts interpret
the meaning in a different way. Any change in OPTIMIZER_INDEX_COST_ADJ results in
table access cost being scaled down (up) to the current value divided by 100.
In other words, I would say, if the value is less than 100, then the Optimizer may choose
indexed access path OR if the value is equal to 100 (or greater than 100), then Optimizer
may choose FULL TABLE SCAN access path.
You can also interpret the meaning in this way: low value for OPTIMIZER_INDEX_COST_ADJ
indicates single block read time is cheaper; high value for OPTIMIZER_INDEX_COST_ADJ
indicates single block read time costlier.
1.10..20..30....100200..50010004000.800010000
Note:
If OPTIMIZER_INDEX_CACHING is for index blocks, then
OPTIMIZER_INDEX_COST_ADJ is for table blocks available in the buffer cache.
2007-11-2534
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 3. Most Influential Init.ora Parameters
SQL> desc state
Name Null? Type
--------------------- -------- ------------------
STATEID NOT NULL CHAR(2)
NAME VARCHAR2(30)
SOMETXT VARCHAR2(3900)
SQL> select stateid, name from state ;
ST NAME
-- ------------------------------
GA Georgia
CA California
NY Newyork
AL Alabama
TX Texas
MA Massachucsetts
SC South Carolina
NC North Carolina
AZ Arizona
9 rows selected. ------------ Small Table to filter rows
based on the STATE code
Note: All the tests are done in 9i. You may get different
execution plans in your system because the cost is
affected by many parameters settings.
Among the 2 parameters, Optimizer_Index_Cost_Adj is
more aggressive than OPIMIZER_INDEX_CACHING.
First let us set up 2 tables to test the theory.
SQL> desc sales
Name Null? Type
----------------- -------- ------------------
CUST_ID NOT NULL NUMBER(12)
STATE NOT NULL CHAR(2)
SALE_YEAR NUMBER(4)
SALE_MONTH NUMBER(2)
PROD_ID NUMBER
QTY NUMBER
AMT NUMBER
COMM_1 VARCHAR2(50)
COMM_2 VARCHAR2(200)
SQL> select /*+ full(a) parallel(a,16) */ count(*) from sales a ;
COUNT(*)
----------
14,336,064 ----------- Big table to test different values.
2007-11-2535
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 3. Most Influential Init.ora Parameters
Case 1
Let us first see what will be the cost for a query with default values of 0 and 100 for
optimizer_index_caching and optimizer_index_cost_adj respectively.
SQL> alter session set optimizer_index_caching = 0;
Session altered.
SQL> alter session set optimizer_index_cost_adj = 100 ;
Session altered.
SQL> explain plan for
2 select a.cust_id , b.name
3 from sales a, state b
4 where a.state = b.stateid and b.stateid = 'GA' ;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 573K | 15M | 45551 |
| 1 | NESTED LOOPS | | 573K | 15M | 45551 |
| 2 | TABLE ACCESS BY INDEX ROWID | STATE | 1 | 21 | 1 |
|* 3 | INDEX UNIQUE SCAN | STATE_PK | 1 | | |
|* 4 | TABLE ACCESS FULL | SALES | 573K | 4480K | 45550 |
---------------------------------------------------------------------------------------------------------------------
So, the total cost
of the query is
45,551 IO. Note
also that when
CPU costing is
off, then the
COST is nothing
but total number
of IO.
This is our base
line data that will
be compared
with the
remaining tests.
2007-11-2536
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 3. Most Influential Init.ora Parameters
Case 2
I changed the OPTIMIZER_INDEX_COST_ADJ to 10 but kept the default value for OPTIMIZER_INDEX_CACHING.
SQL> alter session set optimizer_index_caching = 0 ;
Session altered.
SQL> alter session set optimizer_index_cost_adj = 10 ;
Session altered.
SQL> explain plan for
select a.cust_id , b.name from sales a, state b
where a.state = b.stateid and b.stateid = 'GA' ;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 573K| 15M | 37683 (1) |
| 1 | NESTED LOOPS | | 573K| 15M | 37683 (1) |
| 2 | TABLE ACCESS BY INDEX ROWID | STATE | 1 | 21 | 2 (50) |
|* 3 | INDEX UNIQUE SCAN | STATE_PK | 1 | | |
| 4 | TABLE ACCESS BY INDEX ROWID | SALES | 573K | 4480K | 37682 (1) |
|* 5 | INDEX RANGE SCAN | SALES_IDX_2 | 573K | | 30095 (0) |
------------------------------------------------------------------------------------------------------------------------------------------
The Query plan is completely changed from full table scan to indexed access on the SALES
table. The total cost of the query came down to 37,683 from 45,551, the TABLE ACCESS BY
INDEX ROWID cost is 37,682 that includes the cost of INDEX RANGE SCAN for
SALES_IDX_2 30,095.
2007-11-2537
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 3. Most Influential Init.ora Parameters
Case 3
In real life situation some amount of index leaf blocks are always cached in the
memory.
Now I tell Oracle that 50 % of index blocks are cached in the SGA by changing the
OPTIMIZER_INDEX_CACHING parameter.
SQL> alter session set optimizer_index_caching = 50 ;
Session altered.
SQL> alter session set optimizer_index_cost_adj = 10 ;
Session altered.
SQL> explain plan for
2 select a.cust_id , b.name
3 from sales a, state b
4 where a.state = b.stateid and b.stateid = 'GA' ;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 573K| 15M | 36207 (0) |
| 1 | NESTED LOOPS | | 573K| 15M | 36207 (0) |
| 2 | TABLE ACCESS BY INDEX ROWID | STATE | 1 | 21 | 2 (50) |
|* 3 | INDEX UNIQUE SCAN | STATE_PK | 1 | | |
| 4 | TABLE ACCESS BY INDEX ROWID | SALES | 573K| 4480K | 36206 (0) |
|* 5 | INDEX RANGE SCAN | SALES_IDX_2 | 573K| | 15344 (0) |
---------------------------------------------------------------------------------------------------------------------------
In Case -2 , the cost
for INDEX RANGE
SCAN for
SALES_IDX_2 was
30095, after
changing the
parameter
OPTIMIZER_INDEX_
CACHING to 50, it
came to 15344, just
half of what it was
before.
The TABLE
ACCESS BY INDEX
ROWID for SALES
table came down to
36206 from 37682.
Finally the total
cost came down to
36,207 from 37,683.
2007-11-2538
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 3. Most Influential Init.ora Parameters
Case 4
If you further increase the parameter OPTIMIZER_INDEX_CACHING, then the cost of INDEX SCAN will further
come down.
Let us test this concept with a new value, 90.
SQL> alter session set optimizer_index_caching = 90 ;
Session altered.
SQL> alter session set optimizer_index_cost_adj = 10 ;
Session altered.
SQL> explain plan for
2 select a.cust_id , b.name
3 from sales a, state b
4 where a.state = b.stateid and b.stateid = 'GA' ;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 573K | 15M | 34980 (0) |
| 1 | NESTED LOOPS | | 573K | 15M | 34980 (0) |
| 2 | TABLE ACCESS BY INDEX ROWID | STATE | 1 | 21 | 2 (50) |
|* 3 | INDEX UNIQUE SCAN | STATE_PK | 1 | | |
| 4 | TABLE ACCESS BY INDEX ROWID | SALES | 573K | 4480K | 34979 (0) |
|* 5 | INDEX RANGE SCAN | SALES_IDX_2 | 573K | | 3069 (0) |
--------------------------------------------------------------------------------------------------------------------------------------
The cost of INDEX RANGE SCAN has been reduced to 3069.
2007-11-2539
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning 3. Most Influential Init.ora Parameters
In conclusion
When the SYSTEM statistics is off:
One thing you should remember, the above tests and various costs obtained did not
tell you which query will run faster.
I just demonstrated the impact of changing those 2 parameters.
There is no rule of thumb to fix those 2 values. How ever, One thing is sure that the
default value 0 and 100 for OPTIMIZER_INDEX_CACHING and
OPTIMIZER_INDEX_COST_ADJ respectively are set for Data Warehouse System.
If your system is OLTP, then these 2 parameters values should be changed. I would
test the sytem with different values before choosing the correct values.
Setting 90 to OPTIMIZER_INDEX_CACHING and 10 (or 15) to
OPTIMIZER_INDEX_COST_ADJ will perform good for OLTP system.
When the SYSTEM statistics is on:
Starting from 9i and 10g You can collect system statistics (CPU & IO). When those
statistics are available, then the optimizer uses those statistics in the execution
plan and ignores OPTIMIZER_INDEX_CACHING and
OPTIMIZER_INDEX_COST_ADJ values.
2007-11-2540
Beacon Infotech Corporation
www.oracleact.com
Oracle Performance Tuning