con8643 oracle optimizer bootcamp part2
TRANSCRIPT
Oracle Optimizer Bootcamp 10 Optimizer tips you can't do without
Maria Colgan & Jonathan Lewis
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 2
PART 2
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 3
Program Agenda
Using the right tools
Finding the right sample size
Tell the optimizer everything
Functions friends or foe
Most useful hints to know
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 4
Tell the Optimizer everything
The Optimizer makes assumptions in certain case
– Each additional where clause predicates reduces the number of rows
– Each additional group by column will increase number of rows returned
– Applying a function to column will alter the NDV of the column
Sometimes you know more about your data than basic statistics show
– Best way to get a good plan is to tell the Optimizer everything
– Otherwise it assumes, making an ass out of u and me
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 5
Tell the optimizer everything Correlated column example
SELECT * FROM vehicles WHERE model = ‘530xi’
AND color = 'RED’;
MAKE MODEL COLOR Year
BMW 530xi RED 2013
Cardinality #ROWS * 1 * 1 12 * 1 * 1 1 NDV c1 NDV c2 4 3
= => =
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 6
Tell the optimizer everything Correlated column example
SELECT * FROM vehicles WHERE model = ‘530xi’
AND make = ‘BMW’;
MAKE MODEL COLOR Year
BMW 530xi RED 2013
BMW 530xi BLACK 2011
BMW 530xi BLUE 2012
Cardinality #ROWS * 1 * 1 12 * 1 * 1 1 NDV c1 NDV c2 4 3
=> =
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 7
Create extended statistics on column group DBMS_STATS.CREATE_EXTENDED_STATS
New Column with
system generated
name
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 8
Tell the optimizer everything Correlated column example with extended statistics
SELECT * FROM vehicles WHERE model = ‘530xi’
AND make = ‘BMW’;
MAKE MODEL COLOR Year
BMW 530xi RED 2013
BMW 530xi BLACK 2011
BMW 530xi BLUE 2012
Cardinality calculated using column group statistics
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 9
Tell the Optimizer everything
Use SEED_COL_USAGE to have Oracle monitor workload
Can monitor STS or live system
Recommends what column groups are needed based on workload
Automatic column group detection
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 10
Bad Defaults (a)
create table t1 as
select
decode(
mod(rownum - 1,1000),
0,to_date('31-Dec-4000'),
to_date('01-Jan-2010') +
trunc((rownum-1)/100)
) date_closed
from
large_data_source
where
rownum <= 1827 * 100
;
-- 5 years in days * 100
-- every 1000th row
-- is a 'null' date
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 11
Bad Defaults (b)
select * from t1 where date_closed
between to_date('01-Jan-2012','dd-mon-yyyy')
and to_date('31-Dec-2012','dd-mon-yyyy');
-- 36,500 rows
With simple statistics.
TABLE ACCESS (FULL) OF 'T1' (Cost=46 Card=291 Bytes=2328)
With 11 column histogram (two per year and one for the garbage)
TABLE ACCESS (FULL) OF 'T1' (Cost=46 Card=36320 Bytes=290560)
With nulls and simple statistics.
TABLE ACCESS (FULL) OF 'T1' (Cost=46 Card=36583 Bytes=256081)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 12
Graphical Interpretation
The real data
Oracle's first impression
Impression with histogram
Data for 2012
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 13
Bad Data Types (a)
create table t1 as
select
d1,
to_number(to_char(d1,'yyyymmdd')) n1,
to_char(d1,'yyyymmdd') v1
from (
select
to_date('31-Dec-2009') + rownum d1
from all_objects
where
rownum <= 1827 -- 5 years, daily
);
-- date
-- numeric
-- char
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 14
Bad Data Types (b)
select * from t1 where d1 -- 7 rows
between to_date('30-Dec-2012','dd-mon-yyyy')
and to_date('05-Jan-2013','dd-mon-yyyy');
On the date type.
TABLE ACCESS (FULL) OF 'T1' (Cost=3 Card=8 Bytes=184)
N1 between 20121230 and 20030105
TABLE ACCESS (FULL) OF 'T1' (Cost=3 Card=397 Bytes=9131)
V1 between ' 20121230' and '20030105'
TABLE ACCESS (FULL) OF 'T1' (Cost=3 Card=457 Bytes=10511)
10g+ gets Card=397 - everything looks like numbers)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 15
Histogram effects:
N1 between 20121230 and 20130105
– pre-histogram
TABLE ACCESS (FULL) OF 'T1' (Cost=3 Card=397 Bytes=9131)
– post-histogram
TABLE ACCESS (FULL) OF 'T1' (Cost=3 Card=32 Bytes=736)
V1 between ' 20121230' and '20130105‘
‒ pre-histogram
TABLE ACCESS (FULL) OF 'T1' (Cost=3 Card=457 Bytes=10511)
‒ post-histogram
TABLE ACCESS (FULL) OF 'T1' (Cost=3 Card=30 Bytes=690)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 16
Graphical Interpretation The real (char/number) data
Oracle's first impression
Impression with histogram
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 17
Program Agenda
Using the right tools
Finding the right sample size
Tell the optimizer everything
Functions friends or foe
Most useful hints to know
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 18
Functions friends or foe?
Query – How many packages of bounce did we sell?
Sales 2 has a b-tree index on the prod_id column
Expected index range scan but got fast full index scan
SELECT count(*)
FROM sales2
WHERE to_char(prod_id)=‘139’;
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 19
Functions friends or foe?
Cardinality estimate is in the
right ballpark so not a
problem with statistics
Why is an equality predicate
being evaluated as a filter
and not an access
predicate?
Could it have something to do
with the TO_CHAR function
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 20
Functions friends or foe?
INTERNAL_FUNCTION indicates Oracle needs to modify predicate
– In this case a data type conversion occurred
Predicate is TO_CHAR(prod_id)
Optimizer has no idea how function effects values in prod_id column
Optimizer can’t determine which rows will be accessed now
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 21
Functions friends or foe?
What data type is the prod_id column ?
But literal value is a character string ‘139’
Better to apply inverse function on other side of predicate
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 22
Functions friends or foe?
Query rewrite SELECT count(*)
FROM sales2
WHERE prod_id=to_number(‘139’);
Solution - Use inverse function on other side of predicate
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 23
Functions friends or foe?
Keep the following in mind when deciding where to place the function
– Try to place functions on top of constants (literals, binds) rather than on columns
– Avoid functions on index columns or partition keys as it prevents index use or
partition pruning
– For function-based index to be considered, use that exact function as specified in
index
– If multiple predicates involve the same columns, write predicates such that they
share common expressions For example,
WHERE f(a) = b WHERE a = inv_f(b)
AND a = c AND a = c
Using inverse function on other side of predicate
Should be
rewritten as
This will allow transitive
predicate c=inv_f(b) to be
added by the optimizer
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 24
Virtual Columns (a)
create table t1 as
Select
cast(rownum as number(8,0)) id1,
cast(rownum as number(8,0)) id2
from all_objects
where rownum <= 10000
;
execute dbms_stats.gather_table_stats(user,'t1');
alter table t1 add
m2 generated always as ( mod(id2,3)) virtual
;
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 25
Virtual Columns (b)
set autotrace traceonly explain
select * from t1 where mod(id1,3) = 0;
.
|* 1 | TABLE ACCESS FULL| T1 | 100 | 1100 | 4 |
Predicate Information (identified by operation id):
1 - filter(MOD("ID1",3)=0)
select * from t1 where mod(id1,3) != 0;
.
|* 1 | TABLE ACCESS FULL| T1 | 500 | 5500 | 4 |
Predicate Information (identified by operation id):
1 - filter(MOD("ID1",3)<>0)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 26
Virtual Columns (c)
set autotrace traceonly explain
select * from t1 where mod(id2,3) = 0;
.
|* 1 | TABLE ACCESS FULL| T1 | 3333 | 36663 | 4 |
Predicate Information (identified by operation id):
1 - filter("T1"."M2"=0)
select * from t1 where mod(id2,3) != 0;
.
|* 1 | TABLE ACCESS FULL| T1 | 6667 | 73337 | 4 |
Predicate Information (identified by operation id):
1 - filter("T1"."M2"<>0)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 27
Program Agenda
Using the right tools
Finding the right sample size
Tell the optimizer everything
Functions friends or foe
Most useful hints to know
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 28
Most useful hints to know
Understanding Optimizer hints
Hints allow you to influence the Optimizer when it has to choose
between several possibilities
A hint is a directive that will be followed when applicable
Can influence everything from the Optimizer mode used to each
operation in the execution
The hint mechanism is not exclusively used by the Optimizer
Some of the most useful hint influence SQL execution
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 29
Most useful hints to know
GATHER_PLAN_STATISTICS triggers execution time statistics to be
preserved
Records actual number of rows seen for each operation (step) in plan
Execution statistis displayed in plan when format parameter of
DMBS_XPLAN set to ALLSTATS LAST
– Means display all execution statistics for last execution of this cursor
GATHER_PLAN_STATISTICS hint
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 30
GATHER_PLAN_STATISTICS hint
SELECT * FROM table (
DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'ALLSTATS
LAST'));
Compare estimated rows returned for each operation to actual rows
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 31
GATHER_PLAN_STATISTICS Hint
SELECT * FROM table (
DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'ALLSTATS LAST'));
Note: a lot of the data is zero in
the A-rows column because we
only show last executed cursor
which is the QC. Need to use
ALLSTATS ALL to see info on all
parallel server cursors
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 32
GATHER_PLAN_STATISTICS Hint
SELECT * FROM table (
DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'ALLSTATS ALL'));
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 33
Alternatively using MONITOR hint
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 34
Most helpful hints to know
Allows value for init.ora Optimizer parameters to be changed for a specific
query
Useful way to prevent setting non-default parameter value system-wide
Only the following Optimizer influencing init.ora parameters can be set:
OPT_PARAM hint
OPTIMIZER_DYNAMIC_SAMPLING
OPTIMIZER_INDEX_CACHING
OPTIMIZER_INDEX_COST_ADJ
OPTIMIZER_USE_PENDING_STATISTICS
Optimizer related underscore parameters
STAR_TRANSFORMATION_ENABLED
PARALLEL_DEGREE_POLICY
PARALLEL_DEGREE_LIMIT
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 35
OPT_PARAM hint Example
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 36
OPT_PARAM hint Example
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 37
Most useful hints to know
OPTIMIZER_FEATURES_ENABLE parameter allows you to switch
between optimizer versions
Setting it to previous database version reverts the Optimizer to that
version
– Disables any functionality that was not present in that version
Easy way to work around unexpected behavior in a new release
Hint allows you to revert the Optimizer for just a single statement
OPTIMIZER_FEATURES_ENABLE hint
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 38
Precision matters (a)
select /*+ parallel(pt1,2) */
{list of columns}
from pt1
where pt1.n1 = 5
and pt1.n2 = 10
and pt1.pt_group in (0,10)
;
The optimizer DID obey the hint
.
|Id|Operation |Name |Cost |Pstart| Pstop|
| 0|SELECT STATEMENT | | 48| | |
| 1| PARTITION LIST INLIST | | 48|KEY(I)|KEY(I)|
|*2| TABLE ACCESS BY LOCAL INDEX ROWID|PT1 | 48|KEY(I)|KEY(I)|
|*3| INDEX RANGE SCAN |PT1_I1| 3|KEY(I)|KEY(I)|
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 39
Precision matters (b)
...
NESTED LOOP
TABLE ACCESS (FULL) OF T7
TABLE ACCESS BY INDEX ROWID T8
INDEX RANGE SCAN T8_IND_SECOND -- “wrong” index
... select /*+ index(t8 t8_ind_first) */ -- hint the “right” one
...
HASH JOIN -- wrong method
TABLE ACCESS (FULL) OF T7
TABLE ACCESS BY INDEX ROWID T8
INDEX FULL SCAN T8_IND_FIRST -- “right” index
...
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 40
How much don't we know ? select
/*+
leading(t4 t1 t2 t3)
full(t4)
use_hash(t1) full(t1)
use_hash(t2) full(t2)
use_hash(t3) full(t3)
*/
...
From t4, t1, t2, t3
Where t1.id = t4.id1
and t2.id = t4.id2
and t3.id = t4.id3;
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 41
How much don't we know ? N – 1 simultaneous build (hash) tables
Maximum two simultaneous build (hash) tables
HASH JOIN
TABLE ACCESS (FULL) OF TABLE_3
HASH JOIN
TABLE ACCESS (FULL) OF TABLE_2
HASH JOIN
TABLE ACCESS (FULL) OF TABLE_1
TABLE ACCESS (FULL) OF TABLE_4
HASH JOIN
HASH JOIN
HASH JOIN
TABLE ACCESS (FULL) OF TABLE_4
TABLE ACCESS (FULL) OF TABLE_1
TABLE ACCESS (FULL) OF TABLE_2
TABLE ACCESS (FULL) OF TABLE_3
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 42
Summary
Forgive the Optimizer – it’s not out to get you
– Its knowledge is limited to the information you provide it
A complete representative set of statistics gets the best plans
– Determine or have Oracle determine what extended statistics are needed
Be mindful of when you capture a representative set of statistics
– Don’t be afraid to adjust maintenance window or include statistics in ETL
Optimizer hints should only be used with extreme caution
– To guarantee the same plan every time use SQL Plan Baselines
Enjoy the challenge!
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 43
More Information
White papers
– Optimizer with Oracle Database 12c
– SQL Plan Management with Oracle Database 12c
– Understanding Optimizer Statistics with Oracle Database 12c
Blogs
– http://jonathanlewis.wordpress.com/all-postings/
– http://blogs.oracle.com/optimizer
Oracle.com
– http://www.oracle.com/technetwork/database/focus-areas/bi-
datawarehousing/dbbi-tech-info-optmztn-092214.html
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 44