SlideShare une entreprise Scribd logo
1  sur  91
Télécharger pour lire hors ligne
10	
  Things	
  You	
  Might	
  Not	
  Know	
  
       About	
  Oracle	
  Indexes	
  
               Richard	
  Foote	
  




                 The most comprehensive Oracle applications & technology content under one roof
Richard	
  Foote	
  
•    Working	
  in	
  IT	
  for	
  25	
  years	
  (scary	
  stuff)	
  
•    Working	
  with	
  Oracle	
  for	
  15	
  years	
  (almost	
  as	
  scary)	
  
•    Previously	
  employed	
  by	
  Oracle	
  CorporaFon	
  for	
  5	
  ½	
  years	
  (scary	
  as	
  hell)	
  
•    Currently	
  employed	
  by	
  the	
  Australian	
  Federal	
  Government	
  as	
  a	
  Senior	
  
     DBA	
  
•    Responsible	
  for	
  many	
  large	
  scale,	
  mission	
  criFcal,	
  “life-­‐dependant”	
  
     classified	
  Oracle	
  systems	
  
•    Based	
  in	
  sunny	
  Canberra,	
  Australia	
  
•    Oracle	
  OakTable	
  member	
  since	
  2002	
  and	
  Oracle	
  ACE	
  Director	
  since	
  2008	
  
•    Interests	
  includes	
  all	
  sports	
  and	
  music	
  (cool	
  stuff	
  like	
  David	
  Bowie,	
  Pink	
  
     Floyd,	
  Radiohead	
  and	
  Muse)	
  
•    richard.foote@bigpond.com	
  
•    Richard	
  Foote’s	
  Oracle	
  Blog:	
  hBp://richardfoote.wordpress.com/	
  



                                               The most comprehensive Oracle applications & technology content under one roof
1.	
  Delete	
  More	
  Rows	
  To	
  Reduce	
  
         Deleted	
  Space	
  Within	
  An	
  Index	
  
•  Very	
  common	
  advice	
  to	
  rebuild	
  index	
  if	
  percentage	
  
   of	
  deleted	
  space	
  >	
  20%	
  
•  For	
  example	
  -­‐	
  Metalink	
  Note:	
  122008.1	
  
   recommended	
  this	
  for	
  many	
  years	
  
•  Validate	
  index	
  structure	
  (Ignoring	
  that	
  it’s	
  
   expensive	
  and	
  locks	
  the	
  table)	
  
•  Claimed	
  rebuild	
  will	
  remove	
  index	
  “deadwood”	
  and	
  
   make	
  index	
  more	
  efficient	
  
•  However,	
  if	
  only	
  we	
  just	
  deleted	
  even	
  more	
  rows	
  ...	
  

                                  The most comprehensive Oracle applications & technology content under one roof
1:	
  If	
  deleted	
  space	
  >20%,	
  delete	
  some	
  more!!	
  
SQL>	
  create	
  table	
  radiohead	
  (id	
  number,	
  name	
  varchar2(20));	
  
Table	
  created.	
  
	
  	
  
SQL>	
  insert	
  into	
  radiohead	
  select	
  rownum,	
  'OK	
  COMPUTER'	
  from	
  dual	
  connect	
  by	
  level	
  <=	
  
100000;	
  
100000	
  rows	
  created.	
  
	
  	
  
SQL>	
  commit;	
  
Commit	
  complete.	
  
	
  	
  
SQL>	
  create	
  index	
  radiohead_i	
  on	
  radiohead(id)	
  pckree	
  0;	
  
Index	
  created.	
  
	
  	
  
SQL>	
  analyze	
  index	
  radiohead_i	
  validate	
  structure;	
  
Index	
  analyzed.	
  
	
  	
  
SQL>	
  select	
  lf_rows,	
  del_lf_rows,	
  round((del_lf_rows/lf_rows)*100)	
  PCT_DEL,	
  pct_used	
  from	
  
index_stats;	
  
	
  	
  
   LF_ROWS DEL_LF_ROWS    PCT_DEL   PCT_USED
---------- ----------- ---------- ----------
    100000           0          0        100




                                                    The most comprehensive Oracle applications & technology content under one roof
1:	
  If	
  deleted	
  space	
  >20%,	
  delete	
  some	
  more!!	
  
SQL>	
  delete	
  radiohead	
  where	
  mod(id,10)	
  IN	
  (2,4,6);	
  
30000	
  rows	
  deleted.	
  
	
  	
  
SQL>	
  commit;	
  
Commit	
  complete.	
  
	
  
SQL>	
  analyze	
  index	
  radiohead_i	
  validate	
  structure;	
  
Index	
  analyzed.	
  
	
  	
  
SQL>	
  select	
  lf_rows,	
  del_lf_rows,	
  (del_lf_rows/lf_rows)*100	
  PCT_DEL,	
  pct_used	
  from	
  
index_stats;	
  
	
  	
  
	
    LF_ROWS DEL_LF_ROWS    PCT_DEL   PCT_USED
---------- ----------- ---------- ----------
    100000       30000         30        100

So	
  based	
  on	
  common	
  rebuild	
  criteria,	
  this	
  index	
  really	
  
should	
  be	
  rebuilt	
  ...	
  

                                                The most comprehensive Oracle applications & technology content under one roof
1:	
  If	
  deleted	
  space	
  >20%,	
  delete	
  some	
  more!!	
  
Well,	
  let’s	
  just	
  delete	
  some	
  more	
  rows	
  ...	
  
SQL>	
  delete	
  radiohead	
  where	
  mod(id,10)	
  =	
  8;	
  
	
  10000	
  rows	
  deleted.	
  
	
  	
  
SQL>	
  commit;	
  
Commit	
  complete.	
  
	
  	
  
SQL>	
  analyze	
  index	
  radiohead_i	
  validate	
  structure;	
  
Index	
  analyzed.	
  
	
  	
  
SQL>	
  select	
  lf_rows,	
  del_lf_rows,	
  round((del_lf_rows/lf_rows)*100)	
  PCT_DEL,	
  pct_used	
  
from	
  index_stats;	
  
	
  	
  
   LF_ROWS DEL_LF_ROWS    PCT_DEL   PCT_USED
---------- ----------- ---------- ----------
     70000       10000         14         70




                                             The most comprehensive Oracle applications & technology content under one roof
1:	
  If	
  deleted	
  space	
  >20%,	
  delete	
  some	
  more!!	
  
•  What	
  many	
  don’t	
  realise	
  is	
  that	
  in	
  most	
  scenarios,	
  
   deleted	
  space	
  is	
  the	
  same	
  as	
  free	
  space	
  
•  It	
  will	
  generally	
  eventually	
  get	
  reused	
  
•  To	
  clean	
  out	
  deleted	
  space,	
  it	
  just	
  takes	
  the	
  leaf	
  
   block	
  to	
  be	
  modified	
  by	
  a	
  subsequent	
  transacFon	
  
•  The	
  criteria	
  actually	
  rebuilds	
  indexes	
  that	
  don’t	
  need	
  
   rebuilding,	
  and	
  
•  The	
  criteria	
  misses	
  out	
  on	
  those	
  indexes	
  that	
  might	
  
   actually	
  need	
  rebuilding	
  


                                  The most comprehensive Oracle applications & technology content under one roof
2.Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
•  Very	
  common	
  advice	
  to	
  only	
  use	
  Bitmap	
  Index	
  with	
  
   “Low”	
  Cardinality	
  Columns	
  
•  Generally	
  columns	
  with	
  less	
  than	
  20	
  disFnct	
  values	
  
•  Examples:	
  Eye/Hair	
  Colour,	
  Sex,	
  States	
  of	
  Australia...	
  
•  A	
  column	
  with	
  say	
  10,000	
  disFnct	
  values	
  would	
  be	
  far	
  
   too	
  many	
  and	
  result	
  in	
  huge,	
  inefficient	
  index	
  	
  
•  A	
  column	
  on	
  say	
  person	
  first	
  name	
  or	
  surname	
  would	
  
   be	
  totally	
  unsuitable	
  for	
  a	
  Bitmap	
  Index	
  
•  But	
  would	
  it	
  really	
  ...	
  


                                    The most comprehensive Oracle applications & technology content under one roof
2.Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
SQL>	
  CREATE	
  TABLE	
  big_dwh_table	
  (id	
  NUMBER,	
  album_id	
  NUMBER,	
  arFst_id	
  NUMBER,	
  country_id	
  NUMBER,	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  format_id	
  NUMBER,	
  release_date	
  DATE,	
  total_sales	
  NUMBER);	
  
Table	
  created.	
  
	
  
SQL>	
  CREATE	
  SEQUENCE	
  dwh_seq;	
  
Sequence	
  created.	
  
	
  
SQL>	
  create	
  or	
  replace	
  procedure	
  pop_big_dwh_table	
  as	
  
	
  	
  2	
  	
  v_id	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  number;	
  
	
  	
  3	
  	
  v_arFst_id	
  	
  	
  number;	
  
	
  	
  4	
  	
  begin	
  
	
  	
  5	
  	
  	
  	
  for	
  v_album_id	
  in	
  1..10000	
  loop	
  
	
  	
  6	
  	
  	
  	
  	
  	
  	
  	
  v_arFst_id:=	
  ceil(dbms_random.value(0,100));	
  
	
  	
  7	
  	
  	
  	
  	
  	
  	
  	
  for	
  v_country_id	
  in	
  1..100	
  loop	
  
	
  	
  8	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  select	
  dwh_seq.nextval	
  into	
  v_id	
  from	
  dual;	
  
	
  	
  9	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  insert	
  into	
  big_dwh_table	
  values	
  (v_id,	
  v_album_id,	
  v_arFst_id,	
  vcountry_id,	
  ceil(dbms_random.value(0,4)),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  trunc(sysdate-­‐mod(v_id,ceil(dbms_random.value(0,1000)))),	
  ceil(dbms_random.value(0,500000)));	
  
	
  10	
  	
  	
  	
  	
  	
  	
  end	
  loop;	
  
	
  11	
  	
  	
  	
  end	
  loop;	
  
	
  12	
  commit;	
  
	
  13	
  end;	
  
	
  14	
  /	
  
Procedure	
  created.	
  
	
  
SQL>	
  exec	
  pop_big_dwh_table	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  




                                                                                                                                         The most comprehensive Oracle applications & technology content under one roof
2.Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
 OK,	
  let’s	
  start	
  with	
  a	
  B-­‐Tree	
  Index	
  
SQL>	
  CREATE	
  INDEX	
  big_dwh_album_id_i	
  ON	
  big_dwh_table(album_id)	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  COMPUTE	
  STATISTICS;	
  
	
  
Index	
  created.	
  
	
  
SQL>	
  SELECT	
  i.index_type,	
  i.disFnct_keys,	
  t.num_rows	
  "T	
  ROWS",	
  t.blocks	
  "T	
  BLOCKS",	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  i.num_rows	
  "I	
  ROWS",	
  i.clustering_factor	
  CF,	
  i.leaf_blocks	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  FROM	
  user_indexes	
  i,	
  user_tables	
  t	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  i.table_name=t.table_name	
  and	
  i.index_name	
  =	
  'BIG_DWH_ALBUM_ID_I';	
  
	
  
INDEX_TYPE DISTINCT_KEYS     T ROWS   T BLOCKS     I ROWS         CF LEAF_BLOCKS
---------- ------------- ---------- ---------- ---------- ---------- -----------
NORMAL             10000    1000000       4948    1000000       4951        2090


Note	
  the	
  album_id	
  column	
  has	
  a	
  relaFvely	
  “high”	
  cardinality	
  at	
  
10,000	
  disFnct	
  values.	
  Also	
  note	
  the	
  B-­‐Tree	
  Index	
  is	
  extremely	
  well	
  
clustered	
  (CF	
  matches	
  blocks	
  in	
  table)	
  and	
  has	
  2090	
  leaf	
  blocks	
  ...	
  	
  


                                                                          The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  WHERE	
  album_id	
  =	
  42;	
  
	
  
100 rows selected.


Execution Plan
-------------------------------------------------------------------------------------------------
| Id | Operation                    | Name                 | Rows | Bytes |Cost (%CPU)| Time    |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                      |   100 | 3000 |    103 (0)|00:00:02|
|   1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE_2       |   100 | 3000 |    103 (0)|00:00:02|
|* 2 |    INDEX RANGE SCAN          | BIG_DWH_2_ALBUM_ID_I |   100 |       |     3 (0)|00:00:01|
-------------------------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
       19 consistent gets
      100 rows processed



  Note:	
  As	
  expected,	
  the	
  index	
  is	
  used	
  to	
  retrieve	
  the	
  relaFvely	
  few	
  
  100	
  rows	
  (0.01%	
  of	
  data).	
  	
  
  	
  
  Just	
  19	
  consistent	
  reads	
  required	
  ...	
  


                                                    The most comprehensive Oracle applications & technology content under one roof
2.Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
Let’s	
  create	
  same	
  index	
  as	
  a	
  Bitmap	
  Index.	
  However,	
  with	
  10,000	
  
disFnct	
  values,	
  unlikely	
  to	
  be	
  efficient,	
  right	
  ?	
  
SQL>	
  DROP	
  INDEX	
  big_dwh_album_id_i;	
  
	
  
Index	
  dropped.	
  
	
  
SQL>	
  CREATE	
  BITMAP	
  INDEX	
  big_dwh_album_id_i	
  ON	
  big_dwh_table(album_id);	
  
	
  
Index	
  created.	
  
	
  
SQL>	
  SELECT	
  index_name,	
  index_type,	
  disFnct_keys,	
  num_rows,	
  leaf_blocks,	
  blocks	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  FROM	
  user_indexes	
  i,	
  user_segments	
  s	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  i.index_name	
  =	
  s.segment_name	
  and	
  i.index_name	
  =	
  'BIG_DWH_ALBUM_ID_I';	
  
	
  
INDEX_NAME         INDEX_TYPE DISTINCT_KEYS NUM_ROWS LEAF_BLOCKS BLOCKS
------------------ ---------- ------------- -------- ----------- ------
BIG_DWH_ALBUM_ID_I BITMAP             10000   10000           56    128


Wrong.	
  The	
  number	
  of	
  index	
  rows	
  is	
  just	
  10000,	
  one	
  for	
  each	
  disFnct	
  
value	
  and	
  leaf	
  blocks	
  has	
  dropped	
  from	
  2090	
  to	
  just	
  56	
  !!	
  


                                                         The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  WHERE	
  album_id	
  =	
  42;	
  
	
  
100 rows selected.


Execution Plan
-------------------------------------------------------------------------------------------------
| Id | Operation                     | Name               | Rows | Bytes | Cost (%CPU)| Time    |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                    |   100 | 3000 |     22   (0)|00:00:01|
|   1 | TABLE ACCESS BY INDEX ROWID | BIG_DWH_TABLE       |   100 | 3000 |     22   (0)|00:00:01|
|   2 |   BITMAP CONVERSION TO ROWIDS|                    |       |       |            |        |
|* 3 |     BITMAP INDEX SINGLE VALUE | BIG_DWH_ALBUM_ID_I |       |       |            |        |
-------------------------------------------------------------------------------------------------


Statistics
----------------------------------------------------------
       11    consistent gets
      100    rows processed


  Note:	
  Not	
  only	
  is	
  the	
  index	
  used,	
  but	
  the	
  number	
  of	
  consistent	
  reads	
  
  has	
  dropped	
  from	
  19	
  to	
  just	
  11	
  !!	
  


                                                    The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
The	
  Clustering	
  Factor	
  of	
  an	
  index	
  has	
  a	
  big	
  impact	
  on	
  the	
  overall	
  size	
  of	
  a	
  Bitmap	
  Index	
  
	
  
This	
  is	
  due	
  to	
  having	
  more	
  conFnuous	
  zeros	
  in	
  the	
  bitmap	
  string	
  that	
  can	
  be	
  more	
  efficiently	
  
compressed	
  
	
  
SQL>	
  SELECT	
  i.index_name,	
  i.index_type,	
  t.num_rows	
  "TABLE	
  ROWS",	
  t.blocks,	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  i.num_rows	
  "INDEX	
  ROWS",	
  i.clustering_factor	
  CF,	
  i.leaf_blocks	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  FROM	
  user_indexes	
  i,	
  user_tables	
  t	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  i.table_name=t.table_name	
  and	
  i.index_name	
  =	
  'BIG_DWH_ALBUM_ID_I';	
  
	
  
INDEX_NAME         INDEX_TYPE TABLE ROWS BLOCKS INDEX ROWS      CF LEAF_BLOCKS
------------------ ---------- ---------- ------- ---------- ------ -----------
BIG_DWH_ALBUM_ID_I BITMAP        1000000    4948      10000 10000           56


Note	
  the	
  CF	
  as	
  recorded	
  for	
  Bitmap	
  Indexes	
  is	
  a	
  liyle	
  meaningless	
  as	
  a	
  specific	
  index	
  entry	
  
covers	
  many	
  Rowids	
  but	
  the	
  CF	
  calculaFon	
  is	
  sFll	
  based	
  on	
  the	
  block	
  within	
  the	
  rowid	
  
changing	
  from	
  one	
  index	
  entry	
  to	
  the	
  next.	
  
	
  
Therefore,	
  CF	
  of	
  an	
  index	
  is	
  commonly	
  recorded	
  as	
  being	
  the	
  number	
  of	
  index	
  row	
  entries	
  




                                                                          The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
Create	
  a	
  copy	
  of	
  the	
  table	
  but	
  this	
  Fme	
  clustered	
  by	
  the	
  
TOTAL_SALES	
  column	
  
	
  
Then	
  create	
  a	
  Bitmap	
  Index	
  on	
  the	
  now	
  poorly	
  clustered	
  ALBUM_ID	
  
column	
  
SQL>	
  CREATE	
  TABLE	
  big_dwh_table_2	
  AS	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ORDER	
  BY	
  total_sales;	
  
	
  
Table	
  created.	
  
	
  
SQL>	
  CREATE	
  BITMAP	
  INDEX	
  big_dwh_2_album_id_i	
  ON	
  big_dwh_table_2(album_id);	
  
	
  
Index	
  created.	
  
	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>null,	
  tabname=>	
  'BIG_DWH_TABLE_2',	
  
esFmate_percent=>	
  null,	
  cascade=>	
  true,	
  method_opt=>	
  'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  
	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  




                                            The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
SQL>	
  SELECT	
  i.index_name,	
  i.index_type,	
  t.num_rows	
  "TABLE	
  ROWS",	
  t.blocks,	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  i.num_rows	
  "INDEX	
  ROWS",	
  i.clustering_factor	
  CF,	
  i.leaf_blocks	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  FROM	
  user_indexes	
  i,	
  user_tables	
  t	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  i.table_name=t.table_name	
  and	
  i.index_name	
  =	
  'BIG_DWH_2_ALBUM_ID_I';	
  
	
  
INDEX_NAME           INDEX_TYPE TABLE ROWS BLOCKS INDEX ROWS      CF LEAF_BLOCKS
-------------------- ---------- ---------- ------- ---------- ------ -----------
BIG_DWH_2_ALBUM_ID_I BITMAP        1000000    4973      10000 10000          455



  Note:	
  Leaf	
  Blocks	
  has	
  jumped	
  up	
  significantly	
  from	
  56	
  blocks	
  to	
  455	
  
  blocks	
  	
  




                                                                             The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table_2	
  WHERE	
  album_id	
  =	
  42;	
  
	
  
100 rows selected.


Execution Plan
-------------------------------------------------------------------------------------------------
| Id | Operation                     | Name                 | Rows | Bytes |Cost (%CPU)|Time    |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                      |   100| 3000 |    22   (0)|00:00:01|
|   1 | TABLE ACCESS BY INDEX ROWID | BIG_DWH_TABLE_2       |   100| 3000 |    22   (0)|00:00:01|
|   2 |   BITMAP CONVERSION TO ROWIDS|                      |      |       |           |        |
|* 3 |     BITMAP INDEX SINGLE VALUE | BIG_DWH_2_ALBUM_ID_I |      |       |           |        |
-------------------------------------------------------------------------------------------------


Statistics
----------------------------------------------------------
     101 consistent gets
     100 rows processed



  Note:	
  The	
  number	
  of	
  consistent	
  reads	
  has	
  now	
  jumped	
  up	
  from	
  11	
  to	
  
  101	
  ...	
  

                                                    The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
  Of	
  course,	
  this	
  will	
  also	
  impact	
  Clustering	
  Factor	
  of	
  a	
  B-­‐Tree	
  Index	
  ...	
  
SQL>	
  DROP	
  INDEX	
  big_dwh_2_album_id_i;	
  
	
  
Index	
  dropped.	
  
	
  
SQL>	
  CREATE	
  INDEX	
  big_dwh_2_album_id_i	
  ON	
  big_dwh_table_2(album_id);	
  
	
  
Index	
  created.	
  
	
  
SQL>	
  SELECT	
  i.index_name,	
  i.index_type,	
  t.num_rows	
  "TABLE	
  ROWS",	
  t.blocks,	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  i.num_rows	
  "INDEX	
  ROWS",	
  i.clustering_factor	
  CF,	
  i.leaf_blocks	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  FROM	
  user_indexes	
  i,	
  user_tables	
  t	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  i.table_name=t.table_name	
  and	
  i.index_name	
  =	
  'BIG_DWH_2_ALBUM_ID_I';	
  
	
  
INDEX_NAME           INDEX_TYPE TABLE ROWS BLOCKS INDEX ROWS       CF LEAF_BLOCKS
-------------------- ---------- ---------- ------- ---------- ------- -----------
BIG_DWH_2_ALBUM_ID_I NORMAL        1000000    4973    1000000 990003         2090

    Although	
  the	
  index	
  has	
  same	
  no.	
  of	
  leaf	
  blocks,	
  the	
  Clustering	
  Factor	
  
    has	
  jumped	
  to	
  a	
  massive	
  990003	
  ...	
  

                                                                             The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table_2	
  WHERE	
  album_id	
  =	
  42;	
  
	
  
100 rows selected.
Execution Plan

-------------------------------------------------------------------------------------------------
| Id | Operation                    | Name                 | Rows | Bytes |Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                      |   100 | 3000 | 103     (0)|00:00:02|
|   1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE_2       |   100 | 3000 | 103     (0)|00:00:02|
|* 2 |    INDEX RANGE SCAN          | BIG_DWH_2_ALBUM_ID_I |   100 |       |    3   (0)|00:00:01|
-------------------------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
      109 consistent gets
      100 rows processed


  Consistent	
  reads	
  has	
  jumped	
  from	
  19	
  to	
  109	
  which	
  is	
  sFll	
  worse	
  than	
  
  the	
  101	
  consistent	
  reads	
  	
  of	
  the	
  Bitmap	
  Index	
  ...	
  


                                                    The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
Table	
  containing	
  person	
  names,	
  using	
  freshly	
  rebuilt	
  B-­‐Tree	
  Indexes	
  ...	
  
 NAME                INDEX_TYPE     NUM_ROWS DISTINCT_KEYS LEAF_BLOCKS
 ----------          ------------ ---------- ------------- -----------
 FIRST NAME          NORMAL          2378672        147446        5842
 LAST NAME           NORMAL          2405599        361177        6202
 	
  	
  
 SQL>	
  select	
  *	
  from	
  persons	
  where	
  given_name1	
  =	
  'DAVID'	
  or	
  last_name	
  =	
  'BOWIE';	
  
 39240	
  rows	
  selected.	
  
 	
  	
  
 Execution Plan
 ---------------------------------------------------------------------------------------------------
 | Id | Operation                     | Name               | Rows | Bytes | Cost (%CPU)| Time      |
 ---------------------------------------------------------------------------------------------------
 |   0 | SELECT STATEMENT             |                    |   174 | 36888 |   164   (0)| 00:00:01 |
 |   1 | CONCATENATION                |                    |       |       |            |          |
 |   2 |   TABLE ACCESS BY INDEX ROWID| PERSONS            |    47 | 9964 |     44   (0)| 00:00:01 |
 |* 3 |     INDEX RANGE SCAN          | PERS_LAST_NAME_I   |    47 |       |     3   (0)| 00:00:01 |
 |* 4 |    TABLE ACCESS BY INDEX ROWID| PERSONS            |   127 | 26924 |   120   (0)| 00:00:01 |
 |* 5 |     INDEX RANGE SCAN          | PERS_FIRST_NAME1_I |   127 |       |     3   (0)| 00:00:01 |
 ---------------------------------------------------------------------------------------------------

 Statistics
 ----------------------------------------------------------
      28600 consistent gets




                                                             The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
Bitmap	
  Indexes	
  are	
  actually	
  substanFally	
  smaller	
  and	
  more	
  efficient	
  ...	
  
NAME                INDEX_TYPE     NUM_ROWS DISTINCT_KEYS LEAF_BLOCKS
----------          ------------ ---------- ------------- -----------
FIRST NAME          BITMAP           148208        147463        1608 (-4234)
LAST NAME           BITMAP           361421        361183        2543 (-3659)
	
  	
  
SQL>	
  select	
  *	
  from	
  persons	
  where	
  given_name1	
  =	
  'DAVID'	
  or	
  last_name	
  =	
  'BOWIE';	
  
	
  39240	
  rows	
  selected.	
  
	
  	
  
Execution Plan
---------------------------------------------------------------------------------------------------
| Id | Operation                     | Name               | Rows | Bytes | Cost (%CPU)| Time      |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                    |   176 | 37312 |    43   (0)| 00:00:01 |
|   1 | TABLE ACCESS BY INDEX ROWID | PERSONS             |   176 | 37312 |    43   (0)| 00:00:01 |
|   2 |   BITMAP CONVERSION TO ROWIDS|                    |       |       |            |          |
|   3 |    BITMAP OR                 |                    |       |       |            |          |
|* 4 |      BITMAP INDEX SINGLE VALUE| PERS_FIRST_NAME1_I |       |       |            |          |
|* 5 |      BITMAP INDEX SINGLE VALUE| PERS_LAST_NAME_I   |       |       |            |          |
---------------------------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
     28483 consistent gets




                                                            The most comprehensive Oracle applications & technology content under one roof
2.	
  Bitmap	
  Index	
  High	
  Cardinality	
  Columns	
  	
  
•  If	
  you	
  only	
  use	
  Bitmap	
  Indexes	
  for	
  low	
  cardinality	
  
   columns,	
  you’re	
  not	
  taking	
  full	
  advantage	
  of	
  them	
  
•  Suitable	
  for	
  all	
  columns	
  that	
  are	
  not	
  approaching	
  
   uniqueness	
  
•  BUT,	
  only	
  for	
  Data	
  Warehouse	
  environments	
  due	
  to	
  
   locking	
  implicaFons	
  of	
  concurrent	
  transacFons	
  
   within	
  same	
  table	
  


                                 The most comprehensive Oracle applications & technology content under one roof
3.	
  B-­‐Tree	
  Index	
  Low	
  Cardinality	
  Columns	
  
•  Generally	
  B-­‐Tree	
  Indexes	
  more	
  suitable	
  for	
  columns	
  
   with	
  many	
  disFnct	
  values	
  
•  Increases	
  selecFvity	
  and	
  makes	
  indexes	
  a	
  more	
  
   efficient	
  opFon	
  to	
  the	
  CBO	
  
•  However,	
  there	
  are	
  always	
  excepFons	
  
•  B-­‐Tree	
  Index	
  might	
  be	
  the	
  perfect	
  candidate	
  for	
  a	
  
   column	
  with	
  as	
  low	
  as	
  1	
  disFnct	
  value	
  ...	
  


                                 The most comprehensive Oracle applications & technology content under one roof
3.	
  B-­‐Tree	
  Index	
  Low	
  Cardinality	
  Columns	
  
 SQL>	
  create	
  table	
  bowie	
  (id	
  number,	
  code	
  number,	
  name	
  varchar2(50));	
  
 Table	
  created.	
  
 	
  	
  
 SQL>	
  create	
  index	
  bowie_code_i	
  on	
  bowie(code);	
  
 Index	
  created.	
  
 	
  
 SQL>	
  insert	
  into	
  bowie	
  select	
  rownum,	
  null,	
  'Ziggy	
  Stardust	
  and	
  the	
  Spiders	
  From	
  Mars'	
  from	
  dual	
  
 connect	
  by	
  level	
  <=	
  1000000;	
  
 1000000	
  rows	
  created.	
  
 	
  	
  
 SQL>	
  update	
  bowie	
  set	
  code	
  =	
  42	
  where	
  mod(id,10000)	
  =	
  0;	
  
 100	
  rows	
  updated.	
  
 	
  	
  
 SQL>	
  commit;	
  
 Commit	
  complete.	
  
 	
  
 SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>null,	
  tabname=>'BOWIE',	
  cascade=>	
  true,	
  
 esFmate_percent=>null,	
  method_opt=>'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  
 	
  	
  
 PL/SQL	
  procedure	
  successfully	
  completed.	
  


CODE	
  column	
  only	
  has	
  1	
  disFnct	
  value	
  although	
  most	
  rows	
  are	
  NULL	
  ...	
  


                                                                The most comprehensive Oracle applications & technology content under one roof
3.	
  B-­‐Tree	
  Index	
  Low	
  Cardinality	
  Columns	
  
SQL>	
  select	
  blevel,	
  leaf_blocks,	
  disFnct_keys	
  from	
  dba_indexes	
  where	
  index_name='BOWIE_CODE_I';	
  
	
  	
  
    BLEVEL LEAF_BLOCKS DISTINCT_KEYS
---------- ----------- -------------
         0           1             1
	
  
SQL>	
  select	
  column_name,	
  num_disFnct,	
  num_nulls	
  from	
  dba_tab_columns	
  where	
  table_name	
  =	
  
'BOWIE'	
  and	
  column_name	
  =	
  'CODE';	
  
	
  	
  
COLUMN_NAME NUM_DISTINCT NUM_NULLS
------------ ------------ ----------
CODE                    1     999900
	
  	
  


As	
  NULLs	
  are	
  not	
  stored	
  in	
  B-­‐Tree	
  Indexes	
  by	
  default,	
  index	
  is	
  Fny	
  
	
  
CBO	
  knows	
  there’s	
  only	
  1	
  disFnct	
  value	
  but	
  it	
  also	
  knows	
  most	
  rows	
  
are	
  only	
  NULLs	
  


                                                   The most comprehensive Oracle applications & technology content under one roof
3.	
  B-­‐Tree	
  Index	
  Low	
  Cardinality	
  Columns	
  
SQL>	
  select	
  *	
  from	
  bowie	
  where	
  code	
  =	
  42;	
  
	
  	
  
100	
  rows	
  selected.	
  
	
  	
  
Execution Plan
--------------------------------------------------------------------------------------------
| Id | Operation                    | Name         | Rows | Bytes | Cost (%CPU)| Time      |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |   100 | 4700 |    101   (0)| 00:00:02 |
|   1 | TABLE ACCESS BY INDEX ROWID| BOWIE         |   100 | 4700 |    101   (0)| 00:00:02 |
|* 2 |    INDEX RANGE SCAN          | BOWIE_CODE_I |   100 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------




CBO	
  will	
  happily	
  use	
  index	
  on	
  CODE	
  column	
  with	
  1	
  disFnct	
  value	
  
	
  
No	
  histograms	
  necessary	
  as	
  exisFng	
  staFsFcs	
  sufficient	
  for	
  CBO	
  to	
  
know	
  index	
  is	
  the	
  most	
  efficient	
  access	
  path	
  ...	
  



                                                                   The most comprehensive Oracle applications & technology content under one roof
4.	
  Index	
  Just	
  Which	
  Column	
  Values	
  You	
  
                              Want	
  
•  By	
  default,	
  all	
  values	
  within	
  a	
  column	
  are	
  indexed	
  
•  There	
  are	
  many	
  scenarios	
  when	
  you	
  may	
  not	
  want	
  
   to	
  index	
  all	
  values	
  within	
  a	
  column	
  
•  Some	
  column	
  values	
  maybe	
  too	
  numerous	
  to	
  be	
  of	
  
   pracFcal	
  use	
  within	
  the	
  index	
  
•  Some	
  column	
  values	
  may	
  unnecessarily	
  inflate	
  size	
  
   and	
  efficiency	
  of	
  index	
  
•  So,	
  just	
  don't	
  index	
  them	
  ...	
  


                                 The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
SQL>	
  CREATE	
  TABLE	
  index_some_stuff	
  (id	
  number,	
  status	
  varchar2(20),	
  descripFon	
  
varchar2(50));	
  
	
  Table	
  created.	
  
	
  	
  
SQL>	
  INSERT	
  INTO	
  index_some_stuff	
  SELECT	
  rownum,	
  'PROCESSED',	
  'NOT	
  REALLY	
  
INTERESTED	
  WITH	
  THIS	
  ROW'	
  FROM	
  DUAL	
  CONNECT	
  BY	
  LEVEL	
  <=	
  1000000;	
  
	
  1000000	
  rows	
  created.	
  
	
  	
  
SQL>	
  UPDATE	
  index_some_stuff	
  SET	
  status	
  =	
  'BOWIE',	
  descripFon	
  =	
  'ROW	
  OF	
  INTEREST'	
  
where	
  mod(id,10000)=42;	
  
	
  100	
  rows	
  updated.	
  
	
  	
  
SQL>	
  commit;	
  
	
  Commit	
  complete.	
  
	
  	
  
SQL>	
  SELECT	
  status,	
  count(*)	
  FROM	
  index_some_stuff	
  GROUP	
  BY	
  status;	
  
	
  	
  
STATUS                 COUNT(*)
-------------------- ----------
PROCESSED                999900
BOWIE                       100




                                                  The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
SQL>	
  CREATE	
  INDEX	
  index_some_stuff_i_1	
  ON	
  index_some_stuff(status);	
  
Index	
  created.	
  
	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>'BOWIE',	
  tabname=>	
  
’INDEX_SOME_STUFF',	
  method_opt=>	
  'FOR	
  COLUMNS	
  STATUS	
  SIZE	
  5');	
  
	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  
	
  
SQL>	
  SELECT	
  *	
  FROM	
  index_some_stuff	
  WHERE	
  status	
  =	
  'BOWIE';	
  
	
  	
  
100	
  rows	
  selected.	
  
	
  	
  
Execution Plan
----------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                      |   100 |  5200 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| INDEX_SOME_STUFF     |   100 |  5200 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | INDEX_SOME_STUFF_I_1 |   100 |       |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
        104 consistent gets
        100 rows processed




                                            The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
But	
  why	
  bother	
  indexing	
  all	
  the	
  common	
  values	
  when	
  they’ll	
  never	
  be	
  referenced	
  ?	
  
SQL>	
  CREATE	
  INDEX	
  index_some_stuff_i_2	
  ON	
  	
  
index_some_stuff(DECODE(status,	
  'BOWIE',	
  'BOWIE',	
  NULL))	
  COMPUTE	
  STATISTICS;	
  
Index	
  created.	
  
	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>'BOWIE',	
  tabname=>	
  
‘INDEX_SOME_STUFF',	
  method_opt=>'FOR	
  ALL	
  HIDDEN	
  COLUMNS	
  SIZE	
  1',	
  cascade=>	
  true);	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  
	
  
SQL>	
  SELECT	
  index_name,	
  blevel,	
  leaf_blocks,	
  disFnct_keys,	
  num_rows	
  	
  
FROM	
  dba_indexes	
  WHERE	
  owner='BOWIE'	
  AND	
  table_name='INDEX_SOME_STUFF';	
  
	
  
INDEX_NAME                         BLEVEL LEAF_BLOCKS DISTINCT_KEYS   NUM_ROWS
------------------------------ ---------- ----------- ------------- ----------
INDEX_SOME_STUFF_I_2                    0           1             1        100
INDEX_SOME_STUFF_I_1                    2        2924             2    1000000

 The	
  index	
  is	
  only	
  a	
  fracFon	
  the	
  size	
  of	
  the	
  previous	
  index	
  as	
  it	
  only	
  contains	
  the	
  
 one	
  index	
  entry	
  of	
  interest	
  



                                                       The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
SQL>	
  SELECT	
  *	
  FROM	
  bowie.index_some_stuff	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE(DECODE(status,	
  'BOWIE',	
  'BOWIE',	
  null))	
  =	
  'BOWIE';	
  
	
  
100 row selected.

----------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                      |   100 |  5300 |   101   (0)| 00:00:02 |
|   1 |  TABLE ACCESS BY INDEX ROWID| INDEX_SOME_STUFF     |   100 |  5300 |   101   (0)| 00:00:02 |
|*  2 |   INDEX RANGE SCAN          | INDEX_SOME_STUFF_I_2 |   100 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
        102 consistent gets
        100 rows processed




  Note:	
  consistent	
  gets	
  have	
  now	
  reduced	
  down	
  from	
  104	
  to	
  102	
  


                                                                     The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
Can	
  use	
  zero	
  sized	
  unusable	
  indexes	
  to	
  your	
  advantage	
  to	
  index	
  only	
  
useful	
  porFons	
  of	
  a	
  table.	
  Most	
  data	
  here	
  is	
  processed:	
  
SQL>	
  create	
  table	
  bowie_stuff	
  (id	
  number,	
  processed	
  varchar2(10));	
  
Table	
  created.	
  
	
  
SQL>	
  insert	
  into	
  bowie_stuff	
  select	
  rownum,	
  'YES'	
  from	
  dual	
  connect	
  by	
  level	
  <=	
  1000000;	
  
1000000	
  rows	
  created.	
  
	
  
SQL>	
  commit;	
  
Commit	
  complete.	
  
	
  
SQL>	
  update	
  bowie_stuff	
  set	
  processed	
  =	
  ‘NO’	
  where	
  id	
  in	
  (999990,	
  999992,	
  999994,	
  999996,	
  999998);	
  
5	
  rows	
  updated.	
  
	
  
SQL>	
  commit;	
  
Commit	
  complete.	
  
	
  
SQL>	
  create	
  index	
  bowie_stuff_i	
  on	
  bowie_stuff(processed)	
  pckree	
  0;	
  
Index	
  created.




                                                           The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
SQL>	
  select	
  index_name,	
  leaf_blocks	
  from	
  dba_indexes	
  where	
  index_name	
  =	
  'BOWIE_STUFF_I';	
  
	
  
INDEX_NAME                                                 LEAF_BLOCKS
------------------------------ -----------
BOWIE_STUFF_I                                                          1877
	
  
SQL>	
  select	
  segment_name,	
  blocks	
  from	
  dba_segments	
  where	
  segment_name	
  =	
  'BOWIE_STUFF_I';	
  
	
  
SEGMENT_NAME                                   BLOCKS
-------------------- ----------
BOWIE_STUFF_I                                      1920
	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>'BOWIE',	
  tabname=>'BOWIE_STUFF',	
  
esFmate_percent=>null,	
  cascade=>	
  true,	
  method_opt=>	
  'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  
	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  
	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>'BOWIE',	
  tabname=>'BOWIE_STUFF',	
  
esFmate_percent=>null,	
  method_opt=>	
  'FOR	
  COLUMNS	
  PROCESSED	
  SIZE	
  5');	
  
	
  
PL/SQL	
  procedure	
  successfully	
  completed.




                                                   The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
SQL>	
  select	
  *	
  from	
  bowie_stuff	
  where	
  processed	
  =	
  'NO';	
  
	
  
Execution Plan
---------------------------------------------------------------------------------------------
| Id | Operation                    | Name          | Rows | Bytes | Cost (%CPU)| Time      |
---------------------------------------------------------------------------------------------
|    0 | SELECT STATEMENT           |               |     5 |    40 |     4   (0)| 00:00:01 |
|    1 | TABLE ACCESS BY INDEX ROWID| BOWIE_STUFF   |     5 |    40 |     4   (0)| 00:00:01 |
|* 2 |     INDEX RANGE SCAN         | BOWIE_STUFF_I |     5 |       |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0 recursive calls
          0 db block gets
          6 consistent gets
          0 physical reads
          0 redo size
        540 bytes sent via SQL*Net to client
        396 bytes received via SQL*Net from client
          2 SQL*Net roundtrips to/from client
          0 sorts (memory)
          0 sorts (disk)
          5 rows processed




                                                                      The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
However	
  in	
  11g	
  R2,	
  if	
  we	
  now	
  recreate	
  the	
  index	
  as	
  a	
  parFFoned	
  
index	
  with	
  only	
  the	
  “useful”	
  porFon	
  of	
  the	
  index	
  usable	
  ...	
  
SQL>	
  drop	
  index	
  bowie_stuff_i;	
  
	
  
Index	
  dropped.	
  
	
  
SQL>	
  create	
  index	
  bowie_stuff_i	
  on	
  bowie_stuff(processed)	
  
	
  	
  2	
  	
  global	
  parFFon	
  by	
  range	
  (processed)	
  
	
  	
  3	
  	
  (parFFon	
  not_processed_part	
  values	
  less	
  than	
  ('YES'),	
  
	
  	
  4	
  	
  	
  parFFon	
  processed_part	
  values	
  less	
  than	
  (MAXVALUE))	
  
	
  	
  5	
  	
  unusable;	
  
	
  
Index	
  created.	
  
	
  
SQL>	
  alter	
  index	
  bowie_stuff_i	
  rebuild	
  parFFon	
  not_processed_part;	
  
	
  
Index	
  altered.




                                                  The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
We	
  now	
  only	
  use	
  a	
  fracFon	
  of	
  the	
  storage	
  for	
  the	
  index	
  and	
  the	
  
“useful”	
  porFon	
  of	
  the	
  indexed	
  data	
  is	
  just	
  a	
  single	
  leaf	
  block	
  in	
  size	
  ...	
  
SQL>	
  select	
  index_name,	
  parFFon_name,	
  leaf_blocks	
  from	
  dba_ind_parFFons	
  where	
  index_name	
  =	
  
'BOWIE_STUFF_I';	
  
	
  
INDEX_NAME                            PARTITION_NAME                       LEAF_BLOCKS
-------------------- -------------------- -----------
BOWIE_STUFF_I                         PROCESSED_PART                                     0
BOWIE_STUFF_I                         NOT_PROCESSED_PART                                 1
	
  
SQL>	
  select	
  segment_name,	
  parFFon_name,	
  blocks	
  from	
  dba_segments	
  where	
  segment_name	
  =	
  
'BOWIE_STUFF_I';	
  
	
  
SEGMENT_NAME                          PARTITION_NAME                             BLOCKS
-------------------- -------------------- ----------
BOWIE_STUFF_I                         NOT_PROCESSED_PART                                8




                                                    The most comprehensive Oracle applications & technology content under one roof
4.	
  Just	
  index	
  some	
  column	
  values	
  
SQL>	
  select	
  *	
  from	
  bowie_stuff	
  where	
  processed	
  =	
  'NO';	
  
	
  
Execution Plan
--------------------------------------------------------------------------------------------------------------
| Id | Operation                      | Name          | Rows | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------
|    0 | SELECT STATEMENT             |               |     5 |   45 |     1   (0)| 00:00:01 |       |       |
|    1 | PARTITION RANGE SINGLE       |               |     5 |   45 |     1   (0)| 00:00:01 |     1 |     1 |
|    2 |   TABLE ACCESS BY INDEX ROWID| BOWIE_STUFF   |     5 |   45 |     1   (0)| 00:00:01 |       |       |
|* 3 |      INDEX RANGE SCAN          | BOWIE_STUFF_I |     5 |      |     1   (0)| 00:00:01 |     1 |     1 |
--------------------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0 recursive calls
          0 db block gets
          4 consistent gets
          0 physical reads
          0 redo size
        542 bytes sent via SQL*Net to client
        395 bytes received via SQL*Net from client
          2 SQL*Net roundtrips to/from client
          0 sorts (memory)
          0 sorts (disk)
          5 rows processed


  Note:	
  The	
  query	
  itself	
  is	
  also	
  more	
  efficient	
  with	
  consistent	
  gets	
  
  reduced	
  from	
  6	
  down	
  to	
  4	
  ...	
  


                                                                                    The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
•  Generally	
  indexes	
  only	
  process	
  a	
  “small”	
  %	
  of	
  
   overall	
  data	
  
•  Cheaper	
  to	
  use	
  a	
  Full	
  Table	
  Scan	
  to	
  process	
  a	
  
   “high”	
  %	
  of	
  data	
  
•  Common	
  belief	
  that	
  if	
  returning	
  more	
  than	
  ‘x’%,	
  
   indexes	
  are	
  ignored	
  by	
  CBO	
  
•  However,	
  indexes	
  can	
  be	
  most	
  efficient	
  access	
  
   path	
  when	
  returning	
  anything	
  up	
  to	
  100%	
  of	
  data	
  


                               The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  create	
  table	
  ziggy	
  (id	
  number,	
  name	
  varchar2(30));	
  
Table	
  created.	
  
	
  	
  
SQL>	
  insert	
  into	
  ziggy	
  select	
  rownum,	
  'ZIGGY	
  STARDUST'	
  from	
  dual	
  connect	
  by	
  level	
  <=	
  
1000000;	
  
1000000	
  rows	
  created.	
  
	
  	
  
SQL>	
  commit;	
  
Commit	
  complete.	
  
	
  	
  
SQL>	
  delete	
  ziggy	
  where	
  id	
  between	
  1	
  and	
  999000;	
  
999000	
  rows	
  deleted.	
  
	
  	
  
SQL>	
  commit;	
  
Commit	
  complete.	
  
	
  
SQL>	
  create	
  index	
  ziggy_id_i	
  on	
  ziggy(id);	
  
Index	
  created.	
  
	
  	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>'BOWIE',	
  tabname=>'ZIGGY',	
  
cascade=>	
  true,	
  esFmate_percent=>null,	
  method_opt=>	
  'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  



                                                       The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  select	
  id	
  from	
  ziggy	
  where	
  id	
  >	
  1;	
  
	
  	
  
1000	
  rows	
  selected.	
  
	
  	
  
Execution Plan
-----------------------------------------------------------------------------------
| Id | Operation             | Name       | Rows | Bytes | Cost (%CPU)| Time      |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |            | 1000 | 5000 |       3   (0)| 00:00:01 |
|* 1 | INDEX FAST FULL SCAN| ZIGGY_ID_I | 1000 | 5000 |         3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------
	
  	
  



If	
  all	
  columns	
  of	
  interest	
  can	
  be	
  found	
  within	
  an	
  index,	
  an	
  
Index	
  Fast	
  Full	
  Scan	
  can	
  treat	
  the	
  index	
  as	
  a	
  “skinny”	
  table.	
  


                                                                 The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  select	
  *	
  from	
  ziggy	
  where	
  id	
  >	
  1;	
  
	
  	
  
1000	
  rows	
  selected.	
  
	
  	
  
Execution Plan
------------------------------------------------------------------------------------------
| Id | Operation                    | Name       | Rows | Bytes | Cost (%CPU)|Time      |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            | 1000 | 20000 |      8   (0)|00:00:01 |
|   1 | TABLE ACCESS BY INDEX ROWID| ZIGGY       | 1000 | 20000 |      8   (0)|00:00:01 |
|* 2 |    INDEX RANGE SCAN          | ZIGGY_ID_I | 1000 |        |     4   (0)|00:00:01 |
------------------------------------------------------------------------------------------



However,	
  because	
  the	
  table	
  is	
  so	
  fragmented,	
  the	
  CBO	
  is	
  
using	
  the	
  index	
  to	
  access	
  the	
  table	
  and	
  retrieve	
  100%	
  of	
  the	
  
rows	
  ...	
  

                                                                 The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  CREATE	
  TABLE	
  big_dwh_table_2	
  AS	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ORDER	
  BY	
  total_sales;	
  
	
  
Table	
  created.	
  
	
  
SQL>	
  CREATE	
  INDEX	
  big_dwh_album_id_i	
  ON	
  big_dwh_table(album_id);	
  
	
  
Index	
  created.	
  
	
  
SQL>	
  CREATE	
  INDEX	
  big_dwh_2_album_id_i	
  ON	
  big_dwh_table_2(album_id);	
  
	
  
Index	
  created.	
  
	
  
SQL>	
  SELECT	
  index_name,	
  leaf_blocks,	
  clustering_factor	
  FROM	
  user_indexes	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  index_name	
  like	
  'BIG_DWH%ALBUM_ID_I';	
  
	
  
INDEX_NAME                                                                         LEAF_BLOCKS CLUSTERING_FACTOR
------------------------------ ----------- -----------------
BIG_DWH_2_ALBUM_ID_I                                                                        2090          990282
BIG_DWH_ALBUM_ID_I                                                                          2090            4957



                                               The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  WHERE	
  album_id	
  BETWEEN	
  10	
  AND	
  20	
  ORDER	
  BY	
  id;	
  
	
  
1100	
  rows	
  selected.	
  
	
  
Execution Plan
----------------------------------------------------------------------------------------------
| Id | Operation                     | Name               | Rows| Bytes |Cost(%CPU)| Time    |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                    |1200 | 36000 |   12 (9)|00:00:01 |
|   1 | SORT ORDER BY                |                    |1200 | 36000 |   12 (9)|00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE      |1200 | 36000 |   11 (0)|00:00:01 |
|* 3 |     INDEX RANGE SCAN          | BIG_DWH_ALBUM_ID_I |1200 |       |   5   (0)|00:00:01 |
----------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          1 recursive calls
          0 db block gets
         11 consistent gets
          4 physical reads
          0 redo size
      30759 bytes sent via SQL*Net to client
        396 bytes received via SQL*Net from client
          2 SQL*Net roundtrips to/from client
          1 sorts (memory)
          0 sorts (disk)
       1100 rows processed




                                                  The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  WHERE	
  album_id	
  BETWEEN	
  10	
  AND	
  20	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ORDER	
  BY	
  album_id;	
  
	
  
1100 rows selected.
Execution Plan
----------------------------------------------------------------------------------------------
| Id | Operation                    | Name               | Rows | Bytes |Cost(%CPU)| Time    |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                    | 1200 | 36000 |    11 (0)|00:00:01|
|   1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE       | 1200 | 36000 |    11 (0)|00:00:01|
|* 2 |    INDEX RANGE SCAN          | BIG_DWH_ALBUM_ID_I | 1200 |        |    5 (0)|00:00:01|
----------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          1 recursive calls
          0 db block gets
         13 consistent gets
          0 physical reads
          0 redo size
      30759 bytes sent via SQL*Net to client
        396 bytes received via SQL*Net from client
          2 SQL*Net roundtrips to/from client
          0 sorts (memory)
          0 sorts (disk)
       1100 rows processed




                                                  The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  WHERE	
  album_id	
  BETWEEN	
  1	
  AND	
  10000	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ORDER	
  BY	
  album_id;	
  
	
  
Execution Plan
----------------------------------------------------------------------------------------------
| Id | Operation                    | Name               | Rows | Bytes |Cost(%CPU)| Time    |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                    | 1000K|     28M|7145   (2)|00:00:48|
|   1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE       | 1000K|     28M|7145   (2)|00:00:48|
|* 2 |    INDEX FULL SCAN           | BIG_DWH_ALBUM_ID_I | 1000K|        |2130   (2)|00:00:15|
---------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0 recursive calls
          0 db block gets
     139919 consistent gets
          0 physical reads
          0 redo size
   37476458 bytes sent via SQL*Net to client
     733722 bytes received via SQL*Net from client
      66668 SQL*Net roundtrips to/from client
          0 sorts (memory)
          0 sorts (disk)
    1000000 rows processed




                                                  The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  ORDER	
  BY	
  album_id;	
  
	
  
1000000	
  rows	
  selected.	
  
	
  
Execution Plan
--------------------------------------------------------------------------------------------
| Id | Operation           | Name          | Rows | Bytes |TempSpc| Cost (%CPU)| Time      |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |               | 1000K|     28M|       | 7699    (4)| 00:00:51 |
|   1 | SORT ORDER BY      |               | 1000K|     28M|    91M| 7699    (4)| 00:00:51 |
|   2 |   TABLE ACCESS FULL| BIG_DWH_TABLE | 1000K|     28M|       |   555 (10)| 00:00:04 |
--------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
         43 recursive calls
          5 db block gets
       4954 consistent gets
       5432 physical reads
          0 redo size
   37476485 bytes sent via SQL*Net to client
     733722 bytes received via SQL*Net from client
      66668 SQL*Net roundtrips to/from client
          0 sorts (memory)
          1 sorts (disk)
    1000000 rows processed




                                                The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table	
  WHERE	
  album_id	
  IS	
  NOT	
  NULL	
  ORDER	
  BY	
  album_id;	
  
	
  
1000000 rows selected.
Execution Plan
----------------------------------------------------------------------------------------------
| Id | Operation                    | Name               | Rows | Bytes |Cost(%CPU)| Time    |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                    | 1000K|     28M|7145   (2)|00:00:48|
|   1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE       | 1000K|     28M|7145   (2)|00:00:48|
|* 2 |    INDEX FULL SCAN           | BIG_DWH_ALBUM_ID_I | 1000K|        |2130   (2)|00:00:15|
----------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0 recursive calls
          0 db block gets
     139919 consistent gets
       7040 physical reads
          0 redo size
   37476493 bytes sent via SQL*Net to client
     733722 bytes received via SQL*Net from client
      66668 SQL*Net roundtrips to/from client
          0 sorts (memory)
          0 sorts (disk)
    1000000 rows processed




                                                 The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  *	
  FROM	
  big_dwh_table_2	
  WHERE	
  album_id	
  IS	
  NOT	
  NULL	
  ORDER	
  BY	
  album_id;	
  
	
  
1000000 rows selected.
Execution Plan
----------------------------------------------------------------------------------------------
| Id | Operation           | Name            | Rows | Bytes |TempSpc| Cost (%CPU)| Time      |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                 | 1000K|     28M|       | 7704    (4)| 00:00:51 |
|   1 | SORT ORDER BY      |                 | 1000K|     28M|    91M| 7704    (4)| 00:00:51 |
|* 2 |    TABLE ACCESS FULL| BIG_DWH_TABLE_2 | 1000K|     28M|       |   561 (11)| 00:00:04 |
----------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
         44 recursive calls
         18 db block gets
       4979 consistent gets
       7669 physical reads
          0 redo size
   36721186 bytes sent via SQL*Net to client
     733722 bytes received via SQL*Net from client
      66668 SQL*Net roundtrips to/from client
          0 sorts (memory)
          1 sorts (disk)
    1000000 rows processed




                                                 The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  /*+	
  index(a)	
  */	
  *	
  from	
  big_dwh_table_2	
  a	
  WHERE	
  album_id	
  IS	
  NOT	
  NULL	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ORDER	
  BY	
  album_id;	
  
	
  
1000000 rows selected.
Execution Plan
-------------------------------------------------------------------------------------------------
| Id | Operation                    | Name                 | Rows | Bytes |Cost (%CPU)|Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                      | 1000K|    28M| 993K (1)|01:49:31 |
|   1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE_2       | 1000K|    28M| 993K (1)|01:49:31 |
|* 2 |    INDEX FULL SCAN           | BIG_DWH_2_ALBUM_ID_I | 1000K|       | 2130   (2)|00:00:15 |
-------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0 recursive calls
          0 db block gets
    1059553 consistent gets
       7065 physical reads
          0 redo size
   36720213 bytes sent via SQL*Net to client
     733722 bytes received via SQL*Net from client
      66668 SQL*Net roundtrips to/from client
          0 sorts (memory)
          0 sorts (disk)
    1000000 rows processed




                                                        The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  *	
  from	
  big_dwh_table_2	
  WHERE	
  album_id	
  BETWEEN	
  1	
  AND	
  15	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ORDER	
  BY	
  album_id;	
  
	
  
1500 rows selected.
Execution Plan
------------------------------------------------------------------------------------
| Id | Operation           | Name            | Rows | Bytes | Cost(%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                 | 1500 | 45000 | 1297 (5)| 00:00:07|
|   1 | SORT ORDER BY      |                 | 1500 | 45000 | 1297 (5)| 00:00:07|
|* 2 |    TABLE ACCESS FULL| BIG_DWH_TABLE_2 | 1500 | 45000 | 1296 (4)| 00:00:07|
------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0 recursive calls
          0 db block gets
       4981 consistent gets
          0 physical reads
          0 redo size
      54139 bytes sent via SQL*Net to client
       1485 bytes received via SQL*Net from client
        101 SQL*Net roundtrips to/from client
          1 sorts (memory)
          0 sorts (disk)
       1500 rows processed




                                                   The most comprehensive Oracle applications & technology content under one roof
5.	
  100%	
  Index	
  SelecFvity	
  
SQL>	
  SELECT	
  *	
  from	
  big_dwh_table_2	
  WHERE	
  album_id	
  BETWEEN	
  1	
  AND	
  13	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ORDER	
  BY	
  album_id;	
  
	
  
1300 rows selected.
Execution Plan
-------------------------------------------------------------------------------------------------
| Id | Operation                    | Name                 | Rows | Bytes |Cost(%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                      | 1300| 39000 |1295    (1)| 00:00:07 |
|   1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE_2       | 1300| 39000 |1295    (1)| 00:00:07 |
|* 2 |    INDEX RANGE SCAN          | BIG_DWH_2_ALBUM_ID_I | 1300|        |   5   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0 recursive calls
          0 db block gets
       1385 consistent gets
         60 physical reads
          0 redo size
      47048 bytes sent via SQL*Net to client
       1342 bytes received via SQL*Net from client
         88 SQL*Net roundtrips to/from client
          0 sorts (memory)
          0 sorts (disk)
       1300 rows processed




                                                     The most comprehensive Oracle applications & technology content under one roof
6.	
  BLEVEL	
  1	
  =>	
  BLEVEL	
  2	
  	
  
Careful	
  of	
  indexes	
  increasing	
  from	
  BLEVEL	
  1	
  to	
  2.	
  Following	
  demo	
  
11.2.0.1	
  with	
  8K	
  block	
  size.	
  	
  
SQL>	
  create	
  table	
  major_tom	
  (id	
  number,	
  code	
  number,	
  name	
  varchar2(30));	
  
	
  Table	
  created.	
  
	
  	
  
SQL>	
  create	
  index	
  major_tom_i	
  on	
  major_tom(id);	
  
	
  Index	
  created.	
  
	
  	
  
SQL>	
  insert	
  into	
  major_tom	
  select	
  rownum,	
  mod(rownum,100),	
  'GROUND	
  CONTROL'	
  from	
  dual	
  
connect	
  by	
  level	
  <=336000;	
  
	
  336000	
  rows	
  created.	
  
	
  	
  	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>null,	
  tabname=>	
  'MAJOR_TOM',	
  cascade=>	
  
true,	
  esFmate_percent=>null,	
  method_opt=>'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  
	
  PL/SQL	
  procedure	
  successfully	
  completed.	
  
	
  
SQL>	
  select	
  blevel,	
  leaf_blocks,	
  num_rows,	
  clustering_factor	
  from	
  dba_indexes	
  wh	
  
ere	
  index_name='MAJOR_TOM_I';	
  
	
  
    BLEVEL LEAF_BLOCKS   NUM_ROWS CLUSTERING_FACTOR
---------- ----------- ---------- -----------------
         1         671     336000              1296	
  




                                                The most comprehensive Oracle applications & technology content under one roof
6.	
  BLEVEL	
  1	
  =>	
  BLEVEL	
  2	
  	
  
SQL>	
  select	
  *	
  from	
  major_tom	
  where	
  id	
  =	
  42;	
  
	
  	
  
Execution Plan
-------------------------------------------------------------------------------------------
| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |     1 |    23 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| MAJOR_TOM   |     1 |    23 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | MAJOR_TOM_I |     1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
 
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        531  bytes sent via SQL*Net to client
        395  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
          1  rows processed	
  


When	
  BLEVEL	
  =	
  1,	
  CBO	
  ignores	
  the	
  BLEVEL	
  from	
  its	
  calculaFons	
  


                                                                  The most comprehensive Oracle applications & technology content under one roof
6.	
  BLEVEL	
  1	
  =>	
  BLEVEL	
  2	
  	
  
Let’s	
  create	
  another	
  table,	
  with	
  a	
  CODE	
  column	
  that’s	
  has	
  100	
  
occurrences	
  of	
  each	
  value	
  ...	
  
SQL>	
  create	
  table	
  ziggy	
  (id	
  number,	
  code	
  number,	
  name	
  varchar2(30));	
  
	
  Table	
  created.	
  
	
  	
  
SQL>	
  insert	
  into	
  ziggy	
  select	
  rownum,	
  mod(rownum,10000),	
  'ZIGGY	
  STARDUST'	
  from	
  dual	
  connect	
  by	
  
level	
  <=	
  1000000;	
  
	
  1000000	
  rows	
  created.	
  
	
  
SQL>	
  commit;	
  
Commit	
  complete.	
  
	
  	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>null,	
  tabname=>	
  'ZIGGY',	
  cascade=>	
  true,	
  
esFmate_percent=>null,	
  method_opt=>'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  
	
  PL/SQL	
  procedure	
  successfully	
  completed.	
  




                                                        The most comprehensive Oracle applications & technology content under one roof
6.	
  BLEVEL	
  1	
  =>	
  BLEVEL	
  2	
  	
  
SQL>	
  select	
  *	
  from	
  ziggy	
  z,	
  major_tom	
  m	
  where	
  z.id	
  =	
  m.id	
  and	
  z.code	
  in	
  (42,	
  4242);	
  
	
  	
  
68	
  rows	
  selected.	
  
	
  	
  
Execution Plan
--------------------------------------------------------------------------------------------
| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |   200 |  9400 |  1372   (2)| 00:00:17 |
|   1 |  NESTED LOOPS                |             |       |       |            |          |
|   2 |   NESTED LOOPS               |             |   200 |  9400 |  1372   (2)| 00:00:17 |
|*  3 |    TABLE ACCESS FULL         | ZIGGY       |   200 |  4800 |  1105   (2)| 00:00:14 |
|*  4 |    INDEX RANGE SCAN          | MAJOR_TOM_I |     1 |       |     1   (0)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| MAJOR_TOM   |     1 |    23 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------




CBO	
  choose	
  a	
  Nest	
  Loop	
  as	
  the	
  cost	
  of	
  accessing	
  the	
  MAJOR_TOM	
  
table	
  100	
  Fmes	
  via	
  the	
  index	
  is	
  relaFvely	
  inexpensive	
  


                                                                    The most comprehensive Oracle applications & technology content under one roof
6.	
  BLEVEL	
  1	
  =>	
  BLEVEL	
  2	
  	
  
Let’s	
  just	
  add	
  another	
  500	
  rows	
  (or	
  0.15%	
  of	
  data)	
  
SQL>	
  insert	
  into	
  major_tom	
  select	
  rownum+336000,	
  mod(rownum,100),	
  'GROUND	
  CONTROL'	
  from	
  dual	
  
connect	
  by	
  level	
  <=500;	
  
	
  500	
  rows	
  created.	
  
	
  	
  
SQL>	
  commit;	
  
	
  Commit	
  complete.	
  
	
  	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>null,	
  tabname=>	
  'MAJOR_TOM',	
  cascade=>	
  true,	
  
esFmate_percent=>null,	
  method_opt=>'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  
	
  PL/SQL	
  procedure	
  successfully	
  completed.	
  
	
  	
  
	
  SQL>	
  select	
  blevel,	
  leaf_blocks,	
  num_rows,	
  clustering_factor	
  from	
  dba_indexes	
  where	
  index_name	
  =	
  
'MAJOR_TOM_I';	
  
	
  
    BLEVEL LEAF_BLOCKS   NUM_ROWS CLUSTERING_FACTOR
---------- ----------- ---------- -----------------
         2         672     336500              1298

Leaf	
  blocks	
  has	
  just	
  gone	
  up	
  by	
  just	
  1	
  but	
  it’s	
  enough	
  to	
  increase	
  the	
  
BLEVEL	
  to	
  2	
  ...	
  


                                                      The most comprehensive Oracle applications & technology content under one roof
6.	
  BLEVEL	
  1	
  =>	
  BLEVEL	
  2	
  	
  
SQL>	
  select	
  *	
  from	
  major_tom	
  where	
  id	
  =	
  42;	
  
	
  	
  
Execution Plan
-------------------------------------------------------------------------------------------
| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |     1 |    23 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| MAJOR_TOM   |     1 |    23 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | MAJOR_TOM_I |     1 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          5  consistent gets
          0  physical reads
          0  redo size
        531  bytes sent via SQL*Net to client
        395  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed


The	
  cost	
  of	
  accessing	
  1	
  row	
  has	
  gone	
  up	
  by	
  2	
  as	
  the	
  BLEVEL	
  is	
  no	
  
longer	
  ignored	
  by	
  the	
  CBO	
  ...	
  	
  


                                                                  The most comprehensive Oracle applications & technology content under one roof
6.	
  BLEVEL	
  1	
  =>	
  BLEVEL	
  2	
  	
  
  SQL>	
  select	
  *	
  from	
  ziggy	
  z,	
  major_tom	
  m	
  where	
  m.id	
  =	
  z.id	
  and	
  z.code	
  in	
  (42,	
  4242);	
  
  	
  	
  
  68	
  rows	
  selected.	
  
  	
  	
  
  Execution Plan
  --------------------------------------------------------------------------------
  | Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
  --------------------------------------------------------------------------------
  |   0 | SELECT STATEMENT   |           |   200 |  9400 |  1485   (2)| 00:00:18 |
  |*  1 |  HASH JOIN         |           |   200 |  9400 |  1485   (2)| 00:00:18 |
  |*  2 |   TABLE ACCESS FULL| ZIGGY     |   200 |  4800 |  1105   (2)| 00:00:14 |
  |   3 |   TABLE ACCESS FULL| MAJOR_TOM |   336K|  7558K|   378   (1)| 00:00:05 |
  --------------------------------------------------------------------------------


Nested	
  Loop	
  costs	
  (previously	
  1372)	
  have	
  gone	
  up	
  considerably	
  as	
  the	
  cost	
  has	
  gone	
  
up	
  by	
  2	
  for	
  each	
  iteraFon	
  of	
  the	
  loop.	
  
	
  
Hash	
  Join	
  and	
  FTS	
  now	
  selected	
  by	
  the	
  CBO	
  even	
  though	
  overall	
  size	
  of	
  index	
  is	
  similar.	
  
	
  
Index	
  BLEVEL	
  can	
  potenFally	
  toggle	
  between	
  1	
  and	
  2	
  and	
  result	
  in	
  variable	
  
performance	
  if	
  size	
  is	
  borderline	
  and	
  index	
  frequently	
  rebuilt	
  due	
  to	
  some	
  deleFons.	
  


                                                                      The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
•  Since	
  Oracle8,	
  Non-­‐Unique	
  Indexes	
  Can	
  Police	
  
   Primary	
  and	
  Unique	
  Key	
  Constraints	
  
•  Non-­‐Unique	
  Indexes	
  Necessary	
  For	
  Deferrable	
  
   and	
  NoValidate	
  Constraints	
  
•  Non-­‐Unique	
  Indexes	
  are	
  not	
  automaFcally	
  
   dropped	
  when	
  constraint	
  is	
  dropped	
  or	
  disabled	
  
•  However,	
  Unique	
  Indexes	
  are	
  not	
  outdated	
  and	
  
   are	
  generally	
  “beyer”	
  ...	
  


                            The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
SQL>	
  CREATE	
  TABLE	
  index_size_test	
  (id	
  NUMBER,	
  value	
  VARCHAR2(100)	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  CONSTRAINT	
  index_size_test_pk_1	
  PRIMARY	
  KEY);	
  
	
  
Table	
  created.	
  
	
  
SQL>	
  INSERT	
  INTO	
  index_size_test	
  VALUES	
  (1,	
  'DAVID	
  BOWIE');	
  
	
  
1	
  row	
  created.	
  
	
  
SQL>	
  COMMIT;	
  
	
  
Commit	
  complete.	
  
	
  
SQL>	
  SELECT	
  header_file,	
  header_block+1	
  FROM	
  dba_segments	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  segment_name	
  =	
  'INDEX_SIZE_TEST_PK_1';	
  
	
  
HEADER_FILE HEADER_BLOCK+1
----------- --------------
                                                  5              138370
	
  
SQL>	
  ALTER	
  SYSTEM	
  DUMP	
  DATAFILE	
  5	
  BLOCK	
  138370;	
  
	
  
System	
  altered.	
  



                                                 The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
row#0[8016]	
  flag:	
  -­‐-­‐-­‐-­‐-­‐-­‐,	
  lock:	
  2,	
  len=20,	
  data:(6):	
  	
  01	
  42	
  1c	
  7a	
  00	
  00	
  
col	
  0;	
  len	
  11;	
  (11):	
  	
  44	
  41	
  56	
  49	
  44	
  20	
  42	
  4f	
  57	
  49	
  45	
  

      SQL>	
  ALTER	
  TABLE	
  index_size_test	
  DROP	
  PRIMARY	
  KEY;	
  
      	
  
      Table	
  altered.	
  
      	
  
      SQL>	
  CREATE	
  INDEX	
  index_size_test_pk_2	
  ON	
  index_size_test(value);	
  
      	
  
      Index	
  created.	
  
      	
  
      SQL>	
  ALTER	
  TABLE	
  index_size_test	
  ADD	
  PRIMARY	
  KEY	
  (value);	
  
      	
  
      Table	
  altered.	
  

row#0[8015]	
  flag:	
  -­‐-­‐-­‐-­‐-­‐-­‐,	
  lock:	
  0,	
  len=21	
  
col	
  0;	
  len	
  11;	
  (11):	
  	
  44	
  41	
  56	
  49	
  44	
  20	
  42	
  4f	
  57	
  49	
  45	
  
col	
  1;	
  len	
  6;	
  (6):	
  	
  01	
  42	
  1c	
  7a	
  00	
  00	
  




                                                                          The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
SQL>	
  CREATE	
  TABLE	
  test1	
  AS	
  SELECT	
  rownum	
  id	
  FROM	
  dual	
  CONNECT	
  BY	
  LEVEL	
  <=	
  1000000;	
  
Table	
  created.	
  
	
  
SQL>	
  CREATE	
  INDEX	
  non_unique_idx	
  ON	
  test1(id)	
  PCTFREE	
  0;	
  
Index	
  created.	
  
	
  
SQL>	
  CREATE	
  TABLE	
  test2	
  AS	
  SELECT	
  rownum	
  id	
  FROM	
  dual	
  CONNECT	
  BY	
  LEVEL	
  <=	
  1000000;	
  
Table	
  created.	
  
	
  
SQL>	
  CREATE	
  UNIQUE	
  INDEX	
  non_unique_idx	
  ON	
  test2(id)	
  PCTFREE	
  0;	
  
Index	
  created.	
  
	
  
SQL>	
  exec	
  dbms_stats.gather_index_stats(ownname=>'BOWIE',	
  indname=>	
  
'NON_UNIQUE_IDX',	
  esFmate_percent=>	
  null);	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  
	
  
SQL>	
  exec	
  dbms_stats.gather_index_stats(ownname=>'BOWIE',	
  indname=>'UNIQUE_IDX',	
  
esFmate_percent=>	
  null);	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  
	
  



                                                    The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
SQL>	
  SELECT	
  index_name,	
  blevel,	
  leaf_blocks,	
  num_rows	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  FROM	
  dba_indexes	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  index_name	
  IN	
  ('NON_UNIQUE_IDX',	
  'UNIQUE_IDX');	
  
	
  
INDEX_NAME     BLEVEL LEAF_BLOCKS NUM_ROWS
-------------- ------ ----------- --------
NON_UNIQUE_IDX      2        1999 1000000
UNIQUE_IDX          2        1875 1000000




  The	
  Non-­‐Unique	
  Index	
  has	
  used	
  an	
  extra	
  124	
  blocks	
  or	
  
  approximately	
  6.6%	
  more	
  blocks	
  than	
  the	
  Unique	
  Index	
  	
  




                                                             The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
Unique	
  indexes	
  have	
  less	
  latching	
  and	
  CPU	
  related	
  overheads	
  ...	
  
SQL>	
  CREATE	
  TABLE	
  ziggy	
  (id	
  NUMBER,	
  name	
  VARCHAR2(30));	
  
	
  
Table	
  created.	
  
	
  
SQL>	
  INSERT	
  into	
  ziggy	
  SELECT	
  rownum,	
  'Bowie'	
  FROM	
  dual	
  CONNECT	
  BY	
  level	
  <=1000;	
  
	
  
1000	
  rows	
  created.	
  
	
  
SQL>	
  COMMIT;	
  
	
  
Commit	
  complete.	
  
	
  
SQL>	
  ALTER	
  TABLE	
  ziggy	
  ADD	
  PRIMARY	
  KEY	
  (id);	
  
	
  
Table	
  altered.	
  
	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>NULL,	
  tabname=>'ZIGGY',	
  
esFmate_percent=>	
  NULL,	
  method_opt=>	
  'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  
	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  



                                                  The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
In	
  one	
  session,	
  run	
  the	
  following	
  a	
  couple	
  of	
  Fmes	
  to	
  ensure	
  no	
  
recursive	
  SQL:	
  
SQL>	
  SELECT	
  *	
  FROM	
  ziggy	
  WHERE	
  id	
  =	
  10;	
  
	
  
   ID NAME
----- -----------------------
   10 Bowie



In	
  other	
  session,	
  run	
  the	
  following	
  (where	
  SID	
  =	
  the	
  sid	
  of	
  the	
  other	
  
session)	
  before	
  and	
  a‚er	
  an	
  execuFon	
  of	
  the	
  above	
  select	
  statement	
  
in	
  the	
  other	
  session.	
  
SQL>	
  SELECT	
  n.name,	
  s.value	
  FROM	
  v$sesstat	
  s,	
  v$statname	
  n	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  WHERE	
  s.staFsFc#	
  =	
  n.staFsFc#	
  AND	
  s.sid	
  =	
  123	
  AND	
  n.name	
  like	
  'consistent%';	
  




                                                                    The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
 NAME	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  VALUE	
  
 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
 consistent	
  gets	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  17703	
  
 consistent	
  gets	
  from	
  cache	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  17703	
  
 consistent	
  gets	
  -­‐	
  examinaFon	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  10536	
  


 NAME	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  VALUE	
  
 -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
 consistent	
  gets	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  17706	
  
 consistent	
  gets	
  from	
  cache	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  17706	
  
 consistent	
  gets	
  -­‐	
  examinaFon	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  10539	
  

Note	
  that	
  consistent	
  gets	
  increases	
  by	
  3,	
  consistent	
  gets	
  from	
  cache	
  increases	
  by	
  3,	
  
consistent	
  gets	
  -­‐	
  examinaFon	
  increases	
  by	
  3	
  (1	
  for	
  the	
  index	
  root	
  block,	
  1	
  for	
  the	
  
index	
  leaf	
  block	
  and	
  1	
  for	
  the	
  table	
  block).	
  That’s	
  a	
  total	
  of	
  3	
  CRs	
  and	
  3	
  latches	
  (as	
  all	
  
CRs	
  are	
  the	
  cheaper	
  ‘examinaFons’	
  which	
  only	
  require	
  1	
  latch	
  each)	
  



                                                                                                                                                                                                      The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
Now	
  the	
  same	
  test	
  but	
  this	
  Fme	
  with	
  a	
  non-­‐unique	
  index	
  ...	
  
SQL>	
  ALTER	
  TABLE	
  ziggy	
  DROP	
  PRIMARY	
  KEY;	
  
	
  
Table	
  altered.	
  
	
  
SQL>	
  ALTER	
  TABLE	
  ziggy	
  ADD	
  PRIMARY	
  KEY	
  (id)	
  USING	
  INDEX	
  
	
  	
  2	
  	
  (CREATE	
  INDEX	
  ziggy_id_i	
  ON	
  ziggy(id));	
  
	
  
Table	
  altered.	
  
	
  
SQL>	
  exec	
  dbms_stats.gather_table_stats(ownname=>NULL,	
  tabname=>'ZIGGY',	
  
esFmate_percent=>	
  NULL,	
  method_opt=>	
  'FOR	
  ALL	
  COLUMNS	
  SIZE	
  1');	
  
	
  
PL/SQL	
  procedure	
  successfully	
  completed.	
  



                                           The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
NAME	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  VALUE	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
consistent	
  gets	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  18504	
  
consistent	
  gets	
  from	
  cache	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  18504	
  
consistent	
  gets	
  -­‐	
  examinaFon	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  10949	
  


NAME	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  VALUE	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
consistent	
  gets	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  18508	
  
consistent	
  gets	
  from	
  cache	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  18508	
  
consistent	
  gets	
  -­‐	
  examinaFon	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  10950	
  

    Note	
  that	
  consistent	
  gets	
  increases	
  by	
  4	
  (not	
  3),	
  consistent	
  gets	
  from	
  cache	
  increases	
  by	
  4	
  
    (not	
  3),	
  consistent	
  gets	
  -­‐	
  examinaFon	
  increases	
  by	
  only	
  1(not	
  3).	
  	
  
    	
  
    In	
  summary,	
  there	
  are	
  4	
  not	
  3	
  CRs	
  with	
  only	
  the	
  root	
  block	
  acquired	
  via	
  a	
  1	
  latch	
  examinaFon	
  
    CR,	
  the	
  other	
  3	
  CRs	
  are	
  ‘full’	
  2	
  latch	
  gets	
  which	
  is	
  a	
  total	
  of	
  7	
  latches	
  (vs.	
  only	
  3	
  for	
  the	
  
    equivalent	
  unique	
  index).	
  



                                                                                                                                                                                                                          The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
Create	
  table	
  with	
  a	
  PK	
  and	
  ayempt	
  to	
  insert	
  duplicate	
  PK	
  rows	
  ...	
  
 SQL>	
  create	
  table	
  radiohead	
  (id	
  number	
  constraint	
  radiohead_pk_i	
  primary	
  key	
  using	
  index	
  (create	
  unique	
  index	
  
 radiohead_pk_i	
  on	
  radiohead(id)),	
  name	
  varchar2(20));	
  
 	
  
 Table	
  created.	
  
 	
  
 SQL>	
  select	
  index_name,	
  uniqueness,	
  table_name	
  from	
  dba_indexes	
  where	
  index_name	
  =	
  'RADIOHEAD_PK_I';	
  
 	
  
 INDEX_NAME                     UNIQUENES TABLE_NAME
 ------------------------------ --------- ------------------------------
 RADIOHEAD_PK_I                 UNIQUE    RADIOHEAD
 	
  
 SQL>	
  insert	
  into	
  radiohead	
  select	
  rownum,	
  'OK	
  COMPUTER'	
  from	
  dual	
  connect	
  by	
  level	
  <=	
  10;	
  
 	
  
 10	
  rows	
  created.	
  
 	
  
 SQL>	
  commit;	
  
 	
  
 Commit	
  complete.	
  
 	
  
 SQL>	
  insert	
  into	
  radiohead	
  select	
  rownum,	
  'OK	
  COMPUTER'	
  from	
  dual	
  connect	
  by	
  level	
  <=	
  12;	
  
 insert	
  into	
  radiohead	
  select	
  rownum,	
  'OK	
  COMPUTER'	
  from	
  dual	
  connect	
  by	
  level	
  <=	
  12	
  
 *	
  
 ERROR	
  at	
  line	
  1:	
  
 ORA-­‐00001:	
  unique	
  constraint	
  (BOWIE.RADIOHEAD_PK_I)	
  violated




                                                                       The most comprehensive Oracle applications & technology content under one roof
7.	
  Why	
  Unique	
  Indexes	
  Are	
  Beyer	
  
With	
  the	
  new	
  Oracle11g	
  Rel.	
  1	
  hint,	
  duplicate	
  violaFon	
  rows	
  are	
  automaFcally	
  
ignored.	
  /*+	
  ignore_row_on_dupkey_index(radiohead,radiohead_pk_i)	
  */	
  into	
  radiohead	
  select	
  rownum,	
  'OK	
  COMPUTER'	
  from	
  dual	
  
  SQL>	
  insert	
  
  connect	
  by	
  level	
  <=	
  12;	
  
  2	
  rows	
  created.	
  
  	
  
  SQL>	
  insert	
  /*+	
  ignore_row_on_dupkey_index(radiohead(id))	
  */	
  into	
  radiohead	
  select	
  rownum,	
  'OK	
  COMPUTER'	
  from	
  dual	
  connect	
  by	
  level	
  
  <=	
  13;	
  
  1	
  row	
  created.	
  
  	
  
  SQL>	
  commit;	
  
  Commit	
  complete.	
  
  	
  
  SQL>	
  select	
  *	
  from	
  radiohead;	
  
  	
  
          ID NAME
  ---------- --------------------
           1 OK COMPUTER
           2 OK COMPUTER
           3 OK COMPUTER
           4 OK COMPUTER
           5 OK COMPUTER
           6 OK COMPUTER
           7 OK COMPUTER
           8 OK COMPUTER
           9 OK COMPUTER
          10 OK COMPUTER
          11 OK COMPUTER
          12 OK COMPUTER
          13 OK COMPUTER
  13 rows selected.




                                                                           The most comprehensive Oracle applications & technology content under one roof
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf

Contenu connexe

Tendances

Scaling MySQL Strategies for Developers
Scaling MySQL Strategies for DevelopersScaling MySQL Strategies for Developers
Scaling MySQL Strategies for Developers
Jonathan Levin
 
Avoiding cursors with sql server 2005 tech republic
Avoiding cursors with sql server 2005   tech republicAvoiding cursors with sql server 2005   tech republic
Avoiding cursors with sql server 2005 tech republic
Kaing Menglieng
 
Understanding Query Execution
Understanding Query ExecutionUnderstanding Query Execution
Understanding Query Execution
webhostingguy
 

Tendances (20)

Agile Database Development with JSON
Agile Database Development with JSONAgile Database Development with JSON
Agile Database Development with JSON
 
IR SQLite Session #1
IR SQLite Session #1IR SQLite Session #1
IR SQLite Session #1
 
Oracle training in hyderabad
Oracle training in hyderabadOracle training in hyderabad
Oracle training in hyderabad
 
Scaling MySQL Strategies for Developers
Scaling MySQL Strategies for DevelopersScaling MySQL Strategies for Developers
Scaling MySQL Strategies for Developers
 
Recipe 14 of Data Warehouse and Business Intelligence - Build a Staging Area ...
Recipe 14 of Data Warehouse and Business Intelligence - Build a Staging Area ...Recipe 14 of Data Warehouse and Business Intelligence - Build a Staging Area ...
Recipe 14 of Data Warehouse and Business Intelligence - Build a Staging Area ...
 
Profiling Oracle with GDB
Profiling Oracle with GDBProfiling Oracle with GDB
Profiling Oracle with GDB
 
How to analyze and tune sql queries for better performance percona15
How to analyze and tune sql queries for better performance percona15How to analyze and tune sql queries for better performance percona15
How to analyze and tune sql queries for better performance percona15
 
Avoiding cursors with sql server 2005 tech republic
Avoiding cursors with sql server 2005   tech republicAvoiding cursors with sql server 2005   tech republic
Avoiding cursors with sql server 2005 tech republic
 
Understanding Query Execution
Understanding Query ExecutionUnderstanding Query Execution
Understanding Query Execution
 
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
 
1 Installing & getting started with R
1 Installing & getting started with R1 Installing & getting started with R
1 Installing & getting started with R
 
Mini Session - Using GDB for Profiling
Mini Session - Using GDB for ProfilingMini Session - Using GDB for Profiling
Mini Session - Using GDB for Profiling
 
plsql Les09
 plsql Les09 plsql Les09
plsql Les09
 
plsql Les08
plsql Les08 plsql Les08
plsql Les08
 
OTN TOUR 2016 - DBA Commands and Concepts That Every Developer Should Know
OTN TOUR 2016 - DBA Commands and Concepts That Every Developer Should KnowOTN TOUR 2016 - DBA Commands and Concepts That Every Developer Should Know
OTN TOUR 2016 - DBA Commands and Concepts That Every Developer Should Know
 
In Search of Plan Stability - Part 1
In Search of Plan Stability - Part 1In Search of Plan Stability - Part 1
In Search of Plan Stability - Part 1
 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performance
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql features
 
Optimizer Histograms: When they Help and When Do Not?
Optimizer Histograms: When they Help and When Do Not?Optimizer Histograms: When they Help and When Do Not?
Optimizer Histograms: When they Help and When Do Not?
 
Schemadoc
SchemadocSchemadoc
Schemadoc
 

Similaire à Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf

Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf
Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdfDatabase & Technology 1 _ Tom Kyte _ SQL Techniques.pdf
Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf
InSync2011
 
Myth busters - performance tuning 101 2007
Myth busters - performance tuning 101 2007Myth busters - performance tuning 101 2007
Myth busters - performance tuning 101 2007
paulguerin
 
MySQL Goes to 8! FOSDEM 2020 Database Track, January 2nd, 2020
MySQL Goes to 8!  FOSDEM 2020 Database Track, January 2nd, 2020MySQL Goes to 8!  FOSDEM 2020 Database Track, January 2nd, 2020
MySQL Goes to 8! FOSDEM 2020 Database Track, January 2nd, 2020
Geir Høydalsvik
 
android sqlite
android sqliteandroid sqlite
android sqlite
Deepa Rani
 

Similaire à Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf (20)

Top 10 Oracle SQL tuning tips
Top 10 Oracle SQL tuning tipsTop 10 Oracle SQL tuning tips
Top 10 Oracle SQL tuning tips
 
Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf
Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdfDatabase & Technology 1 _ Tom Kyte _ SQL Techniques.pdf
Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf
 
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
 
Is SQLcl the Next Generation of SQL*Plus?
Is SQLcl the Next Generation of SQL*Plus?Is SQLcl the Next Generation of SQL*Plus?
Is SQLcl the Next Generation of SQL*Plus?
 
Sql lite android
Sql lite androidSql lite android
Sql lite android
 
Top 10 tips for Oracle performance
Top 10 tips for Oracle performanceTop 10 tips for Oracle performance
Top 10 tips for Oracle performance
 
Chapter 3.pptx Oracle SQL or local Android database setup SQL, SQL-Lite, codi...
Chapter 3.pptx Oracle SQL or local Android database setup SQL, SQL-Lite, codi...Chapter 3.pptx Oracle SQL or local Android database setup SQL, SQL-Lite, codi...
Chapter 3.pptx Oracle SQL or local Android database setup SQL, SQL-Lite, codi...
 
从 Oracle 合并到 my sql npr 实例分析
从 Oracle 合并到 my sql   npr 实例分析从 Oracle 合并到 my sql   npr 实例分析
从 Oracle 合并到 my sql npr 实例分析
 
Myth busters - performance tuning 101 2007
Myth busters - performance tuning 101 2007Myth busters - performance tuning 101 2007
Myth busters - performance tuning 101 2007
 
MySQL Goes to 8! FOSDEM 2020 Database Track, January 2nd, 2020
MySQL Goes to 8!  FOSDEM 2020 Database Track, January 2nd, 2020MySQL Goes to 8!  FOSDEM 2020 Database Track, January 2nd, 2020
MySQL Goes to 8! FOSDEM 2020 Database Track, January 2nd, 2020
 
War of the Indices- SQL Server and Oracle
War of the Indices-  SQL Server and OracleWar of the Indices-  SQL Server and Oracle
War of the Indices- SQL Server and Oracle
 
12c Database new features
12c Database new features12c Database new features
12c Database new features
 
Oracle notes
Oracle notesOracle notes
Oracle notes
 
When to no sql and when to know sql javaone
When to no sql and when to know sql   javaoneWhen to no sql and when to know sql   javaone
When to no sql and when to know sql javaone
 
Rdbms day3
Rdbms day3Rdbms day3
Rdbms day3
 
android sqlite
android sqliteandroid sqlite
android sqlite
 
DBA Commands and Concepts That Every Developer Should Know - Part 2
DBA Commands and Concepts That Every Developer Should Know - Part 2DBA Commands and Concepts That Every Developer Should Know - Part 2
DBA Commands and Concepts That Every Developer Should Know - Part 2
 
DBA Commands and Concepts That Every Developer Should Know - Part 2
DBA Commands and Concepts That Every Developer Should Know - Part 2DBA Commands and Concepts That Every Developer Should Know - Part 2
DBA Commands and Concepts That Every Developer Should Know - Part 2
 
Public Training SQL Implementation & Embedded Programming in IBM i (05-09 Jun...
Public Training SQL Implementation & Embedded Programming in IBM i (05-09 Jun...Public Training SQL Implementation & Embedded Programming in IBM i (05-09 Jun...
Public Training SQL Implementation & Embedded Programming in IBM i (05-09 Jun...
 
Public Training SQL Implementation & Embedded Programming in IBM i
Public Training SQL Implementation & Embedded Programming in IBM iPublic Training SQL Implementation & Embedded Programming in IBM i
Public Training SQL Implementation & Embedded Programming in IBM i
 

Plus de InSync2011

Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
InSync2011
 
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdfNew & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
InSync2011
 
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdfOracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
InSync2011
 
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdfReporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
InSync2011
 
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
InSync2011
 
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
InSync2011
 
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
InSync2011
 
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
InSync2011
 
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
InSync2011
 
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdfDatabase & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
InSync2011
 
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
InSync2011
 
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
InSync2011
 
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
InSync2011
 
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
InSync2011
 
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
InSync2011
 
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
InSync2011
 
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
InSync2011
 
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
InSync2011
 
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
InSync2011
 
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
InSync2011
 

Plus de InSync2011 (20)

Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
Developer & Fusion Middleware 2 _ Scott Robertson _ SOA, Portals and Enterpri...
 
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdfNew & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
New & Emerging _ KrisDowney _ Simplifying the Change Process.pdf
 
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdfOracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
Oracle Systems _ Kevin McIsaac _The IT landscape has changed.pdf
 
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdfReporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
Reporting _ Scott Tunbridge _ Op Mgmt to Perf Excel.pdf
 
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
Developer and Fusion Middleware 2 _ Scott Robertson _ SOA, portals and entepr...
 
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
Primavera _ Loretta Bayliss _ Implementing EPPM in rapidly changing and compe...
 
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
Database & Technology 1 _ Martin Power _ Delivering Oracles hight availabilit...
 
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
Database & Technology 1 _ Craig Shallahamer _ Unit of work time based perform...
 
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
Database & Technology 1 _ Marcelle Kratchvil _ Why you should be storing unst...
 
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdfDatabase & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
Database & Technology 1 _ Milina Ristic _ Why use oracle data guard.pdf
 
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
 
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
Databse & Technology 2 _ Francisco Munoz Alvarez _ Oracle Security Tips - Som...
 
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
Databse & Technology 2 _ Francisco Munoz alvarez _ 11g new functionalities fo...
 
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
Databse & Technology 2 | Connor McDonald | Managing Optimiser Statistics - A ...
 
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
Databse & Technology 2 _ Shan Nawaz _ Oracle 11g Top 10 features - not your u...
 
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
Databse & Technology 2 _ Paul Guerin _ The biggest looser database - a boot c...
 
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
Developer and Fusion Middleware 1 _ Kevin Powe _ Log files - a wealth of fore...
 
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
Developer and Fusion Middleware 2 _ Aaron Blishen _ Event driven SOA Integrat...
 
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
Developer and Fusion Middleware 2 _Greg Kirkendall _ How Australia Post teach...
 
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
Developer and Fusion Middleware 1 _ Paul Ricketts _ Paper Process Automation ...
 

Dernier

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Dernier (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 

Database & Technology 2 _ Richard Foote _ 10 things you probably dont know about Oracle's indexes.pdf

  • 1. 10  Things  You  Might  Not  Know   About  Oracle  Indexes   Richard  Foote   The most comprehensive Oracle applications & technology content under one roof
  • 2. Richard  Foote   •  Working  in  IT  for  25  years  (scary  stuff)   •  Working  with  Oracle  for  15  years  (almost  as  scary)   •  Previously  employed  by  Oracle  CorporaFon  for  5  ½  years  (scary  as  hell)   •  Currently  employed  by  the  Australian  Federal  Government  as  a  Senior   DBA   •  Responsible  for  many  large  scale,  mission  criFcal,  “life-­‐dependant”   classified  Oracle  systems   •  Based  in  sunny  Canberra,  Australia   •  Oracle  OakTable  member  since  2002  and  Oracle  ACE  Director  since  2008   •  Interests  includes  all  sports  and  music  (cool  stuff  like  David  Bowie,  Pink   Floyd,  Radiohead  and  Muse)   •  richard.foote@bigpond.com   •  Richard  Foote’s  Oracle  Blog:  hBp://richardfoote.wordpress.com/   The most comprehensive Oracle applications & technology content under one roof
  • 3. 1.  Delete  More  Rows  To  Reduce   Deleted  Space  Within  An  Index   •  Very  common  advice  to  rebuild  index  if  percentage   of  deleted  space  >  20%   •  For  example  -­‐  Metalink  Note:  122008.1   recommended  this  for  many  years   •  Validate  index  structure  (Ignoring  that  it’s   expensive  and  locks  the  table)   •  Claimed  rebuild  will  remove  index  “deadwood”  and   make  index  more  efficient   •  However,  if  only  we  just  deleted  even  more  rows  ...   The most comprehensive Oracle applications & technology content under one roof
  • 4. 1:  If  deleted  space  >20%,  delete  some  more!!   SQL>  create  table  radiohead  (id  number,  name  varchar2(20));   Table  created.       SQL>  insert  into  radiohead  select  rownum,  'OK  COMPUTER'  from  dual  connect  by  level  <=   100000;   100000  rows  created.       SQL>  commit;   Commit  complete.       SQL>  create  index  radiohead_i  on  radiohead(id)  pckree  0;   Index  created.       SQL>  analyze  index  radiohead_i  validate  structure;   Index  analyzed.       SQL>  select  lf_rows,  del_lf_rows,  round((del_lf_rows/lf_rows)*100)  PCT_DEL,  pct_used  from   index_stats;          LF_ROWS DEL_LF_ROWS    PCT_DEL   PCT_USED ---------- ----------- ---------- ----------     100000           0          0        100 The most comprehensive Oracle applications & technology content under one roof
  • 5. 1:  If  deleted  space  >20%,  delete  some  more!!   SQL>  delete  radiohead  where  mod(id,10)  IN  (2,4,6);   30000  rows  deleted.       SQL>  commit;   Commit  complete.     SQL>  analyze  index  radiohead_i  validate  structure;   Index  analyzed.       SQL>  select  lf_rows,  del_lf_rows,  (del_lf_rows/lf_rows)*100  PCT_DEL,  pct_used  from   index_stats;          LF_ROWS DEL_LF_ROWS    PCT_DEL   PCT_USED ---------- ----------- ---------- ----------     100000       30000         30        100 So  based  on  common  rebuild  criteria,  this  index  really   should  be  rebuilt  ...   The most comprehensive Oracle applications & technology content under one roof
  • 6. 1:  If  deleted  space  >20%,  delete  some  more!!   Well,  let’s  just  delete  some  more  rows  ...   SQL>  delete  radiohead  where  mod(id,10)  =  8;    10000  rows  deleted.       SQL>  commit;   Commit  complete.       SQL>  analyze  index  radiohead_i  validate  structure;   Index  analyzed.       SQL>  select  lf_rows,  del_lf_rows,  round((del_lf_rows/lf_rows)*100)  PCT_DEL,  pct_used   from  index_stats;          LF_ROWS DEL_LF_ROWS    PCT_DEL   PCT_USED ---------- ----------- ---------- ----------      70000       10000         14         70 The most comprehensive Oracle applications & technology content under one roof
  • 7. 1:  If  deleted  space  >20%,  delete  some  more!!   •  What  many  don’t  realise  is  that  in  most  scenarios,   deleted  space  is  the  same  as  free  space   •  It  will  generally  eventually  get  reused   •  To  clean  out  deleted  space,  it  just  takes  the  leaf   block  to  be  modified  by  a  subsequent  transacFon   •  The  criteria  actually  rebuilds  indexes  that  don’t  need   rebuilding,  and   •  The  criteria  misses  out  on  those  indexes  that  might   actually  need  rebuilding   The most comprehensive Oracle applications & technology content under one roof
  • 8. 2.Bitmap  Index  High  Cardinality  Columns     •  Very  common  advice  to  only  use  Bitmap  Index  with   “Low”  Cardinality  Columns   •  Generally  columns  with  less  than  20  disFnct  values   •  Examples:  Eye/Hair  Colour,  Sex,  States  of  Australia...   •  A  column  with  say  10,000  disFnct  values  would  be  far   too  many  and  result  in  huge,  inefficient  index     •  A  column  on  say  person  first  name  or  surname  would   be  totally  unsuitable  for  a  Bitmap  Index   •  But  would  it  really  ...   The most comprehensive Oracle applications & technology content under one roof
  • 9. 2.Bitmap  Index  High  Cardinality  Columns     SQL>  CREATE  TABLE  big_dwh_table  (id  NUMBER,  album_id  NUMBER,  arFst_id  NUMBER,  country_id  NUMBER,                                                                                                                                        format_id  NUMBER,  release_date  DATE,  total_sales  NUMBER);   Table  created.     SQL>  CREATE  SEQUENCE  dwh_seq;   Sequence  created.     SQL>  create  or  replace  procedure  pop_big_dwh_table  as      2    v_id                    number;      3    v_arFst_id      number;      4    begin      5        for  v_album_id  in  1..10000  loop      6                v_arFst_id:=  ceil(dbms_random.value(0,100));      7                for  v_country_id  in  1..100  loop      8                    select  dwh_seq.nextval  into  v_id  from  dual;      9                    insert  into  big_dwh_table  values  (v_id,  v_album_id,  v_arFst_id,  vcountry_id,  ceil(dbms_random.value(0,4)),                                                                      trunc(sysdate-­‐mod(v_id,ceil(dbms_random.value(0,1000)))),  ceil(dbms_random.value(0,500000)));    10              end  loop;    11        end  loop;    12  commit;    13  end;    14  /   Procedure  created.     SQL>  exec  pop_big_dwh_table   PL/SQL  procedure  successfully  completed.   The most comprehensive Oracle applications & technology content under one roof
  • 10. 2.Bitmap  Index  High  Cardinality  Columns     OK,  let’s  start  with  a  B-­‐Tree  Index   SQL>  CREATE  INDEX  big_dwh_album_id_i  ON  big_dwh_table(album_id)                        COMPUTE  STATISTICS;     Index  created.     SQL>  SELECT  i.index_type,  i.disFnct_keys,  t.num_rows  "T  ROWS",  t.blocks  "T  BLOCKS",                                                  i.num_rows  "I  ROWS",  i.clustering_factor  CF,  i.leaf_blocks                        FROM  user_indexes  i,  user_tables  t                        WHERE  i.table_name=t.table_name  and  i.index_name  =  'BIG_DWH_ALBUM_ID_I';     INDEX_TYPE DISTINCT_KEYS T ROWS T BLOCKS I ROWS CF LEAF_BLOCKS ---------- ------------- ---------- ---------- ---------- ---------- ----------- NORMAL 10000 1000000 4948 1000000 4951 2090 Note  the  album_id  column  has  a  relaFvely  “high”  cardinality  at   10,000  disFnct  values.  Also  note  the  B-­‐Tree  Index  is  extremely  well   clustered  (CF  matches  blocks  in  table)  and  has  2090  leaf  blocks  ...     The most comprehensive Oracle applications & technology content under one roof
  • 11. 2.  Bitmap  Index  High  Cardinality  Columns     SQL>  SELECT  *  FROM  big_dwh_table  WHERE  album_id  =  42;     100 rows selected. Execution Plan ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100 | 3000 | 103 (0)|00:00:02| | 1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE_2 | 100 | 3000 | 103 (0)|00:00:02| |* 2 | INDEX RANGE SCAN | BIG_DWH_2_ALBUM_ID_I | 100 | | 3 (0)|00:00:01| ------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 19 consistent gets 100 rows processed Note:  As  expected,  the  index  is  used  to  retrieve  the  relaFvely  few   100  rows  (0.01%  of  data).       Just  19  consistent  reads  required  ...   The most comprehensive Oracle applications & technology content under one roof
  • 12. 2.Bitmap  Index  High  Cardinality  Columns     Let’s  create  same  index  as  a  Bitmap  Index.  However,  with  10,000   disFnct  values,  unlikely  to  be  efficient,  right  ?   SQL>  DROP  INDEX  big_dwh_album_id_i;     Index  dropped.     SQL>  CREATE  BITMAP  INDEX  big_dwh_album_id_i  ON  big_dwh_table(album_id);     Index  created.     SQL>  SELECT  index_name,  index_type,  disFnct_keys,  num_rows,  leaf_blocks,  blocks                        FROM  user_indexes  i,  user_segments  s                        WHERE  i.index_name  =  s.segment_name  and  i.index_name  =  'BIG_DWH_ALBUM_ID_I';     INDEX_NAME INDEX_TYPE DISTINCT_KEYS NUM_ROWS LEAF_BLOCKS BLOCKS ------------------ ---------- ------------- -------- ----------- ------ BIG_DWH_ALBUM_ID_I BITMAP 10000 10000 56 128 Wrong.  The  number  of  index  rows  is  just  10000,  one  for  each  disFnct   value  and  leaf  blocks  has  dropped  from  2090  to  just  56  !!   The most comprehensive Oracle applications & technology content under one roof
  • 13. 2.  Bitmap  Index  High  Cardinality  Columns     SQL>  SELECT  *  FROM  big_dwh_table  WHERE  album_id  =  42;     100 rows selected. Execution Plan ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100 | 3000 | 22 (0)|00:00:01| | 1 | TABLE ACCESS BY INDEX ROWID | BIG_DWH_TABLE | 100 | 3000 | 22 (0)|00:00:01| | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | |* 3 | BITMAP INDEX SINGLE VALUE | BIG_DWH_ALBUM_ID_I | | | | | ------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 11 consistent gets 100 rows processed Note:  Not  only  is  the  index  used,  but  the  number  of  consistent  reads   has  dropped  from  19  to  just  11  !!   The most comprehensive Oracle applications & technology content under one roof
  • 14. 2.  Bitmap  Index  High  Cardinality  Columns     The  Clustering  Factor  of  an  index  has  a  big  impact  on  the  overall  size  of  a  Bitmap  Index     This  is  due  to  having  more  conFnuous  zeros  in  the  bitmap  string  that  can  be  more  efficiently   compressed     SQL>  SELECT  i.index_name,  i.index_type,  t.num_rows  "TABLE  ROWS",  t.blocks,                                                  i.num_rows  "INDEX  ROWS",  i.clustering_factor  CF,  i.leaf_blocks                      FROM  user_indexes  i,  user_tables  t                        WHERE  i.table_name=t.table_name  and  i.index_name  =  'BIG_DWH_ALBUM_ID_I';     INDEX_NAME INDEX_TYPE TABLE ROWS BLOCKS INDEX ROWS CF LEAF_BLOCKS ------------------ ---------- ---------- ------- ---------- ------ ----------- BIG_DWH_ALBUM_ID_I BITMAP 1000000 4948 10000 10000 56 Note  the  CF  as  recorded  for  Bitmap  Indexes  is  a  liyle  meaningless  as  a  specific  index  entry   covers  many  Rowids  but  the  CF  calculaFon  is  sFll  based  on  the  block  within  the  rowid   changing  from  one  index  entry  to  the  next.     Therefore,  CF  of  an  index  is  commonly  recorded  as  being  the  number  of  index  row  entries   The most comprehensive Oracle applications & technology content under one roof
  • 15. 2.  Bitmap  Index  High  Cardinality  Columns     Create  a  copy  of  the  table  but  this  Fme  clustered  by  the   TOTAL_SALES  column     Then  create  a  Bitmap  Index  on  the  now  poorly  clustered  ALBUM_ID   column   SQL>  CREATE  TABLE  big_dwh_table_2  AS  SELECT  *  FROM  big_dwh_table                        ORDER  BY  total_sales;     Table  created.     SQL>  CREATE  BITMAP  INDEX  big_dwh_2_album_id_i  ON  big_dwh_table_2(album_id);     Index  created.     SQL>  exec  dbms_stats.gather_table_stats(ownname=>null,  tabname=>  'BIG_DWH_TABLE_2',   esFmate_percent=>  null,  cascade=>  true,  method_opt=>  'FOR  ALL  COLUMNS  SIZE  1');     PL/SQL  procedure  successfully  completed.   The most comprehensive Oracle applications & technology content under one roof
  • 16. 2.  Bitmap  Index  High  Cardinality  Columns     SQL>  SELECT  i.index_name,  i.index_type,  t.num_rows  "TABLE  ROWS",  t.blocks,                                                  i.num_rows  "INDEX  ROWS",  i.clustering_factor  CF,  i.leaf_blocks                        FROM  user_indexes  i,  user_tables  t                        WHERE  i.table_name=t.table_name  and  i.index_name  =  'BIG_DWH_2_ALBUM_ID_I';     INDEX_NAME INDEX_TYPE TABLE ROWS BLOCKS INDEX ROWS CF LEAF_BLOCKS -------------------- ---------- ---------- ------- ---------- ------ ----------- BIG_DWH_2_ALBUM_ID_I BITMAP 1000000 4973 10000 10000 455 Note:  Leaf  Blocks  has  jumped  up  significantly  from  56  blocks  to  455   blocks     The most comprehensive Oracle applications & technology content under one roof
  • 17. 2.  Bitmap  Index  High  Cardinality  Columns     SQL>  SELECT  *  FROM  big_dwh_table_2  WHERE  album_id  =  42;     100 rows selected. Execution Plan ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost (%CPU)|Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100| 3000 | 22 (0)|00:00:01| | 1 | TABLE ACCESS BY INDEX ROWID | BIG_DWH_TABLE_2 | 100| 3000 | 22 (0)|00:00:01| | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | |* 3 | BITMAP INDEX SINGLE VALUE | BIG_DWH_2_ALBUM_ID_I | | | | | ------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 101 consistent gets 100 rows processed Note:  The  number  of  consistent  reads  has  now  jumped  up  from  11  to   101  ...   The most comprehensive Oracle applications & technology content under one roof
  • 18. 2.  Bitmap  Index  High  Cardinality  Columns     Of  course,  this  will  also  impact  Clustering  Factor  of  a  B-­‐Tree  Index  ...   SQL>  DROP  INDEX  big_dwh_2_album_id_i;     Index  dropped.     SQL>  CREATE  INDEX  big_dwh_2_album_id_i  ON  big_dwh_table_2(album_id);     Index  created.     SQL>  SELECT  i.index_name,  i.index_type,  t.num_rows  "TABLE  ROWS",  t.blocks,                                                  i.num_rows  "INDEX  ROWS",  i.clustering_factor  CF,  i.leaf_blocks                        FROM  user_indexes  i,  user_tables  t                        WHERE  i.table_name=t.table_name  and  i.index_name  =  'BIG_DWH_2_ALBUM_ID_I';     INDEX_NAME INDEX_TYPE TABLE ROWS BLOCKS INDEX ROWS CF LEAF_BLOCKS -------------------- ---------- ---------- ------- ---------- ------- ----------- BIG_DWH_2_ALBUM_ID_I NORMAL 1000000 4973 1000000 990003 2090 Although  the  index  has  same  no.  of  leaf  blocks,  the  Clustering  Factor   has  jumped  to  a  massive  990003  ...   The most comprehensive Oracle applications & technology content under one roof
  • 19. 2.  Bitmap  Index  High  Cardinality  Columns     SQL>  SELECT  *  FROM  big_dwh_table_2  WHERE  album_id  =  42;     100 rows selected. Execution Plan ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100 | 3000 | 103 (0)|00:00:02| | 1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE_2 | 100 | 3000 | 103 (0)|00:00:02| |* 2 | INDEX RANGE SCAN | BIG_DWH_2_ALBUM_ID_I | 100 | | 3 (0)|00:00:01| ------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 109 consistent gets 100 rows processed Consistent  reads  has  jumped  from  19  to  109  which  is  sFll  worse  than   the  101  consistent  reads    of  the  Bitmap  Index  ...   The most comprehensive Oracle applications & technology content under one roof
  • 20. 2.  Bitmap  Index  High  Cardinality  Columns     Table  containing  person  names,  using  freshly  rebuilt  B-­‐Tree  Indexes  ...   NAME INDEX_TYPE NUM_ROWS DISTINCT_KEYS LEAF_BLOCKS ---------- ------------ ---------- ------------- ----------- FIRST NAME NORMAL 2378672 147446 5842 LAST NAME NORMAL 2405599 361177 6202     SQL>  select  *  from  persons  where  given_name1  =  'DAVID'  or  last_name  =  'BOWIE';   39240  rows  selected.       Execution Plan --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 174 | 36888 | 164 (0)| 00:00:01 | | 1 | CONCATENATION | | | | | | | 2 | TABLE ACCESS BY INDEX ROWID| PERSONS | 47 | 9964 | 44 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | PERS_LAST_NAME_I | 47 | | 3 (0)| 00:00:01 | |* 4 | TABLE ACCESS BY INDEX ROWID| PERSONS | 127 | 26924 | 120 (0)| 00:00:01 | |* 5 | INDEX RANGE SCAN | PERS_FIRST_NAME1_I | 127 | | 3 (0)| 00:00:01 | --------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 28600 consistent gets The most comprehensive Oracle applications & technology content under one roof
  • 21. 2.  Bitmap  Index  High  Cardinality  Columns     Bitmap  Indexes  are  actually  substanFally  smaller  and  more  efficient  ...   NAME INDEX_TYPE NUM_ROWS DISTINCT_KEYS LEAF_BLOCKS ---------- ------------ ---------- ------------- ----------- FIRST NAME BITMAP 148208 147463 1608 (-4234) LAST NAME BITMAP 361421 361183 2543 (-3659)     SQL>  select  *  from  persons  where  given_name1  =  'DAVID'  or  last_name  =  'BOWIE';    39240  rows  selected.       Execution Plan --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 176 | 37312 | 43 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID | PERSONS | 176 | 37312 | 43 (0)| 00:00:01 | | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | | 3 | BITMAP OR | | | | | | |* 4 | BITMAP INDEX SINGLE VALUE| PERS_FIRST_NAME1_I | | | | | |* 5 | BITMAP INDEX SINGLE VALUE| PERS_LAST_NAME_I | | | | | --------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 28483 consistent gets The most comprehensive Oracle applications & technology content under one roof
  • 22. 2.  Bitmap  Index  High  Cardinality  Columns     •  If  you  only  use  Bitmap  Indexes  for  low  cardinality   columns,  you’re  not  taking  full  advantage  of  them   •  Suitable  for  all  columns  that  are  not  approaching   uniqueness   •  BUT,  only  for  Data  Warehouse  environments  due  to   locking  implicaFons  of  concurrent  transacFons   within  same  table   The most comprehensive Oracle applications & technology content under one roof
  • 23. 3.  B-­‐Tree  Index  Low  Cardinality  Columns   •  Generally  B-­‐Tree  Indexes  more  suitable  for  columns   with  many  disFnct  values   •  Increases  selecFvity  and  makes  indexes  a  more   efficient  opFon  to  the  CBO   •  However,  there  are  always  excepFons   •  B-­‐Tree  Index  might  be  the  perfect  candidate  for  a   column  with  as  low  as  1  disFnct  value  ...   The most comprehensive Oracle applications & technology content under one roof
  • 24. 3.  B-­‐Tree  Index  Low  Cardinality  Columns   SQL>  create  table  bowie  (id  number,  code  number,  name  varchar2(50));   Table  created.       SQL>  create  index  bowie_code_i  on  bowie(code);   Index  created.     SQL>  insert  into  bowie  select  rownum,  null,  'Ziggy  Stardust  and  the  Spiders  From  Mars'  from  dual   connect  by  level  <=  1000000;   1000000  rows  created.       SQL>  update  bowie  set  code  =  42  where  mod(id,10000)  =  0;   100  rows  updated.       SQL>  commit;   Commit  complete.     SQL>  exec  dbms_stats.gather_table_stats(ownname=>null,  tabname=>'BOWIE',  cascade=>  true,   esFmate_percent=>null,  method_opt=>'FOR  ALL  COLUMNS  SIZE  1');       PL/SQL  procedure  successfully  completed.   CODE  column  only  has  1  disFnct  value  although  most  rows  are  NULL  ...   The most comprehensive Oracle applications & technology content under one roof
  • 25. 3.  B-­‐Tree  Index  Low  Cardinality  Columns   SQL>  select  blevel,  leaf_blocks,  disFnct_keys  from  dba_indexes  where  index_name='BOWIE_CODE_I';       BLEVEL LEAF_BLOCKS DISTINCT_KEYS ---------- ----------- ------------- 0 1 1   SQL>  select  column_name,  num_disFnct,  num_nulls  from  dba_tab_columns  where  table_name  =   'BOWIE'  and  column_name  =  'CODE';       COLUMN_NAME NUM_DISTINCT NUM_NULLS ------------ ------------ ---------- CODE 1 999900     As  NULLs  are  not  stored  in  B-­‐Tree  Indexes  by  default,  index  is  Fny     CBO  knows  there’s  only  1  disFnct  value  but  it  also  knows  most  rows   are  only  NULLs   The most comprehensive Oracle applications & technology content under one roof
  • 26. 3.  B-­‐Tree  Index  Low  Cardinality  Columns   SQL>  select  *  from  bowie  where  code  =  42;       100  rows  selected.       Execution Plan -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100 | 4700 | 101 (0)| 00:00:02 | | 1 | TABLE ACCESS BY INDEX ROWID| BOWIE | 100 | 4700 | 101 (0)| 00:00:02 | |* 2 | INDEX RANGE SCAN | BOWIE_CODE_I | 100 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- CBO  will  happily  use  index  on  CODE  column  with  1  disFnct  value     No  histograms  necessary  as  exisFng  staFsFcs  sufficient  for  CBO  to   know  index  is  the  most  efficient  access  path  ...   The most comprehensive Oracle applications & technology content under one roof
  • 27. 4.  Index  Just  Which  Column  Values  You   Want   •  By  default,  all  values  within  a  column  are  indexed   •  There  are  many  scenarios  when  you  may  not  want   to  index  all  values  within  a  column   •  Some  column  values  maybe  too  numerous  to  be  of   pracFcal  use  within  the  index   •  Some  column  values  may  unnecessarily  inflate  size   and  efficiency  of  index   •  So,  just  don't  index  them  ...   The most comprehensive Oracle applications & technology content under one roof
  • 28. 4.  Just  index  some  column  values   SQL>  CREATE  TABLE  index_some_stuff  (id  number,  status  varchar2(20),  descripFon   varchar2(50));    Table  created.       SQL>  INSERT  INTO  index_some_stuff  SELECT  rownum,  'PROCESSED',  'NOT  REALLY   INTERESTED  WITH  THIS  ROW'  FROM  DUAL  CONNECT  BY  LEVEL  <=  1000000;    1000000  rows  created.       SQL>  UPDATE  index_some_stuff  SET  status  =  'BOWIE',  descripFon  =  'ROW  OF  INTEREST'   where  mod(id,10000)=42;    100  rows  updated.       SQL>  commit;    Commit  complete.       SQL>  SELECT  status,  count(*)  FROM  index_some_stuff  GROUP  BY  status;       STATUS                 COUNT(*) -------------------- ---------- PROCESSED                999900 BOWIE                       100 The most comprehensive Oracle applications & technology content under one roof
  • 29. 4.  Just  index  some  column  values   SQL>  CREATE  INDEX  index_some_stuff_i_1  ON  index_some_stuff(status);   Index  created.     SQL>  exec  dbms_stats.gather_table_stats(ownname=>'BOWIE',  tabname=>   ’INDEX_SOME_STUFF',  method_opt=>  'FOR  COLUMNS  STATUS  SIZE  5');     PL/SQL  procedure  successfully  completed.     SQL>  SELECT  *  FROM  index_some_stuff  WHERE  status  =  'BOWIE';       100  rows  selected.       Execution Plan ---------------------------------------------------------------------------------------------------- | Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     | ---------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT            |                      |   100 |  5200 |     4   (0)| 00:00:01 | |   1 |  TABLE ACCESS BY INDEX ROWID| INDEX_SOME_STUFF     |   100 |  5200 |     4   (0)| 00:00:01 | |*  2 |   INDEX RANGE SCAN          | INDEX_SOME_STUFF_I_1 |   100 |       |     3   (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 104 consistent gets 100 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 30. 4.  Just  index  some  column  values   But  why  bother  indexing  all  the  common  values  when  they’ll  never  be  referenced  ?   SQL>  CREATE  INDEX  index_some_stuff_i_2  ON     index_some_stuff(DECODE(status,  'BOWIE',  'BOWIE',  NULL))  COMPUTE  STATISTICS;   Index  created.     SQL>  exec  dbms_stats.gather_table_stats(ownname=>'BOWIE',  tabname=>   ‘INDEX_SOME_STUFF',  method_opt=>'FOR  ALL  HIDDEN  COLUMNS  SIZE  1',  cascade=>  true);   PL/SQL  procedure  successfully  completed.     SQL>  SELECT  index_name,  blevel,  leaf_blocks,  disFnct_keys,  num_rows     FROM  dba_indexes  WHERE  owner='BOWIE'  AND  table_name='INDEX_SOME_STUFF';     INDEX_NAME BLEVEL LEAF_BLOCKS DISTINCT_KEYS NUM_ROWS ------------------------------ ---------- ----------- ------------- ---------- INDEX_SOME_STUFF_I_2 0 1 1 100 INDEX_SOME_STUFF_I_1 2 2924 2 1000000 The  index  is  only  a  fracFon  the  size  of  the  previous  index  as  it  only  contains  the   one  index  entry  of  interest   The most comprehensive Oracle applications & technology content under one roof
  • 31. 4.  Just  index  some  column  values   SQL>  SELECT  *  FROM  bowie.index_some_stuff                        WHERE(DECODE(status,  'BOWIE',  'BOWIE',  null))  =  'BOWIE';     100 row selected. ---------------------------------------------------------------------------------------------------- | Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     | ---------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT            |                      |   100 |  5300 |   101   (0)| 00:00:02 | |   1 |  TABLE ACCESS BY INDEX ROWID| INDEX_SOME_STUFF     |   100 |  5300 |   101   (0)| 00:00:02 | |*  2 |   INDEX RANGE SCAN          | INDEX_SOME_STUFF_I_2 |   100 |       |     1   (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 102 consistent gets 100 rows processed Note:  consistent  gets  have  now  reduced  down  from  104  to  102   The most comprehensive Oracle applications & technology content under one roof
  • 32. 4.  Just  index  some  column  values   Can  use  zero  sized  unusable  indexes  to  your  advantage  to  index  only   useful  porFons  of  a  table.  Most  data  here  is  processed:   SQL>  create  table  bowie_stuff  (id  number,  processed  varchar2(10));   Table  created.     SQL>  insert  into  bowie_stuff  select  rownum,  'YES'  from  dual  connect  by  level  <=  1000000;   1000000  rows  created.     SQL>  commit;   Commit  complete.     SQL>  update  bowie_stuff  set  processed  =  ‘NO’  where  id  in  (999990,  999992,  999994,  999996,  999998);   5  rows  updated.     SQL>  commit;   Commit  complete.     SQL>  create  index  bowie_stuff_i  on  bowie_stuff(processed)  pckree  0;   Index  created. The most comprehensive Oracle applications & technology content under one roof
  • 33. 4.  Just  index  some  column  values   SQL>  select  index_name,  leaf_blocks  from  dba_indexes  where  index_name  =  'BOWIE_STUFF_I';     INDEX_NAME LEAF_BLOCKS ------------------------------ ----------- BOWIE_STUFF_I 1877   SQL>  select  segment_name,  blocks  from  dba_segments  where  segment_name  =  'BOWIE_STUFF_I';     SEGMENT_NAME BLOCKS -------------------- ---------- BOWIE_STUFF_I 1920   SQL>  exec  dbms_stats.gather_table_stats(ownname=>'BOWIE',  tabname=>'BOWIE_STUFF',   esFmate_percent=>null,  cascade=>  true,  method_opt=>  'FOR  ALL  COLUMNS  SIZE  1');     PL/SQL  procedure  successfully  completed.     SQL>  exec  dbms_stats.gather_table_stats(ownname=>'BOWIE',  tabname=>'BOWIE_STUFF',   esFmate_percent=>null,  method_opt=>  'FOR  COLUMNS  PROCESSED  SIZE  5');     PL/SQL  procedure  successfully  completed. The most comprehensive Oracle applications & technology content under one roof
  • 34. 4.  Just  index  some  column  values   SQL>  select  *  from  bowie_stuff  where  processed  =  'NO';     Execution Plan --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 40 | 4 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| BOWIE_STUFF | 5 | 40 | 4 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | BOWIE_STUFF_I | 5 | | 3 (0)| 00:00:01 | --------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 6 consistent gets 0 physical reads 0 redo size 540 bytes sent via SQL*Net to client 396 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 5 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 35. 4.  Just  index  some  column  values   However  in  11g  R2,  if  we  now  recreate  the  index  as  a  parFFoned   index  with  only  the  “useful”  porFon  of  the  index  usable  ...   SQL>  drop  index  bowie_stuff_i;     Index  dropped.     SQL>  create  index  bowie_stuff_i  on  bowie_stuff(processed)      2    global  parFFon  by  range  (processed)      3    (parFFon  not_processed_part  values  less  than  ('YES'),      4      parFFon  processed_part  values  less  than  (MAXVALUE))      5    unusable;     Index  created.     SQL>  alter  index  bowie_stuff_i  rebuild  parFFon  not_processed_part;     Index  altered. The most comprehensive Oracle applications & technology content under one roof
  • 36. 4.  Just  index  some  column  values   We  now  only  use  a  fracFon  of  the  storage  for  the  index  and  the   “useful”  porFon  of  the  indexed  data  is  just  a  single  leaf  block  in  size  ...   SQL>  select  index_name,  parFFon_name,  leaf_blocks  from  dba_ind_parFFons  where  index_name  =   'BOWIE_STUFF_I';     INDEX_NAME PARTITION_NAME LEAF_BLOCKS -------------------- -------------------- ----------- BOWIE_STUFF_I PROCESSED_PART 0 BOWIE_STUFF_I NOT_PROCESSED_PART 1   SQL>  select  segment_name,  parFFon_name,  blocks  from  dba_segments  where  segment_name  =   'BOWIE_STUFF_I';     SEGMENT_NAME PARTITION_NAME BLOCKS -------------------- -------------------- ---------- BOWIE_STUFF_I NOT_PROCESSED_PART 8 The most comprehensive Oracle applications & technology content under one roof
  • 37. 4.  Just  index  some  column  values   SQL>  select  *  from  bowie_stuff  where  processed  =  'NO';     Execution Plan -------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | -------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 45 | 1 (0)| 00:00:01 | | | | 1 | PARTITION RANGE SINGLE | | 5 | 45 | 1 (0)| 00:00:01 | 1 | 1 | | 2 | TABLE ACCESS BY INDEX ROWID| BOWIE_STUFF | 5 | 45 | 1 (0)| 00:00:01 | | | |* 3 | INDEX RANGE SCAN | BOWIE_STUFF_I | 5 | | 1 (0)| 00:00:01 | 1 | 1 | -------------------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 4 consistent gets 0 physical reads 0 redo size 542 bytes sent via SQL*Net to client 395 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 5 rows processed Note:  The  query  itself  is  also  more  efficient  with  consistent  gets   reduced  from  6  down  to  4  ...   The most comprehensive Oracle applications & technology content under one roof
  • 38. 5.  100%  Index  SelecFvity   •  Generally  indexes  only  process  a  “small”  %  of   overall  data   •  Cheaper  to  use  a  Full  Table  Scan  to  process  a   “high”  %  of  data   •  Common  belief  that  if  returning  more  than  ‘x’%,   indexes  are  ignored  by  CBO   •  However,  indexes  can  be  most  efficient  access   path  when  returning  anything  up  to  100%  of  data   The most comprehensive Oracle applications & technology content under one roof
  • 39. 5.  100%  Index  SelecFvity   SQL>  create  table  ziggy  (id  number,  name  varchar2(30));   Table  created.       SQL>  insert  into  ziggy  select  rownum,  'ZIGGY  STARDUST'  from  dual  connect  by  level  <=   1000000;   1000000  rows  created.       SQL>  commit;   Commit  complete.       SQL>  delete  ziggy  where  id  between  1  and  999000;   999000  rows  deleted.       SQL>  commit;   Commit  complete.     SQL>  create  index  ziggy_id_i  on  ziggy(id);   Index  created.       SQL>  exec  dbms_stats.gather_table_stats(ownname=>'BOWIE',  tabname=>'ZIGGY',   cascade=>  true,  esFmate_percent=>null,  method_opt=>  'FOR  ALL  COLUMNS  SIZE  1');   The most comprehensive Oracle applications & technology content under one roof
  • 40. 5.  100%  Index  SelecFvity   SQL>  select  id  from  ziggy  where  id  >  1;       1000  rows  selected.       Execution Plan ----------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000 | 5000 | 3 (0)| 00:00:01 | |* 1 | INDEX FAST FULL SCAN| ZIGGY_ID_I | 1000 | 5000 | 3 (0)| 00:00:01 | -----------------------------------------------------------------------------------     If  all  columns  of  interest  can  be  found  within  an  index,  an   Index  Fast  Full  Scan  can  treat  the  index  as  a  “skinny”  table.   The most comprehensive Oracle applications & technology content under one roof
  • 41. 5.  100%  Index  SelecFvity   SQL>  select  *  from  ziggy  where  id  >  1;       1000  rows  selected.       Execution Plan ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)|Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1000 | 20000 | 8 (0)|00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| ZIGGY | 1000 | 20000 | 8 (0)|00:00:01 | |* 2 | INDEX RANGE SCAN | ZIGGY_ID_I | 1000 | | 4 (0)|00:00:01 | ------------------------------------------------------------------------------------------ However,  because  the  table  is  so  fragmented,  the  CBO  is   using  the  index  to  access  the  table  and  retrieve  100%  of  the   rows  ...   The most comprehensive Oracle applications & technology content under one roof
  • 42. 5.  100%  Index  SelecFvity   SQL>  CREATE  TABLE  big_dwh_table_2  AS  SELECT  *  FROM  big_dwh_table                        ORDER  BY  total_sales;     Table  created.     SQL>  CREATE  INDEX  big_dwh_album_id_i  ON  big_dwh_table(album_id);     Index  created.     SQL>  CREATE  INDEX  big_dwh_2_album_id_i  ON  big_dwh_table_2(album_id);     Index  created.     SQL>  SELECT  index_name,  leaf_blocks,  clustering_factor  FROM  user_indexes                        WHERE  index_name  like  'BIG_DWH%ALBUM_ID_I';     INDEX_NAME LEAF_BLOCKS CLUSTERING_FACTOR ------------------------------ ----------- ----------------- BIG_DWH_2_ALBUM_ID_I 2090 990282 BIG_DWH_ALBUM_ID_I 2090 4957 The most comprehensive Oracle applications & technology content under one roof
  • 43. 5.  100%  Index  SelecFvity   SQL>  SELECT  *  FROM  big_dwh_table  WHERE  album_id  BETWEEN  10  AND  20  ORDER  BY  id;     1100  rows  selected.     Execution Plan ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows| Bytes |Cost(%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | |1200 | 36000 | 12 (9)|00:00:01 | | 1 | SORT ORDER BY | |1200 | 36000 | 12 (9)|00:00:01 | | 2 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE |1200 | 36000 | 11 (0)|00:00:01 | |* 3 | INDEX RANGE SCAN | BIG_DWH_ALBUM_ID_I |1200 | | 5 (0)|00:00:01 | ---------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 11 consistent gets 4 physical reads 0 redo size 30759 bytes sent via SQL*Net to client 396 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1100 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 44. 5.  100%  Index  SelecFvity   SQL>  SELECT  *  FROM  big_dwh_table  WHERE  album_id  BETWEEN  10  AND  20                        ORDER  BY  album_id;     1100 rows selected. Execution Plan ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost(%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1200 | 36000 | 11 (0)|00:00:01| | 1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE | 1200 | 36000 | 11 (0)|00:00:01| |* 2 | INDEX RANGE SCAN | BIG_DWH_ALBUM_ID_I | 1200 | | 5 (0)|00:00:01| ---------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 13 consistent gets 0 physical reads 0 redo size 30759 bytes sent via SQL*Net to client 396 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1100 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 45. 5.  100%  Index  SelecFvity   SQL>  SELECT  *  FROM  big_dwh_table  WHERE  album_id  BETWEEN  1  AND  10000                        ORDER  BY  album_id;     Execution Plan ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost(%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000K| 28M|7145 (2)|00:00:48| | 1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE | 1000K| 28M|7145 (2)|00:00:48| |* 2 | INDEX FULL SCAN | BIG_DWH_ALBUM_ID_I | 1000K| |2130 (2)|00:00:15| --------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 139919 consistent gets 0 physical reads 0 redo size 37476458 bytes sent via SQL*Net to client 733722 bytes received via SQL*Net from client 66668 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1000000 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 46. 5.  100%  Index  SelecFvity   SQL>  SELECT  *  FROM  big_dwh_table  ORDER  BY  album_id;     1000000  rows  selected.     Execution Plan -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000K| 28M| | 7699 (4)| 00:00:51 | | 1 | SORT ORDER BY | | 1000K| 28M| 91M| 7699 (4)| 00:00:51 | | 2 | TABLE ACCESS FULL| BIG_DWH_TABLE | 1000K| 28M| | 555 (10)| 00:00:04 | -------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 43 recursive calls 5 db block gets 4954 consistent gets 5432 physical reads 0 redo size 37476485 bytes sent via SQL*Net to client 733722 bytes received via SQL*Net from client 66668 SQL*Net roundtrips to/from client 0 sorts (memory) 1 sorts (disk) 1000000 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 47. 5.  100%  Index  SelecFvity   SQL>  SELECT  *  FROM  big_dwh_table  WHERE  album_id  IS  NOT  NULL  ORDER  BY  album_id;     1000000 rows selected. Execution Plan ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost(%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000K| 28M|7145 (2)|00:00:48| | 1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE | 1000K| 28M|7145 (2)|00:00:48| |* 2 | INDEX FULL SCAN | BIG_DWH_ALBUM_ID_I | 1000K| |2130 (2)|00:00:15| ---------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 139919 consistent gets 7040 physical reads 0 redo size 37476493 bytes sent via SQL*Net to client 733722 bytes received via SQL*Net from client 66668 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1000000 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 48. 5.  100%  Index  SelecFvity   SQL>  SELECT  *  FROM  big_dwh_table_2  WHERE  album_id  IS  NOT  NULL  ORDER  BY  album_id;     1000000 rows selected. Execution Plan ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000K| 28M| | 7704 (4)| 00:00:51 | | 1 | SORT ORDER BY | | 1000K| 28M| 91M| 7704 (4)| 00:00:51 | |* 2 | TABLE ACCESS FULL| BIG_DWH_TABLE_2 | 1000K| 28M| | 561 (11)| 00:00:04 | ---------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 44 recursive calls 18 db block gets 4979 consistent gets 7669 physical reads 0 redo size 36721186 bytes sent via SQL*Net to client 733722 bytes received via SQL*Net from client 66668 SQL*Net roundtrips to/from client 0 sorts (memory) 1 sorts (disk) 1000000 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 49. 5.  100%  Index  SelecFvity   SQL>  SELECT  /*+  index(a)  */  *  from  big_dwh_table_2  a  WHERE  album_id  IS  NOT  NULL                        ORDER  BY  album_id;     1000000 rows selected. Execution Plan ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost (%CPU)|Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000K| 28M| 993K (1)|01:49:31 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE_2 | 1000K| 28M| 993K (1)|01:49:31 | |* 2 | INDEX FULL SCAN | BIG_DWH_2_ALBUM_ID_I | 1000K| | 2130 (2)|00:00:15 | ------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1059553 consistent gets 7065 physical reads 0 redo size 36720213 bytes sent via SQL*Net to client 733722 bytes received via SQL*Net from client 66668 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1000000 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 50. 5.  100%  Index  SelecFvity   SQL>  SELECT  *  from  big_dwh_table_2  WHERE  album_id  BETWEEN  1  AND  15                        ORDER  BY  album_id;     1500 rows selected. Execution Plan ------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost(%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1500 | 45000 | 1297 (5)| 00:00:07| | 1 | SORT ORDER BY | | 1500 | 45000 | 1297 (5)| 00:00:07| |* 2 | TABLE ACCESS FULL| BIG_DWH_TABLE_2 | 1500 | 45000 | 1296 (4)| 00:00:07| ------------------------------------------------------------------------------------ Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 4981 consistent gets 0 physical reads 0 redo size 54139 bytes sent via SQL*Net to client 1485 bytes received via SQL*Net from client 101 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1500 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 51. 5.  100%  Index  SelecFvity   SQL>  SELECT  *  from  big_dwh_table_2  WHERE  album_id  BETWEEN  1  AND  13                        ORDER  BY  album_id;     1300 rows selected. Execution Plan ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost(%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1300| 39000 |1295 (1)| 00:00:07 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_DWH_TABLE_2 | 1300| 39000 |1295 (1)| 00:00:07 | |* 2 | INDEX RANGE SCAN | BIG_DWH_2_ALBUM_ID_I | 1300| | 5 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1385 consistent gets 60 physical reads 0 redo size 47048 bytes sent via SQL*Net to client 1342 bytes received via SQL*Net from client 88 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1300 rows processed The most comprehensive Oracle applications & technology content under one roof
  • 52. 6.  BLEVEL  1  =>  BLEVEL  2     Careful  of  indexes  increasing  from  BLEVEL  1  to  2.  Following  demo   11.2.0.1  with  8K  block  size.     SQL>  create  table  major_tom  (id  number,  code  number,  name  varchar2(30));    Table  created.       SQL>  create  index  major_tom_i  on  major_tom(id);    Index  created.       SQL>  insert  into  major_tom  select  rownum,  mod(rownum,100),  'GROUND  CONTROL'  from  dual   connect  by  level  <=336000;    336000  rows  created.         SQL>  exec  dbms_stats.gather_table_stats(ownname=>null,  tabname=>  'MAJOR_TOM',  cascade=>   true,  esFmate_percent=>null,  method_opt=>'FOR  ALL  COLUMNS  SIZE  1');    PL/SQL  procedure  successfully  completed.     SQL>  select  blevel,  leaf_blocks,  num_rows,  clustering_factor  from  dba_indexes  wh   ere  index_name='MAJOR_TOM_I';     BLEVEL LEAF_BLOCKS NUM_ROWS CLUSTERING_FACTOR ---------- ----------- ---------- ----------------- 1 671 336000 1296   The most comprehensive Oracle applications & technology content under one roof
  • 53. 6.  BLEVEL  1  =>  BLEVEL  2     SQL>  select  *  from  major_tom  where  id  =  42;       Execution Plan ------------------------------------------------------------------------------------------- | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     | ------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT            |             |     1 |    23 |     2   (0)| 00:00:01 | |   1 |  TABLE ACCESS BY INDEX ROWID| MAJOR_TOM   |     1 |    23 |     2   (0)| 00:00:01 | |*  2 |   INDEX RANGE SCAN          | MAJOR_TOM_I |     1 |       |     1   (0)| 00:00:01 | -------------------------------------------------------------------------------------------   Statistics ----------------------------------------------------------         0  recursive calls           0  db block gets           4  consistent gets           0  physical reads         0  redo size         531  bytes sent via SQL*Net to client         395  bytes received via SQL*Net from client           2  SQL*Net roundtrips to/from client           6  sorts (memory)           0  sorts (disk)           1  rows processed   When  BLEVEL  =  1,  CBO  ignores  the  BLEVEL  from  its  calculaFons   The most comprehensive Oracle applications & technology content under one roof
  • 54. 6.  BLEVEL  1  =>  BLEVEL  2     Let’s  create  another  table,  with  a  CODE  column  that’s  has  100   occurrences  of  each  value  ...   SQL>  create  table  ziggy  (id  number,  code  number,  name  varchar2(30));    Table  created.       SQL>  insert  into  ziggy  select  rownum,  mod(rownum,10000),  'ZIGGY  STARDUST'  from  dual  connect  by   level  <=  1000000;    1000000  rows  created.     SQL>  commit;   Commit  complete.       SQL>  exec  dbms_stats.gather_table_stats(ownname=>null,  tabname=>  'ZIGGY',  cascade=>  true,   esFmate_percent=>null,  method_opt=>'FOR  ALL  COLUMNS  SIZE  1');    PL/SQL  procedure  successfully  completed.   The most comprehensive Oracle applications & technology content under one roof
  • 55. 6.  BLEVEL  1  =>  BLEVEL  2     SQL>  select  *  from  ziggy  z,  major_tom  m  where  z.id  =  m.id  and  z.code  in  (42,  4242);       68  rows  selected.       Execution Plan -------------------------------------------------------------------------------------------- | Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     | -------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT             |             |   200 |  9400 |  1372   (2)| 00:00:17 | |   1 |  NESTED LOOPS                |             |       |       |            |          | |   2 |   NESTED LOOPS               |             |   200 |  9400 |  1372   (2)| 00:00:17 | |*  3 |    TABLE ACCESS FULL         | ZIGGY       |   200 |  4800 |  1105   (2)| 00:00:14 | |*  4 |    INDEX RANGE SCAN          | MAJOR_TOM_I |     1 |       |     1   (0)| 00:00:01 | |   5 |   TABLE ACCESS BY INDEX ROWID| MAJOR_TOM   |     1 |    23 |     2   (0)| 00:00:01 | -------------------------------------------------------------------------------------------- CBO  choose  a  Nest  Loop  as  the  cost  of  accessing  the  MAJOR_TOM   table  100  Fmes  via  the  index  is  relaFvely  inexpensive   The most comprehensive Oracle applications & technology content under one roof
  • 56. 6.  BLEVEL  1  =>  BLEVEL  2     Let’s  just  add  another  500  rows  (or  0.15%  of  data)   SQL>  insert  into  major_tom  select  rownum+336000,  mod(rownum,100),  'GROUND  CONTROL'  from  dual   connect  by  level  <=500;    500  rows  created.       SQL>  commit;    Commit  complete.       SQL>  exec  dbms_stats.gather_table_stats(ownname=>null,  tabname=>  'MAJOR_TOM',  cascade=>  true,   esFmate_percent=>null,  method_opt=>'FOR  ALL  COLUMNS  SIZE  1');    PL/SQL  procedure  successfully  completed.        SQL>  select  blevel,  leaf_blocks,  num_rows,  clustering_factor  from  dba_indexes  where  index_name  =   'MAJOR_TOM_I';     BLEVEL LEAF_BLOCKS NUM_ROWS CLUSTERING_FACTOR ---------- ----------- ---------- ----------------- 2 672 336500 1298 Leaf  blocks  has  just  gone  up  by  just  1  but  it’s  enough  to  increase  the   BLEVEL  to  2  ...   The most comprehensive Oracle applications & technology content under one roof
  • 57. 6.  BLEVEL  1  =>  BLEVEL  2     SQL>  select  *  from  major_tom  where  id  =  42;       Execution Plan ------------------------------------------------------------------------------------------- | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     | ------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT            |             |     1 |    23 |     4   (0)| 00:00:01 | |   1 |  TABLE ACCESS BY INDEX ROWID| MAJOR_TOM   |     1 |    23 |     4   (0)| 00:00:01 | |*  2 |   INDEX RANGE SCAN          | MAJOR_TOM_I |     1 |       |     3   (0)| 00:00:01 | ------------------------------------------------------------------------------------------- Statistics ----------------------------------------------------------           1  recursive calls           0  db block gets           5  consistent gets           0  physical reads           0  redo size         531  bytes sent via SQL*Net to client         395  bytes received via SQL*Net from client           2  SQL*Net roundtrips to/from client           0  sorts (memory)           0  sorts (disk)           1  rows processed The  cost  of  accessing  1  row  has  gone  up  by  2  as  the  BLEVEL  is  no   longer  ignored  by  the  CBO  ...     The most comprehensive Oracle applications & technology content under one roof
  • 58. 6.  BLEVEL  1  =>  BLEVEL  2     SQL>  select  *  from  ziggy  z,  major_tom  m  where  m.id  =  z.id  and  z.code  in  (42,  4242);       68  rows  selected.       Execution Plan -------------------------------------------------------------------------------- | Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     | -------------------------------------------------------------------------------- |   0 | SELECT STATEMENT   |           |   200 |  9400 |  1485   (2)| 00:00:18 | |*  1 |  HASH JOIN         |           |   200 |  9400 |  1485   (2)| 00:00:18 | |*  2 |   TABLE ACCESS FULL| ZIGGY     |   200 |  4800 |  1105   (2)| 00:00:14 | |   3 |   TABLE ACCESS FULL| MAJOR_TOM |   336K|  7558K|   378   (1)| 00:00:05 | -------------------------------------------------------------------------------- Nested  Loop  costs  (previously  1372)  have  gone  up  considerably  as  the  cost  has  gone   up  by  2  for  each  iteraFon  of  the  loop.     Hash  Join  and  FTS  now  selected  by  the  CBO  even  though  overall  size  of  index  is  similar.     Index  BLEVEL  can  potenFally  toggle  between  1  and  2  and  result  in  variable   performance  if  size  is  borderline  and  index  frequently  rebuilt  due  to  some  deleFons.   The most comprehensive Oracle applications & technology content under one roof
  • 59. 7.  Why  Unique  Indexes  Are  Beyer   •  Since  Oracle8,  Non-­‐Unique  Indexes  Can  Police   Primary  and  Unique  Key  Constraints   •  Non-­‐Unique  Indexes  Necessary  For  Deferrable   and  NoValidate  Constraints   •  Non-­‐Unique  Indexes  are  not  automaFcally   dropped  when  constraint  is  dropped  or  disabled   •  However,  Unique  Indexes  are  not  outdated  and   are  generally  “beyer”  ...   The most comprehensive Oracle applications & technology content under one roof
  • 60. 7.  Why  Unique  Indexes  Are  Beyer   SQL>  CREATE  TABLE  index_size_test  (id  NUMBER,  value  VARCHAR2(100)                        CONSTRAINT  index_size_test_pk_1  PRIMARY  KEY);     Table  created.     SQL>  INSERT  INTO  index_size_test  VALUES  (1,  'DAVID  BOWIE');     1  row  created.     SQL>  COMMIT;     Commit  complete.     SQL>  SELECT  header_file,  header_block+1  FROM  dba_segments                        WHERE  segment_name  =  'INDEX_SIZE_TEST_PK_1';     HEADER_FILE HEADER_BLOCK+1 ----------- -------------- 5 138370   SQL>  ALTER  SYSTEM  DUMP  DATAFILE  5  BLOCK  138370;     System  altered.   The most comprehensive Oracle applications & technology content under one roof
  • 61. 7.  Why  Unique  Indexes  Are  Beyer   row#0[8016]  flag:  -­‐-­‐-­‐-­‐-­‐-­‐,  lock:  2,  len=20,  data:(6):    01  42  1c  7a  00  00   col  0;  len  11;  (11):    44  41  56  49  44  20  42  4f  57  49  45   SQL>  ALTER  TABLE  index_size_test  DROP  PRIMARY  KEY;     Table  altered.     SQL>  CREATE  INDEX  index_size_test_pk_2  ON  index_size_test(value);     Index  created.     SQL>  ALTER  TABLE  index_size_test  ADD  PRIMARY  KEY  (value);     Table  altered.   row#0[8015]  flag:  -­‐-­‐-­‐-­‐-­‐-­‐,  lock:  0,  len=21   col  0;  len  11;  (11):    44  41  56  49  44  20  42  4f  57  49  45   col  1;  len  6;  (6):    01  42  1c  7a  00  00   The most comprehensive Oracle applications & technology content under one roof
  • 62. 7.  Why  Unique  Indexes  Are  Beyer   SQL>  CREATE  TABLE  test1  AS  SELECT  rownum  id  FROM  dual  CONNECT  BY  LEVEL  <=  1000000;   Table  created.     SQL>  CREATE  INDEX  non_unique_idx  ON  test1(id)  PCTFREE  0;   Index  created.     SQL>  CREATE  TABLE  test2  AS  SELECT  rownum  id  FROM  dual  CONNECT  BY  LEVEL  <=  1000000;   Table  created.     SQL>  CREATE  UNIQUE  INDEX  non_unique_idx  ON  test2(id)  PCTFREE  0;   Index  created.     SQL>  exec  dbms_stats.gather_index_stats(ownname=>'BOWIE',  indname=>   'NON_UNIQUE_IDX',  esFmate_percent=>  null);   PL/SQL  procedure  successfully  completed.     SQL>  exec  dbms_stats.gather_index_stats(ownname=>'BOWIE',  indname=>'UNIQUE_IDX',   esFmate_percent=>  null);   PL/SQL  procedure  successfully  completed.     The most comprehensive Oracle applications & technology content under one roof
  • 63. 7.  Why  Unique  Indexes  Are  Beyer   SQL>  SELECT  index_name,  blevel,  leaf_blocks,  num_rows                        FROM  dba_indexes                        WHERE  index_name  IN  ('NON_UNIQUE_IDX',  'UNIQUE_IDX');     INDEX_NAME BLEVEL LEAF_BLOCKS NUM_ROWS -------------- ------ ----------- -------- NON_UNIQUE_IDX 2 1999 1000000 UNIQUE_IDX 2 1875 1000000 The  Non-­‐Unique  Index  has  used  an  extra  124  blocks  or   approximately  6.6%  more  blocks  than  the  Unique  Index     The most comprehensive Oracle applications & technology content under one roof
  • 64. 7.  Why  Unique  Indexes  Are  Beyer   Unique  indexes  have  less  latching  and  CPU  related  overheads  ...   SQL>  CREATE  TABLE  ziggy  (id  NUMBER,  name  VARCHAR2(30));     Table  created.     SQL>  INSERT  into  ziggy  SELECT  rownum,  'Bowie'  FROM  dual  CONNECT  BY  level  <=1000;     1000  rows  created.     SQL>  COMMIT;     Commit  complete.     SQL>  ALTER  TABLE  ziggy  ADD  PRIMARY  KEY  (id);     Table  altered.     SQL>  exec  dbms_stats.gather_table_stats(ownname=>NULL,  tabname=>'ZIGGY',   esFmate_percent=>  NULL,  method_opt=>  'FOR  ALL  COLUMNS  SIZE  1');     PL/SQL  procedure  successfully  completed.   The most comprehensive Oracle applications & technology content under one roof
  • 65. 7.  Why  Unique  Indexes  Are  Beyer   In  one  session,  run  the  following  a  couple  of  Fmes  to  ensure  no   recursive  SQL:   SQL>  SELECT  *  FROM  ziggy  WHERE  id  =  10;     ID NAME ----- ----------------------- 10 Bowie In  other  session,  run  the  following  (where  SID  =  the  sid  of  the  other   session)  before  and  a‚er  an  execuFon  of  the  above  select  statement   in  the  other  session.   SQL>  SELECT  n.name,  s.value  FROM  v$sesstat  s,  v$statname  n                        WHERE  s.staFsFc#  =  n.staFsFc#  AND  s.sid  =  123  AND  n.name  like  'consistent%';   The most comprehensive Oracle applications & technology content under one roof
  • 66. 7.  Why  Unique  Indexes  Are  Beyer   NAME                                                                                                                                                            VALUE   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   consistent  gets                                                                                                                              17703   consistent  gets  from  cache                                                                                    17703   consistent  gets  -­‐  examinaFon                                                                            10536   NAME                                                                                                                                                            VALUE   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   consistent  gets                                                                                                                              17706   consistent  gets  from  cache                                                                                    17706   consistent  gets  -­‐  examinaFon                                                                            10539   Note  that  consistent  gets  increases  by  3,  consistent  gets  from  cache  increases  by  3,   consistent  gets  -­‐  examinaFon  increases  by  3  (1  for  the  index  root  block,  1  for  the   index  leaf  block  and  1  for  the  table  block).  That’s  a  total  of  3  CRs  and  3  latches  (as  all   CRs  are  the  cheaper  ‘examinaFons’  which  only  require  1  latch  each)   The most comprehensive Oracle applications & technology content under one roof
  • 67. 7.  Why  Unique  Indexes  Are  Beyer   Now  the  same  test  but  this  Fme  with  a  non-­‐unique  index  ...   SQL>  ALTER  TABLE  ziggy  DROP  PRIMARY  KEY;     Table  altered.     SQL>  ALTER  TABLE  ziggy  ADD  PRIMARY  KEY  (id)  USING  INDEX      2    (CREATE  INDEX  ziggy_id_i  ON  ziggy(id));     Table  altered.     SQL>  exec  dbms_stats.gather_table_stats(ownname=>NULL,  tabname=>'ZIGGY',   esFmate_percent=>  NULL,  method_opt=>  'FOR  ALL  COLUMNS  SIZE  1');     PL/SQL  procedure  successfully  completed.   The most comprehensive Oracle applications & technology content under one roof
  • 68. 7.  Why  Unique  Indexes  Are  Beyer   NAME                                                                                                                                                            VALUE   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   consistent  gets                                                                                                                              18504   consistent  gets  from  cache                                                                                    18504   consistent  gets  -­‐  examinaFon                                                                            10949   NAME                                                                                                                                                            VALUE   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   consistent  gets                                                                                                                              18508   consistent  gets  from  cache                                                                                    18508   consistent  gets  -­‐  examinaFon                                                                            10950   Note  that  consistent  gets  increases  by  4  (not  3),  consistent  gets  from  cache  increases  by  4   (not  3),  consistent  gets  -­‐  examinaFon  increases  by  only  1(not  3).       In  summary,  there  are  4  not  3  CRs  with  only  the  root  block  acquired  via  a  1  latch  examinaFon   CR,  the  other  3  CRs  are  ‘full’  2  latch  gets  which  is  a  total  of  7  latches  (vs.  only  3  for  the   equivalent  unique  index).   The most comprehensive Oracle applications & technology content under one roof
  • 69. 7.  Why  Unique  Indexes  Are  Beyer   Create  table  with  a  PK  and  ayempt  to  insert  duplicate  PK  rows  ...   SQL>  create  table  radiohead  (id  number  constraint  radiohead_pk_i  primary  key  using  index  (create  unique  index   radiohead_pk_i  on  radiohead(id)),  name  varchar2(20));     Table  created.     SQL>  select  index_name,  uniqueness,  table_name  from  dba_indexes  where  index_name  =  'RADIOHEAD_PK_I';     INDEX_NAME UNIQUENES TABLE_NAME ------------------------------ --------- ------------------------------ RADIOHEAD_PK_I UNIQUE RADIOHEAD   SQL>  insert  into  radiohead  select  rownum,  'OK  COMPUTER'  from  dual  connect  by  level  <=  10;     10  rows  created.     SQL>  commit;     Commit  complete.     SQL>  insert  into  radiohead  select  rownum,  'OK  COMPUTER'  from  dual  connect  by  level  <=  12;   insert  into  radiohead  select  rownum,  'OK  COMPUTER'  from  dual  connect  by  level  <=  12   *   ERROR  at  line  1:   ORA-­‐00001:  unique  constraint  (BOWIE.RADIOHEAD_PK_I)  violated The most comprehensive Oracle applications & technology content under one roof
  • 70. 7.  Why  Unique  Indexes  Are  Beyer   With  the  new  Oracle11g  Rel.  1  hint,  duplicate  violaFon  rows  are  automaFcally   ignored.  /*+  ignore_row_on_dupkey_index(radiohead,radiohead_pk_i)  */  into  radiohead  select  rownum,  'OK  COMPUTER'  from  dual   SQL>  insert   connect  by  level  <=  12;   2  rows  created.     SQL>  insert  /*+  ignore_row_on_dupkey_index(radiohead(id))  */  into  radiohead  select  rownum,  'OK  COMPUTER'  from  dual  connect  by  level   <=  13;   1  row  created.     SQL>  commit;   Commit  complete.     SQL>  select  *  from  radiohead;     ID NAME ---------- -------------------- 1 OK COMPUTER 2 OK COMPUTER 3 OK COMPUTER 4 OK COMPUTER 5 OK COMPUTER 6 OK COMPUTER 7 OK COMPUTER 8 OK COMPUTER 9 OK COMPUTER 10 OK COMPUTER 11 OK COMPUTER 12 OK COMPUTER 13 OK COMPUTER 13 rows selected. The most comprehensive Oracle applications & technology content under one roof