Half the battle of writing good SQL is in understanding how the Oracle query optimizer analyzes your code and applies statistics in order to derive the “best” execution plan. The other half of the battle is successfully applying that knowledge to the databases that you manage. The optimizer uses statistics as input to develop query execution plans, and so these statistics are the foundation of good plans. If the statistics supplied aren’t representative of your actual data, you can expect bad plans. However, if the statistics are representative of your data, then the optimizer will probably choose an optimal plan.
1. Managing Statistics for
Optimal Query Performance
Karen Morton
karen.morton@agilex.com
OOW 2009
2009 October 13
1:00pm-2:00pm
Moscone South Room 305
2. Your speaker…
•Karen Morton
– Sr. Principal Database Engineer
– Educator, DBA, developer,
consultant, researcher, author,
speaker, …
•Come see me…
– karenmorton.blogspot.com
– An Oracle user group near you
4. “I accept no responsibility for
statistics, which are a form of magic
beyond my comprehension.”
— Robertson Davies
5. SQL>desc deck
Name Null? Type
------------- -------- -------------
SUIT NOT NULL VARCHAR2(10)
CARD VARCHAR2(10)
COLOR VARCHAR2(5)
FACEVAL NOT NULL NUMBER(2)
6. Table: DECK
Statistic Current value
--------------- -------------------
# rows 52
Blocks 5
Avg Row Len 20
Degree 1
Sample Size 52
Column Name NDV Nulls # Nulls Density Length Low Value High Value
----------- --- ----- ------- ------- ------ ---------- -----------
SUIT 4 N 0 .250000 8 Clubs Spades
CARD 13 Y 0 .076923 5 Ace Two
COLOR 2 Y 0 .500000 5 Black Red
FACEVAL 13 N 0 .076923 3 1 13
Index Name Col# Column Name Unique? Height Leaf Blks Distinct Keys
-------------- ----- ------------ ------- ------ ---------- -------------
DECK_PK 1 SUIT Y 1 1 52
2 FACEVAL
DECK_CARD_IDX 1 CARD N 1 1 13
DECK_COLOR_IDX 1 COLOR N 1 1 2
38. SQL>exec dbms_stats.gather_table_stats (ownname=>?, tabname=>?) ;
partname NULL
cascade DBMS_STATS.AUTO_CASCADE
estimate_percent DBMS_STATS.AUTO_SAMPLE_SIZE
stattab NULL
block_sample FALSE
statid NULL
method_opt FOR ALL COLUMNS SIZE AUTO
statown NULL
degree 1 or value based on number of CPUs
and initialization parameters
force FALSE
granularity AUTO (value is based on partitioning type)
no_invalidate DBMS_STATS.AUTO_INVALIDATE
39. cascade=>
AUTO_CASCADE
Allow Oracle to determine
whether or not to
gather index statistics
44. Say you were standing with one
foot in the oven and one foot in
an ice bucket. According to the
percentage people, you would
be perfectly comfortable.
– Bobby Bragan
98. To derive the cardinality
estimate for range predicates,
the optimizer uses the low
and high value statistics.
99. Table: hi_lo_t
Statistic Current value
--------------- ---------------------
# rows 100000
Blocks 180
Avg Row Len 7
Sample Size 100000
Monitoring YES
Column NDV Nulls Density AvgLen Histogram LowVal HighVal
------- ------ ----- ------- ------ --------- ------ -------
A 100000 N .000010 5 NONE (1) 10 100009
B 10 Y .100000 3 NONE (1) 9 18
100% Statistics
FOR ALL COLUMNS SIZE 1
100. select count(a)
from hi_lo_t
where b < 11 ;
( 11 – 9
18 – 9 ) Predicate value – Low value
High value – Low value
100000 rows x .22222 = 22222
101. select count(a) from hi_lo_t where b < 11
Plan hash value: 3307858660
------------------------------------------------------------------
| Id | Operation | Name | E-Rows | A-Rows | Buffers |
------------------------------------------------------------------
| 1 | SORT AGGREGATE | | 1 | 1 | 184 |
|* 2 | TABLE ACCESS FULL| HI_LO_T | 22222 | 20000 | 184 |
------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("B"<11)
102. select count(a)
from hi_lo_t
where b < 4 ;
.10 x ( 1 +
4 – 9
18 – 9 ) Predicate value – Low value
High value – Low value
100000 rows x .04444 = 4444
103. select count(a) from hi_lo_t where b < 4
Plan hash value: 3307858660
------------------------------------------------------------------
| Id | Operation | Name | E-Rows | A-Rows | Buffers |
------------------------------------------------------------------
| 1 | SORT AGGREGATE | | 1 | 1 | 184 |
|* 2 | TABLE ACCESS FULL| HI_LO_T | 4444 | 0 | 184 |
------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("B"<4)