SlideShare a Scribd company logo
Indexing In Exadata
     Richard Foote
   Oracle Corporation
Richard Foote
• Working in IT for 25+ years (scary stuff)
• Working with Oracle Database for 15+ years
• Spent 19 years employed in Australian Federal Government in various IT roles,
    last 9 years as a senior DBA with the Australian Federal Police
•   Responsible for many large scale, mission critical, “life-dependant” classified
    Oracle systems
•   Previously a DBA Instructor with Oracle Corporation (1996 and 2002)
•   Since Nov 2011, re-joined Oracle Corporation as a Technical Solutions
    Consultant based in sunny Canberra
•   Spent much of this time playing with Exadata (one of the reasons I rejoined) 
•   Oracle OakTable Member since 2002 and Oracle ACE Director since 2008 (now
    Oracle Employee Ace)
•   Richard Foote’s Oracle Blog: http://richardfoote.wordpress.com/
•   Spend as much free time as possible listening to the music of David Bowie !!
     2   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Innovations
       Exadata Storage Server Software
     Intelligent storage                                                      • Hybrid Columnar Compression
              – Smart Scan query offload                                         – 10x compression for warehouses
              – Scale-out storage                                                – 15x compression for archives

                                                                                 Data
                           +                       +                       +     remains
                                                                                 compressed       Uncompressed
                                                                                 for scans
    • Smart Flash Cache                                                          and in Flash
            – Accelerates random I/O up to 30x                                                    primary backup
            – Doubles data scan rate                                                   Benefits          test
                                                                                       Multiply   standby   dev’t
                                                                                                   Compressed

3   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Things can run so much faster in Exadata …
With Non-Exadata …
                   SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200;
                   266176 rows selected.
                   Elapsed: 00:04:43.38
                   -------------------------------------------------------------------------------
                   | Id | Operation          | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                   -------------------------------------------------------------------------------
                   |   0 | SELECT STATEMENT |            |   266K|    23M| 2348K (1)| 07:49:45 |
                   |* 1 | TABLE ACCESS FULL| DWH_BOWIE |     266K|    23M| 2348K (1)| 07:49:45 |
                   -------------------------------------------------------------------------------
                   Predicate Information (identified by operation id):
                   ---------------------------------------------------
                      1 - filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42)
                   Statistics
                   ----------------------------------------------------------
                             1 recursive calls
                             0 db block gets
                       8644512 consistent gets
                       8625479 physical reads
                             0 redo size
                      12279634 bytes sent via SQL*Net to client
                        195719 bytes received via SQL*Net from client
                         17747 SQL*Net roundtrips to/from client
                             0 sorts (memory)
                             0 sorts (disk)
                        266176 rows processed



4   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Things can run so much faster in Exadata …
With Exadata, what previously took minutes can take seconds …
                   SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200;
                   266176 rows selected.
                   Elapsed: 00:00:03.97
                   ---------------------------------------------------------------------------------------
                   | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                   ---------------------------------------------------------------------------------------
                   |   0 | SELECT STATEMENT          |           |   266K|    23M| 2348K (1)| 07:49:45 |
                   |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE |     266K|    23M| 2348K (1)| 07:49:45 |
                   ---------------------------------------------------------------------------------------
                   Predicate Information (identified by operation id):
                   ---------------------------------------------------
                      1 - storage("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42)
                          filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42)
                   Statistics
                   ----------------------------------------------------------
                             0 recursive calls
                             0 db block gets
                       8626963 consistent gets
                       8625479 physical reads
                             0 redo size
                      12279634 bytes sent via SQL*Net to client
                        195719 bytes received via SQL*Net from client
                         17747 SQL*Net roundtrips to/from client
                             0 sorts (memory)
                             0 sorts (disk)
                        266176 rows processed



  5   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Indexing In Exadata …

Are indexes needed anymore ???




6   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Worse - Indexes can get in the way …
                 SQL> create bitmap index dwh_album_artist_i on dwh_bowie(artist_id, album_id);
                 Index created.
                 SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200;
                 266176 rows selected.
                 Elapsed: 00:00:23.11
                 ---------------------------------------------------------------------------------------------------
                 | Id | Operation                      | Name               | Rows | Bytes | Cost (%CPU)| Time     |
                 ---------------------------------------------------------------------------------------------------
                 |   0 | SELECT STATEMENT              |                    |   266K|   23M| 78267   (1)| 00:15:40 |
                 |   1 | TABLE ACCESS BY INDEX ROWID | DWH_BOWIE            |   266K|   23M| 78267   (1)| 00:15:40 |
                 |   2 |    BITMAP CONVERSION TO ROWIDS|                    |       |      |            |          |
                 |* 3 |      BITMAP INDEX RANGE SCAN   | DWH_ALBUM_ARTIST_I |       |      |            |          |
                 ---------------------------------------------------------------------------------------------------
                 Predicate Information (identified by operation id):
                 ---------------------------------------------------
                    3 - access("ARTIST_ID">=42 AND "ALBUM_ID"=42 AND "ARTIST_ID"<=4200)
                        filter("ARTIST_ID">=42 AND "ARTIST_ID"<=4200 AND "ALBUM_ID"=42)
                 Statistics
                 ----------------------------------------------------------
                            1 recursive calls
                            0 db block gets
                      291129 consistent gets
                       25337 physical reads
                       29728 redo size
                    28836174 bytes sent via SQL*Net to client
                      195719 bytes received via SQL*Net from client
                       17747 SQL*Net roundtrips to/from client
                            0 sorts (memory)
                            0 sorts (disk)
                      266176 rows processed




7   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Indexing In Exadata …
Are indexes evil? Should they just be dropped?



Mr. Index, or                                                               Dr. Evil !!




 8   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
What to do? Important Decision
• Many suggest simply drop indexes once you move to Exadata
• Indexes take up much storage (important consideration, especially with ¼
    Exadata racks where storage is more limited)
•   A redundant index wastes space and resources to maintain
•   Indexes critical to performance (or they certainly used to be)
•   But can “get in the way” in Exadata
•   Once dropped, tricky to keep track of what indexes previously existed
•   As usual, the decision to drop or keep indexes not a straightforward one …



    9   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Let’s Go Back To The Basics
Cost of using an Index:
Basic Cost = blevel +
             ceil(effective index selectivity x leaf_blocks) +
             ceil(effective table selectivity x clustering_factor) +
             a bit of CPU …

In Exadata, this is basically the same for uncompressed tables.
With EHCC tables, there’s some additional CPU costs required
to decompress rows.
Therefore actual cost of using an Index can increase in Exadata

 10   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Let’s Go Back To The Basics

Simplistically, cost of Full Table Scan:

Cost = (((No. of table blocks / effective multi block read count) x
      multi block read time) +
      a bit of CPU) /
      single block read time

The costing is still calculated the same in Exadata, however this
may no longer represent the true costs…

 11   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Intelligent Storage Grid
  Exadata cells implement smart scans to greatly reduce the data that
     needs to be processed by database
           – Only return relevant rows and columns to database
           – Offload predicate evaluation
  Data reduction can be very large
           – Column and row reduction often decrease data to be returned to the
                  database by 10x




12   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Smart Scans
 Full Scans (Tables/Indexes/MVs/Partitions)
 Direct Path Reads (By-Passing Buffer Cache)
 Smart Scan Optimizations, some of which include:
      – Column Projection
      – Predicate Filtering
      – Simple Joins
      – Function Off-Loading
      – Virtual Column Evaluation
      – HCC Decompression
      – Decryption
 See MOS Notes 793845.1 and 50415.1 for more info on Direct Path Reads
 13   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Smart Scans - Benefits
 CPU utilization on database nodes improves due to offload
 Less data shipped to database nodes (generally …)
 Query fully encrypted database by moving decryption from database to
  storage cell hardware
 Full Table Scan performance can dramatically improve
 Costs associated with Full Table Scan operation can therefore
  significantly decrease, especially with Storage Indexes kicking in
 With index costs perhaps increasing and FTS costs perhaps
  decreasing, indexes in Exadata become less viable …
 Not looking good for indexes !!!

   14   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Non-Exadata Chart: Indexes vs. FTS




Cost




                                                                                   Rows Returned
                                                                      Full Table Scan
                                                                      Index Scan


 15   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Non-Exadata Chart: Indexes vs. FTS (DWH)



                                        xx                                           x   x
                                       xx                                       xx x
                                      xx                                      xx                      xx
                                                                                                 xx
Cost                                                                 x                       x xx
                                 x                                             x
                                                       x
                          x
                                x
                                x           x
                    xx
                                                                                         Rows Returned
                                                                        Full Table Scan
                                                                                                           x Queries using indexes
                                                                        Index Scan

 16   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Non-Exadata Chart: Indexes vs. FTS (OLTP)



                                           x                                    x
Cost                                                                                     x
                                 x

                       x     x
                       x xx
                    xx x
                     x
                    x x xx x
                                                                                    Rows Returned
                                                                       Full Table Scan
                                                                       Index Scan              x Queries using indexes


 17   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Chart: Indexes vs. FTS




Cost




                                                                                   Rows Returned
                                                                       Full Table Scan
                                                                       Index Scan (on HCC tables)


 18   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Chart: Indexes vs. FTS (DWH)


                                                                                       x
                                        xx
                                         x                                         x
                                       x
                                      xx                                     xxxx x                    x
                                                                                                xx x x
Cost                                                                 x                     xx
                                x
                                                      x                      x
                          x
                                            x
                       x
                       x
                    xx
                                                                                       Rows Returned
                                                                      Full Table Scan
                                                                      Index Scan                           x Queries using indexes


 19   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Chart: Indexes vs. FTS (OLTP)



                                           x                                     x
Cost                                                                                      x
                                 x

                      x     x
                      x xxx
                    xx x
                     xx
                    x x xx
                                                                                     Rows Returned
                                                                        Full Table Scan
                                                                        Index Scan              x Queries using indexes


 20   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Indexes vs. FTS (CBO Costs)



                                         x
                                        xx                                         xx
                                                                               xx x
                                       x
                                      xx                                     xx                  xx
                                                                                            xx
Cost                                                                 x                  x xx
                                 x
                                                      x                      x
                          x
                       x
                       x                    x
                    xx
                                                                                        Rows Returned
                                                                     Full Table Scan
                                                                      Index Scan
                                                                                                      x Queries using indexes
                                                                      CBO Costs

 21   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Indexes vs. FTS (CBO Costs)


                                               x                                      x
                                        x
                                        xx                                        x
                                      x
                                      x                                      xxxx x                 x x
                                      x                                                         x
Cost                                                                 x                    x xxx
                                 x
                                                      x                      x
                          x
                       x                    x
                       x
                    xx
                                                                       Full Table Scan
                                                                                             Rows Returned
                                                                       Index Scan
                                                                                                          x Queries using indexes
                                                                       FTS CBO Cost

 22   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Without Exadata Smart Scans
Going back to the first example …
                    SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200;
                    266176 rows selected.
                    Elapsed: 00:04:43.38
                    -------------------------------------------------------------------------------
                    | Id | Operation          | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                    -------------------------------------------------------------------------------
                    |   0 | SELECT STATEMENT |            |   266K|    23M| 2348K (1)| 07:49:45 |
                    |* 1 | TABLE ACCESS FULL| DWH_BOWIE |     266K|    23M| 2348K (1)| 07:49:45 |
                    -------------------------------------------------------------------------------
                    Predicate Information (identified by operation id):
                    ---------------------------------------------------
                       1 - filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42)
                    Statistics
                    ----------------------------------------------------------
                              1 recursive calls
                              0 db block gets
                        8644512 consistent gets
                        8625479 physical reads
                              0 redo size
                       12279634 bytes sent via SQL*Net to client
                         195719 bytes received via SQL*Net from client
                          17747 SQL*Net roundtrips to/from client
                              0 sorts (memory)
                              0 sorts (disk)
                         266176 rows processed



23   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Smart Scan Example
              SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200;
              266176 rows selected.
              Elapsed: 00:00:03.97

              ---------------------------------------------------------------------------------------
              | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
              ---------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT          |           |   266K|    23M| 2348K (1)| 07:49:45 |
              |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE |     266K|    23M| 2348K (1)| 07:49:45 |
              ---------------------------------------------------------------------------------------

              Predicate Information (identified by operation id):
              ---------------------------------------------------

                    1 - storage("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42)
                        filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42)

              Statistics
              ----------------------------------------------------------
                        0 recursive calls
                        0 db block gets
                  8626963 consistent gets
                  8625479 physical reads
                        0 redo size
                 12279634 bytes sent via SQL*Net to client
                   195719 bytes received via SQL*Net from client
                    17747 SQL*Net roundtrips to/from client
                        0 sorts (memory)
                        0 sorts (disk)
                   266176 rows processed




24   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Smart Scan – How can you tell ?
         SQL> select
         sql_text, io_cell_offload_eligible_bytes, io_interconnect_bytes,
                io_cell_uncompressed_bytes, io_cell_offload_returned_bytes
         from v$sql where sql_id = 'admdhphbh1a1c';

         SQL_TEXT
         --------------------------------------------------------------------------------
         IO_CELL_OFFLOAD_ELIGIBLE_BYTES IO_INTERCONNECT_BYTES IO_CELL_UNCOMPRESSED_BYTES
         ------------------------------ --------------------- --------------------------
         IO_CELL_OFFLOAD_RETURNED_BYTES
         ------------------------------
         select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200
                             1.4132E+11              55217792                 1.6718E+10
                               55217792

         SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where
         n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes
         returned by smart scan', 'cell physical IO bytes saved by storage index');

         NAME                                                                     MB
         ---------------------------------------------------------------- ----------
         cell physical IO bytes saved by storage index                    59414.9453
         cell physical IO interconnect bytes returned by smart scan        26.329895




25   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Non-Smart Scan – CBO Costs The Same
              SQL> alter session set cell_offload_processing=false;
              Session altered.
              SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200;
              266176 rows selected.
              Elapsed: 00:03:03.38
              ---------------------------------------------------------------------------------------
              | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
              ---------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT          |           |   266K|    23M| 2348K (1)| 07:49:45 |
              |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE |     266K|    23M| 2348K (1)| 07:49:45 |
              ---------------------------------------------------------------------------------------

              Predicate Information (identified by operation id):
              ---------------------------------------------------
                 1 - filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42)

              Statistics
              ----------------------------------------------------------
                        1 recursive calls
                        0 db block gets
                  8644512 consistent gets
                  8625479 physical reads
                        0 redo size
                 12279634 bytes sent via SQL*Net to client
                   195719 bytes received via SQL*Net from client
                    17747 SQL*Net roundtrips to/from client
                        0 sorts (memory)
                        0 sorts (disk)
                   266176 rows processed


CBO is not aware of smart scan benefits and FTS costs remain the same …
 26   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Less Efficient Index Chosen By CBO
           SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200;
           266176 rows selected.

           Elapsed: 00:00:23.11
           ---------------------------------------------------------------------------------------------------
           | Id | Operation                     | Name               | Rows | Bytes | Cost (%CPU)| Time      |
           ---------------------------------------------------------------------------------------------------
           |   0 | SELECT STATEMENT             |                    |   266K|    23M| 78267   (1)| 00:15:40 |
           |   1 | TABLE ACCESS BY INDEX ROWID | DWH_BOWIE           |   266K|    23M| 78267   (1)| 00:15:40 |
           |   2 |   BITMAP CONVERSION TO ROWIDS|                    |       |       |            |          |
           |* 3 |     BITMAP INDEX RANGE SCAN   | DWH_ALBUM_ARTIST_I |       |       |            |          |
           ---------------------------------------------------------------------------------------------------
           Predicate Information (identified by operation id):
           ---------------------------------------------------
              3 - access("ARTIST_ID">=42 AND "ALBUM_ID"=42 AND "ARTIST_ID"<=4200)
                  filter("ARTIST_ID">=42 AND "ARTIST_ID"<=4200 AND "ALBUM_ID"=42)
           Statistics
           ----------------------------------------------------------
                     1 recursive calls
                     0 db block gets
                291129 consistent gets
                 25337 physical reads
                 29728 redo size
              28836174 bytes sent via SQL*Net to client
                195719 bytes received via SQL*Net from client
                 17747 SQL*Net roundtrips to/from client
                     0 sorts (memory)
                     0 sorts (disk)
                266176 rows processed

Therefore existing indexes although maybe slower, appear much cheaper…
 27   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
CBO and Smart Scans
 The decision to go for Direct Reads and use a Smart Scan is not made by the CBO
 The CBO is not aware of potential efficiencies provided by Smart Scans and costs
 Full Scans similar to Non-Exadata
 Bug 10248538: OPTIMIZER COST MODEL NOT EXADATA-AWARE
 Therefore, Full Scans are generally over-costed in Exadata, favoring Index Scan
 related execution paths
 Simply dropping all indexes however is not the answer (to be discussed …)
 Consider setting MBRC system stat to 128, assuming 8K block size to compensate
 (1MB default storage region size in storage cell)
 Consider v$sql_plan, dba_hist_sql_plan searching for index plans with high
 cardinality values
 Storage Indexes can make cost differentials even worse …

 28   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Index – Basic Example
Table                                      Index                             • Exadata Storage Indexes maintain summary
                                                                              information about table data in memory
A B C D
                                                                               – Store MIN and MAX values of columns
      1                                                                        – Typically index entry for every MB of disk

      3                                      Min B = 1                       • Eliminates disk I/Os if MIN and MAX can never
                                             Max B = 5                        match “where” clause of a query
      5
      5                                                                      • Completely automatic and transparent
      8                                       Min B = 3                      • Example: Select count(*) from table where B = 1;
                                              Max B =8
      3                                                                      • FTS no longer really a FTS …


 29   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – Demo Setup
SQL> create table big_bowie (id number not null, album_id number not null, artist_id number not null, format_id
number, release_date date, total_sales number, description varchar2(100));
Table created.

SQL> create sequence bowie_seq order;
Sequence created.

SQL> create or replace procedure pop_big_bowie as
  2 begin
  3     for v_album_id in 1..100 loop
  4         for v_artist_id in 1..100000 loop
  5             insert into big_bowie values (bowie_seq.nextval, v_album_id, v_artist_id,
ceil(dbms_random.value(0,5)) * 2,
  6                         trunc(sysdate-ceil(dbms_random.value(0,10000))), ceil(dbms_random.value(0,500000)),
'THE RISE AND FALL OF ZIGGY STARDUST AND THE SPIDERS FROM MARS');
  7         end loop;
  8         commit;
  9     end loop;
 10     commit;
 11 end;
 12 /
Procedure created.

SQL> exec pop_big_bowie
PL/SQL procedure successfully completed.



 30   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – Demo Setup
       SQL> update big_bowie set format_id = 3 where mod(id,10000)=0;
       1000 rows updated.
       SQL> commit;
       Commit complete.
       SQL> update big_bowie set format_id = 5 where id between 424242 and 425241;
       1000 rows updated.
       SQL> commit;
       Commit complete.
       SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'BIG_BOWIE‘, method_opt=>'FOR ALL
       COLUMNS SIZE 1');
       PL/SQL procedure successfully completed.
       SQL> select blocks from dba_tables where table_name = 'BIG_BOWIE';
           BLOCKS
       ----------
           134809



     This equates to approx. 1054 MB (a “typical” OLTP table)
     The DWH_BOWIE table is simply 64 times the BIG_BOWIE table

31    Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – “Clustering Factor”
ALBUM_ID column data is well clustered …
                           SQL> select * from big_bowie where album_id = 42;
                           100000 rows selected.
                           Elapsed: 00:00:00.27
                           Execution Plan
                           ---------------------------------------------------------------------------------------
                           | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                           ---------------------------------------------------------------------------------------
                           |   0 | SELECT STATEMENT          |           |   100K| 8984K| 36663    (1)| 00:07:20 |
                           |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE |     100K| 8984K| 36663    (1)| 00:07:20 |
                           ---------------------------------------------------------------------------------------
                           Predicate Information (identified by operation id):
                           ---------------------------------------------------
                              1 - storage("ALBUM_ID"=42)
                                  filter("ALBUM_ID"=42)
                           Statistics
                           ----------------------------------------------------------
                                     1 recursive calls
                                     0 db block gets
                                134834 consistent gets
                                134809 physical reads
                                     0 redo size
                               4345496 bytes sent via SQL*Net to client
                                 73850 bytes received via SQL*Net from client
                                  6668 SQL*Net roundtrips to/from client
                                     0 sorts (memory)
                                     0 sorts (disk)
                                100000 rows processed




32   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – “Clustering Factor”
SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and
n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by
storage index');

NAME                                                                     MB
---------------------------------------------------------------- ----------
cell physical IO bytes saved by storage index                    1042.24219
cell physical IO interconnect bytes returned by smart scan       9.56161499



The Storage Index has managed to avoid having to read
approx. 99% of the table.

Having data well clustered can result in Partition-Pruning
like efficiencies when using an associated Storage Index …

 33   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – “Clustering Factor”
Note: Conventional database indexes love well clustered data as well …
           SQL> select * from big_bowie where album_id = 42;
           100000 rows selected.
           Elapsed: 00:00:01.07
           Execution Plan
           ----------------------------------------------------------------------------------------------------
           | Id | Operation                    | Name                 | Rows | Bytes | Cost (%CPU)| Time      |
           ----------------------------------------------------------------------------------------------------
           |   0 | SELECT STATEMENT            |                      |   100K| 8984K| 1550     (1)| 00:00:19 |
           |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE             |   100K| 8984K| 1550     (1)| 00:00:19 |
           |* 2 |    INDEX RANGE SCAN          | BIG_BOWIE_ALBUM_ID_I |   100K|       |   199   (1)| 00:00:03 |
           ----------------------------------------------------------------------------------------------------
           Predicate Information (identified by operation id):
           ---------------------------------------------------
              2 - access("ALBUM_ID"=42)
           Statistics
           ----------------------------------------------------------
                     0 recursive calls
                     0 db block gets
                  1590 consistent gets
                  1550 physical reads
                     0 redo size
               9689267 bytes sent via SQL*Net to client
                   733 bytes received via SQL*Net from client
                    21 SQL*Net roundtrips to/from client
                     0 sorts (memory)
                     0 sorts (disk)
                100000 rows processed


But is taking twice as long as FTS, despite “reported” physical reads much reduced…
  34   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – “Clustering Factor”
Even when all the data is cached …
                 SQL> select * from big_bowie where album_id = 42;
                 100000 rows selected.
                 Elapsed: 00:00:00.27
                 Execution Plan
                 ----------------------------------------------------------------------------------------------------
                 | Id | Operation                    | Name                 | Rows | Bytes | Cost (%CPU)| Time      |
                 ----------------------------------------------------------------------------------------------------
                 |   0 | SELECT STATEMENT            |                      |   100K| 8984K| 1550     (1)| 00:00:19 |
                 |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE             |   100K| 8984K| 1550     (1)| 00:00:19 |
                 |* 2 |     INDEX RANGE SCAN         | BIG_BOWIE_ALBUM_ID_I |   100K|       |   199   (1)| 00:00:03 |
                 ----------------------------------------------------------------------------------------------------
                 Predicate Information (identified by operation id):
                 ---------------------------------------------------
                    2 - access("ALBUM_ID"=42)
                 Statistics
                 ----------------------------------------------------------
                            0 recursive calls
                            0 db block gets
                        1590 consistent gets
                            0 physical reads
                            0 redo size
                     9689267 bytes sent via SQL*Net to client
                         733 bytes received via SQL*Net from client
                          21 SQL*Net roundtrips to/from client
                            0 sorts (memory)
                            0 sorts (disk)
                      100000 rows processed


Index is no more efficient than FTS, even though the index is extremely efficient …
 35   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – “Clustering Factor”
The TOTAL_SALES column however is not well clustered …
                     SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142;
                     2009 rows selected.
                     Elapsed: 00:00:01.25
                     Execution Plan
                     ---------------------------------------------------------------------------------------
                     | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                     ---------------------------------------------------------------------------------------
                     |   0 | SELECT STATEMENT          |           | 2040 | 26520 | 36700    (1)| 00:07:21 |
                     |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 2040 | 26520 | 36700      (1)| 00:07:21 |
                     ---------------------------------------------------------------------------------------
                     Predicate Information (identified by operation id):
                     ---------------------------------------------------
                        1 - storage("TOTAL_SALES"<=142 AND "TOTAL_SALES">=42)
                            filter("TOTAL_SALES"<=142 AND "TOTAL_SALES">=42)
                     Statistics
                     ----------------------------------------------------------
                               1 recursive calls
                               0 db block gets
                          134834 consistent gets
                          134809 physical reads
                               0 redo size
                           47506 bytes sent via SQL*Net to client
                            1987 bytes received via SQL*Net from client
                             135 SQL*Net roundtrips to/from client
                               0 sorts (memory)
                               0 sorts (disk)
                            2009 rows processed



 36   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – “Clustering Factor”
SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and
n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by
storage index');

NAME                                                                     MB
---------------------------------------------------------------- ----------
cell physical IO bytes saved by storage index                      72.65625
cell physical IO interconnect bytes returned by smart scan       .383415222


The Storage Index has only managed to avoid having to read approx. 7%
of the table.
The clustering of the data can make a huge impact to the effectiveness of
Storage Indexes.
Even though this query is only reading a fraction of the data as the
previous query, it’s taking twice as long.
The smart scan though is only returning a small fraction of the overall
data back to the database.
 37   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – “Clustering Factor”
Note: Conventional indexes also hate poorly clustered tables …
              SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142;
              2009 rows selected.
              Elapsed: 00:00:01.45
              Execution Plan
              -------------------------------------------------------------------------------------------------------
              | Id | Operation                    | Name                    | Rows | Bytes |Cost (%CPU)| Time      |
              -------------------------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT            |                         | 2040 | 26520 | 2048    (1)| 00:00:25 |
              |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE                | 2040 | 26520 | 2048    (1)| 00:00:25 |
              |* 2 |    INDEX RANGE SCAN          | BIG_BOWIE_TOTAL_SALES_I | 2040 |        |    7   (0)| 00:00:01 |
              -------------------------------------------------------------------------------------------------------
              Predicate Information (identified by operation id):
              ---------------------------------------------------
                 2 - access("TOTAL_SALES">=42 AND "TOTAL_SALES"<=142)
              Statistics
              ----------------------------------------------------------
                        1 recursive calls
                        0 db block gets
                     2150 consistent gets
                     2005 physical reads
                        0 redo size
                    43311 bytes sent via SQL*Net to client
                     1987 bytes received via SQL*Net from client
                      135 SQL*Net roundtrips to/from client
                        0 sorts (memory)
                        0 sorts (disk)
                     2009 rows processed


This index is taking longer than the equivalent Exadata FTS …
  38   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – “Clustering Factor”
But on subsequent re-runs, when most of the data has been cached …
                 SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142;
                 2009 rows selected.
                 Elapsed: 00:00:00.02
                 Execution Plan
                 ------------------------------------------------------------------------------------------------------
                 | Id | Operation                    | Name                    | Rows | Bytes |Cost (%CPU)| Time      |
                 ------------------------------------------------------------------------------------------------------
                 |   0 | SELECT STATEMENT            |                         | 2040 | 26520 | 2048    (1)| 00:00:25 |
                 |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE                | 2040 | 26520 | 2048    (1)| 00:00:25 |
                 |* 2 |    INDEX RANGE SCAN          | BIG_BOWIE_TOTAL_SALES_I | 2040 |        |    7   (0)| 00:00:01 |
                 ------------------------------------------------------------------------------------------------------
                 Predicate Information (identified by operation id):
                 ---------------------------------------------------
                    2 - access("TOTAL_SALES">=42 AND "TOTAL_SALES"<=142)
                 Statistics
                 ----------------------------------------------------------
                           0 recursive calls
                           0 db block gets
                        2150 consistent gets
                           0 physical reads
                           0 redo size
                       43308 bytes sent via SQL*Net to client
                        1987 bytes received via SQL*Net from client
                         135 SQL*Net roundtrips to/from client
                           0 sorts (memory)
                           0 sorts (disk)
                        2009 rows processed


The index is now significantly faster than the FTS which performs consistently …
  39   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Database vs. Storage Indexes
Have much in common:
• Both can eliminate reading unnecessary data within
  a table
• Efficiencies of both are directly impacted by the
  clustering of the data within the table
• Both may need a period of “warming” up before
  optimal use
• Both can combine multiple indexes to further
  increase efficiencies
40   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – Warm up
On the first execution of this query since table creation:
                       SQL> select artist_id, total_sales from big_bowie where album_id = 42;
                       100000 rows selected.
                       Elapsed: 00:00:00.89

                       Execution Plan
                       ---------------------------------------------------------------------------------------
                       | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                       ---------------------------------------------------------------------------------------
                       |   0 | SELECT STATEMENT          |           |   100K| 1269K| 36663    (1)| 00:07:20 |
                       |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE |     100K| 1269K| 36663    (1)| 00:07:20 |
                       ---------------------------------------------------------------------------------------

                       Predicate Information (identified by operation id):
                       ---------------------------------------------------

                              1 - storage("ALBUM_ID"=42)
                                  filter("ALBUM_ID"=42)

                       SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
                       s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
                       'cell physical IO bytes saved by storage index');

                       NAME                                                                     MB
                       ---------------------------------------------------------------- ----------
                       cell physical IO bytes saved by storage index                    114.601563
                       cell physical IO interconnect bytes returned by smart scan       1.77637482



  41   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – Warm up
Subsequent executions, many more IO bytes saved by “warm” storage index
             SQL> select artist_id, total_sales from big_bowie where album_id = 42;
             100000 rows selected.
             Elapsed: 00:00:00.27
             Execution Plan
             ---------------------------------------------------------------------------------------
             | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
             ---------------------------------------------------------------------------------------
             |   0 | SELECT STATEMENT          |           |   100K| 1269K| 36663    (1)| 00:07:20 |
             |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE |     100K| 1269K| 36663    (1)| 00:07:20 |
             ---------------------------------------------------------------------------------------
             Predicate Information (identified by operation id):
             ---------------------------------------------------
                    1 - storage("ALBUM_ID"=42)
                        filter("ALBUM_ID"=42)
             SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
             s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
             'cell physical IO bytes saved by storage index');
             NAME                                                                     MB
             ---------------------------------------------------------------- ----------
             cell physical IO bytes saved by storage index                    1156.84375
             cell physical IO interconnect bytes returned by smart scan       3.41764832



 42   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Database Indexes – Cache Sensitive
     SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142;
     2009 rows selected.
     Elapsed: 00:00:01.45
     Execution Plan
     -------------------------------------------------------------------------------------------------------
     | Id | Operation                    | Name                    | Rows | Bytes |Cost (%CPU)| Time      |
     -------------------------------------------------------------------------------------------------------
     |   0 | SELECT STATEMENT            |                         | 2040 | 26520 | 2048    (1)| 00:00:25 |
     |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE                | 2040 | 26520 | 2048    (1)| 00:00:25 |
     |* 2 |    INDEX RANGE SCAN          | BIG_BOWIE_TOTAL_SALES_I | 2040 |        |    7   (0)| 00:00:01 |
     -------------------------------------------------------------------------------------------------------
     Predicate Information (identified by operation id):
     ---------------------------------------------------
        2 - access("TOTAL_SALES">=42 AND "TOTAL_SALES"<=142)
     Statistics
     ----------------------------------------------------------
               1 recursive calls
               0 db block gets
            2150 consistent gets
            2005 physical reads
               0 redo size
           43311 bytes sent via SQL*Net to client
            1987 bytes received via SQL*Net from client
             135 SQL*Net roundtrips to/from client
               0 sorts (memory)
               0 sorts (disk)
            2009 rows processed



43    Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Database Indexes – Cache Sensitive
But on subsequent re-runs, when most of the data has been cached …
   SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142;
   2009 rows selected.
   Elapsed: 00:00:00.02
   Execution Plan
   -------------------------------------------------------------------------------------------------------
   | Id | Operation                    | Name                    | Rows | Bytes |Cost (%CPU)| Time      |
   -------------------------------------------------------------------------------------------------------
   |   0 | SELECT STATEMENT            |                         | 2040 | 26520 | 2048    (1)| 00:00:25 |
   |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE                | 2040 | 26520 | 2048    (1)| 00:00:25 |
   |* 2 |    INDEX RANGE SCAN          | BIG_BOWIE_TOTAL_SALES_I | 2040 |        |    7   (0)| 00:00:01 |
   -------------------------------------------------------------------------------------------------------
   Predicate Information (identified by operation id):
   ---------------------------------------------------
      2 - access("TOTAL_SALES">=42 AND "TOTAL_SALES"<=142)
   Statistics
   ----------------------------------------------------------
             0 recursive calls
             0 db block gets
          2150 consistent gets
             0 physical reads
             0 redo size
         43308 bytes sent via SQL*Net to client
          1987 bytes received via SQL*Net from client
           135 SQL*Net roundtrips to/from client
             0 sorts (memory)
             0 sorts (disk)
          2009 rows processed

The index is now significantly faster than previously
  44   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Smart Flash Cache
       Improves Database Index performance
       Random reads against tables and indexes are likely to have
        subsequent reads and normally will be cached and have their data
        subsequently delivered from the flash cache
       10x -100x better performance than disk
       Both table and index blocks cached




45   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – Combine
First, we run a query using a storage index on the ALBUM_ID column
       SQL> select * from big_bowie where album_id <= 10;
       1000002 rows selected.
       Elapsed: 00:00:06.41
       Execution Plan
       ---------------------------------------------------------------------------------------
       | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
       ---------------------------------------------------------------------------------------
       |   0 | SELECT STATEMENT          |           | 1009K|     88M| 36667   (1)| 00:07:21 |
       |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1009K|       88M| 36667   (1)| 00:07:21 |
       ---------------------------------------------------------------------------------------
       Predicate Information (identified by operation id):
       ---------------------------------------------------
             1 - storage("ALBUM_ID"<=10)
                 filter("ALBUM_ID"<=10)
       SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
       s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
       'cell physical IO bytes saved by storage index');
       NAME                                                                     MB
       ---------------------------------------------------------------- ----------
       cell physical IO bytes saved by storage index                    947.367188
       cell physical IO interconnect bytes returned by smart scan       94.2925186


  46   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – Combine
Next, we run a query using a storage index on the ARTIST_ID column
       SQL> select * from big_bowie where artist_id <= 10000;
       1000002 rows selected.
       Elapsed: 00:00:06.85
       Execution Plan
       ---------------------------------------------------------------------------------------
       | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
       ---------------------------------------------------------------------------------------
       |   0 | SELECT STATEMENT          |           | 1000K|     87M| 36676   (1)| 00:07:21 |
       |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1000K|       87M| 36676   (1)| 00:07:21 |
       ---------------------------------------------------------------------------------------
       Predicate Information (identified by operation id):
       ---------------------------------------------------
              1 - storage("ARTIST_ID"<=10000)
                  filter("ARTIST_ID"<=10000)
       SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
       s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
       'cell physical IO bytes saved by storage index');
       NAME                                                                     MB
       ---------------------------------------------------------------- ----------
       cell physical IO bytes saved by storage index                    850.140625
       cell physical IO interconnect bytes returned by smart scan       94.4599609


  47   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes – Combine
Finally, we run a query using storage indexes on both columns
        SQL> select * from big_bowie where album_id <= 10 and artist_id <= 10000;
        100002 rows selected.
        Elapsed: 00:00:00.52
        Execution Plan
        ---------------------------------------------------------------------------------------
        | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
        ---------------------------------------------------------------------------------------
        |   0 | SELECT STATEMENT          |           |   100K| 9066K| 36675    (1)| 00:07:21 |
        |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE |     100K| 9066K| 36675    (1)| 00:07:21 |
        ---------------------------------------------------------------------------------------
        Predicate Information (identified by operation id):
        ---------------------------------------------------
           1 - storage("ARTIST_ID"<=10000 AND "ALBUM_ID"<=10)
               filter("ARTIST_ID"<=10000 AND "ALBUM_ID"<=10)

        SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
        s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
        'cell physical IO bytes saved by storage index');
        NAME                                                                     MB
        ---------------------------------------------------------------- ----------
        cell physical IO bytes saved by storage index                     1031.4375
        cell physical IO interconnect bytes returned by smart scan       9.31826019

IO bytes saved by storage indexes is now greater than previous examples
  48   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Index Advantages
  Are created automatically and transparently
  Used automatically if present during Smart Scans
  Do not take up any physical storage (memory only)
  Have negligible impact on DML statements
  Effective in processing IS NULL predicates
  Might make corresponding Database indexes redundant
  As they’re used during Smart Scans, when used can return
     just the rows/columns of interest to the database

49   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Index Disadvantages
 Limited to a max of 8 columns per table
 May not exist on a particular column at a point in time
 Not as “focused” (1MB storage region default vs. 1 data block)
 Has limitations, can only use Min/Max as referenced data
 Database indexes determines specific location of data while a SI can only
  determine where data can’t exist
 Therefore SI can still access unnecessarily storage of no interest
 Can not cache data in database buffer cache for general re-usability
 The CBO is not aware of Storage Indexes savings
 Not as general purpose as database indexes (can’t police constraints,
  avoid sorts, provide CBO statistics, etc.)
50   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
SQL> create table radiohead (id number, col1 number, col2 number, col3 number, col4 number, col5 number, col6 number, col7
number, col8 number, col9 number, col10 number, col11 number, col12 number, some_text varchar2(50));
Table created.
SQL> insert into radiohead select rownum, mod(rownum,10), mod(rownum,100), mod(rownum,1000), mod(rownum,10000),
mod(rownum,100000), mod(rownum,1000000), ceil(dbms_random.value(0,10)), ceil(dbms_random.value(0,100)),
ceil(dbms_random.value(0,1000)), ceil(dbms_random.value(0,10000)), ceil(dbms_random.value(0,100000)),
ceil(dbms_random.value(0,1000000)), 'OK COMPUTER' from dual connect by level <=2000000;
2000000 rows created.
SQL> commit;
Commit complete.
SQL> insert/*+ append */ into radiohead select * from radiohead;
2000000 rows created.
SQL> commit;
Commit complete.
SQL> insert/*+ append */ into radiohead select * from radiohead;
4000000 rows created.
SQL> commit;
Commit complete.
SQL> insert/*+ append */ into radiohead select * from radiohead;
8000000 rows created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'RADIOHEAD', estimate_percent=>null, method_opt=> 'FOR ALL
COLUMNS SIZE 1');




 51   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
                  SQL> select * from radiohead where id = 42;
                  8 rows selected.
                  Elapsed: 00:00:00.05

                  Execution Plan
                  ---------------------------------------------------------------------------------------
                  | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                  ---------------------------------------------------------------------------------------
                  |   0 | SELECT STATEMENT          |           |     8 |   416 | 42425   (1)| 00:08:30 |
                  |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD |       8 |   416 | 42425   (1)| 00:08:30 |
                  ---------------------------------------------------------------------------------------
                  Predicate Information (identified by operation id):
                  ---------------------------------------------------
                         1 - storage("ID"=121212)
                             filter("ID"=121212)

                  SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
                  s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
                  'cell physical IO bytes saved by storage index');

                  NAME                                                                     MB
                  ---------------------------------------------------------------- ----------
                  cell physical IO bytes saved by storage index                    1333.99219
                  cell physical IO interconnect bytes returned by smart scan       .164878845


Storage index created on the ID column …

52   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
Repeat with predicates based on each of the table columns
                      SQL> select * from radiohead where col1=42;
                      no rows selected
                      Elapsed: 00:00:00.01
                      Execution Plan
                      ---------------------------------------------------------------------------------------
                      | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                      ---------------------------------------------------------------------------------------
                      |   0 | SELECT STATEMENT          |           |     1 |    52 | 42440   (1)| 00:08:30 |
                      |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD |       1 |    52 | 42440   (1)| 00:08:30 |
                      ---------------------------------------------------------------------------------------
                      Predicate Information (identified by operation id):
                      ---------------------------------------------------
                              1 - storage("COL1"=42)
                                  filter("COL1"=42)
                      SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
                      s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
                      'cell physical IO bytes saved by storage index');
                      NAME                                                                     MB
                      ---------------------------------------------------------------- ----------
                      cell physical IO bytes saved by storage index                    2546.90625
                      cell physical IO interconnect bytes returned by smart scan       .341438293


The storage index on the COL1 column is used as well (can be useful in situations
when the required value doesn’t exist)…

 53   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
A Storage index is also used on COL4 although because of the distribution of data,
the saved I/Os is limited
                 SQL> select * from radiohead where col4=42;
                 1600 rows selected.
                 Elapsed: 00:00:00.68
                 Execution Plan
                 ---------------------------------------------------------------------------------------
                 | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                 ---------------------------------------------------------------------------------------
                 |   0 | SELECT STATEMENT          |           | 1600 | 83200 | 42486    (1)| 00:08:30 |
                 |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 1600 | 83200 | 42486      (1)| 00:08:30 |
                 ---------------------------------------------------------------------------------------
                 Predicate Information (identified by operation id):
                 ---------------------------------------------------
                        1 - storage("COL4"=42)
                            filter("COL4"=42)
                 SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
                 s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
                 'cell physical IO bytes saved by storage index');
                 NAME                                                                     MB
                 ---------------------------------------------------------------- ----------
                 cell physical IO bytes saved by storage index                    2612.64063   <= + 66MB
                 cell physical IO interconnect bytes returned by smart scan       32.3048401


 54   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
A Storage index is also used on, COL5, COL6, COL7, Col8 and COL9 making a
total of 8 storage indexes defined on this table
                      SQL> select * from radiohead where col9=0;
                      no rows selected
                      Elapsed: 00:00:00.02
                      Execution Plan
                      ---------------------------------------------------------------------------------------
                      | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                      ---------------------------------------------------------------------------------------
                      |   0 | SELECT STATEMENT          |           | 15984 |   811K| 42561   (1)| 00:08:31 |
                      |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 15984 |     811K| 42561   (1)| 00:08:31 |
                      ---------------------------------------------------------------------------------------
                      Predicate Information (identified by operation id):
                      ---------------------------------------------------
                             1 - storage("COL9"=0)
                                 filter("COL9"=0)
                      SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
                      s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
                      'cell physical IO bytes saved by storage index');
                      NAME                                                                     MB
                      ---------------------------------------------------------------- ----------
                      cell physical IO bytes saved by storage index                    8792.94531
                      cell physical IO interconnect bytes returned by smart scan       45.3872757



 55   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
However although a smart scan is performed, a viable storage index is not now
created on COL10 column with 8 existing storage indexes
               SQL> select * from radiohead where col10=42;
               1536 rows selected.
               Elapsed: 00:00:00.73
               Execution Plan
               ---------------------------------------------------------------------------------------
               | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
               ---------------------------------------------------------------------------------------
               |   0 | SELECT STATEMENT          |           | 1600 | 83200 | 42577    (1)| 00:08:31 |
               |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 1600 | 83200 | 42577      (1)| 00:08:31 |
               ---------------------------------------------------------------------------------------
               Predicate Information (identified by operation id):
               ---------------------------------------------------
                      1 - storage("COL10"=42)
                          filter("COL10"=42)
               SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
               s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
               'cell physical IO bytes saved by storage index');
               NAME                                                                     MB
               ---------------------------------------------------------------- ----------
               cell physical IO bytes saved by storage index                    8792.94531    No change
               cell physical IO interconnect bytes returned by smart scan       45.9288864



 56   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
On this much more selective query on COL12, a new storage index is created
                   SQL> select * from radiohead where col12=42;
                   8 rows selected.
                   Elapsed: 00:00:00.39

                   Execution Plan
                   ---------------------------------------------------------------------------------------
                   | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                   ---------------------------------------------------------------------------------------
                   |   0 | SELECT STATEMENT          |           |    19 |   988 | 42607   (1)| 00:08:32 |
                   |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD |      19 |   988 | 42607   (1)| 00:08:32 |
                   ---------------------------------------------------------------------------------------

                   Predicate Information (identified by operation id):
                   ---------------------------------------------------

                          1 - storage("COL12"=42)
                              filter("COL12"=42)

                   SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
                   s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
                   'cell physical IO bytes saved by storage index');

                   NAME                                                                     MB
                   ---------------------------------------------------------------- ----------
                   cell physical IO bytes saved by storage index                    9526.01563
                   cell physical IO interconnect bytes returned by smart scan       53.5218124



  57   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
If we go back to the first query on the ID column, the storage index is still used …
                     SQL> select * from radiohead where id=42;
                     8 rows selected.
                     Elapsed: 00:00:00.05
                     Execution Plan
                     ---------------------------------------------------------------------------------------
                     | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                     ---------------------------------------------------------------------------------------
                     |   0 | SELECT STATEMENT          |           |     8 |   416 | 42425   (1)| 00:08:30 |
                     |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD |       8 |   416 | 42425   (1)| 00:08:30 |
                     ---------------------------------------------------------------------------------------
                     Predicate Information (identified by operation id):
                     ---------------------------------------------------
                            1 - storage("ID"=42)
                                filter("ID"=42)
                     SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
                     s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
                     'cell physical IO bytes saved by storage index');
                     NAME                                                                     MB
                     ---------------------------------------------------------------- ----------
                     cell physical IO bytes saved by storage index                    10726.9844
                     cell physical IO interconnect bytes returned by smart scan       53.5264816



 58   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes: 8 Column Limit
But if we go back to the not so selective query on the COL4 column, the storage
index is no longer used as it was previously …
                SQL> select * from radiohead where col4 = 4242;
                1600 rows selected.
                Elapsed: 00:00:00.73
                Execution Plan
                ---------------------------------------------------------------------------------------
                | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                ---------------------------------------------------------------------------------------
                |   0 | SELECT STATEMENT          |           | 1600 | 83200 | 42486    (1)| 00:08:30 |
                |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 1600 | 83200 | 42486      (1)| 00:08:30 |
                ---------------------------------------------------------------------------------------
                Predicate Information (identified by operation id):
                ---------------------------------------------------
                       1 - storage("COL4"=4242)
                           filter("COL4"=4242)
                SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
                s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
                'cell physical IO bytes saved by storage index');
                NAME                                                                     MB
                ---------------------------------------------------------------- ----------
                cell physical IO bytes saved by storage index                    10726.9844  No Change !!
                cell physical IO interconnect bytes returned by smart scan       54.1522598


The Storage Index on COL4 is replaced by the Storage Index on COL12 …
 59   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
“Hidden” Values of Interest
Returning to the BIG_BOWIE table, the FORMAT_ID column has values 2 – 10, but
only a handful with a value of 3 and 5 …
          SQL> update big_bowie set format_id = 3 where mod(id,10000)=0;
          1000 rows updated.

          SQL> commit;
          Commit complete.

          SQL> update big_bowie set format_id = 5 where id between 424242 and 425241;
          1000 rows updated.

          SQL> commit;
          Commit complete.

          SQL> create index big_bowie_format_id_i on big_bowie(format_id);
          Index created.

          SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'BIG_BOWIE',
          method_opt=> 'FOR COLUMNS FORMAT_ID SIZE 10');

          PL/SQL procedure successfully completed.


  60   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
“Hidden” Values of Interest
With a histogram in place, the CBO uses an index very effectively …
  SQL> select album_id, total_sales from big_bowie where format_id = 3;
  1000 rows selected.
  Elapsed: 00:00:00.01
  Execution Plan
  -----------------------------------------------------------------------------------------------------
  | Id | Operation                    | Name                  | Rows | Bytes | Cost (%CPU)| Time      |
  -----------------------------------------------------------------------------------------------------
  |   0 | SELECT STATEMENT            |                       | 1000 | 11000 |     72   (0)| 00:00:01 |
  |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE              | 1000 | 11000 |     72   (0)| 00:00:01 |
  |* 2 |    INDEX RANGE SCAN          | BIG_BOWIE_FORMAT_ID_I | 1000 |        |     4   (0)| 00:00:01 |
  -----------------------------------------------------------------------------------------------------
  Predicate Information (identified by operation id):
  ---------------------------------------------------
        2 - access("FORMAT_ID"=3)
  Statistics
  ----------------------------------------------------------
            0 recursive calls
            0 db block gets
         1072 consistent gets
            0 physical reads
            0 redo size
        22984 bytes sent via SQL*Net to client
         1250 bytes received via SQL*Net from client
           68 SQL*Net roundtrips to/from client
            0 sorts (memory)
            0 sorts (disk)
         1000 rows processed



 61   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
“Hidden” Values of Interest
Whereas value 3 was littered throughout the table, values 5 are all clustered
together, making the index even more effective …
 SQL> select album_id, total_sales from big_bowie where format_id = 5;
 1000 rows selected.
 Elapsed: 00:00:00.00
 Execution Plan
 -----------------------------------------------------------------------------------------------------
 | Id | Operation                    | Name                  | Rows | Bytes | Cost (%CPU)| Time      |
 -----------------------------------------------------------------------------------------------------
 |   0 | SELECT STATEMENT            |                       | 1000 | 11000 |     72   (0)| 00:00:01 |
 |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE              | 1000 | 11000 |     72   (0)| 00:00:01 |
 |* 2 |    INDEX RANGE SCAN          | BIG_BOWIE_FORMAT_ID_I | 1000 |        |     4   (0)| 00:00:01 |
 -----------------------------------------------------------------------------------------------------
 Predicate Information (identified by operation id):
 ---------------------------------------------------
    2 - access("FORMAT_ID"=5)
 Statistics
 ----------------------------------------------------------
           0 recursive calls
           0 db block gets
         154 consistent gets
           0 physical reads
           0 redo size
       22685 bytes sent via SQL*Net to client
        1250 bytes received via SQL*Net from client
          68 SQL*Net roundtrips to/from client
           0 sorts (memory)
           0 sorts (disk)
        1000 rows processed



 62   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
“Hidden” Values of Interest
Smart Scan performed but a storage index is totally ineffective as the required values
are “hidden” between the min/max (2 – 10) range found in most 1MB storage regions
              SQL> alter index big_bowie_format_id_i invisible;
              Index altered.
              SQL> select album_id, total_sales from big_bowie where format_id = 3;
              1000 rows selected.
              Elapsed: 00:00:00.80
              Execution Plan
              ---------------------------------------------------------------------------------------
              | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
              ---------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT          |           | 1000 | 11000 | 36682    (1)| 00:07:21 |
              |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1000 | 11000 | 36682      (1)| 00:07:21 |
              ---------------------------------------------------------------------------------------
              Predicate Information (identified by operation id):
              ---------------------------------------------------
                     1 - storage("FORMAT_ID"=3)
                         filter("FORMAT_ID"=3)
              SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
              s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
              'cell physical IO bytes saved by storage index');
              NAME                                                                     MB
              ---------------------------------------------------------------- ----------
              cell physical IO bytes saved by storage index                             0
              cell physical IO interconnect bytes returned by smart scan       .397476196



 63   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
“Hidden” Values of Interest
In both cases, Storage Index is not used with Database index considerably faster …
            SQL> select album_id, total_sales from big_bowie where format_id = 5;
            1000 rows selected.
            Elapsed: 00:00:00.89

            Execution Plan
            ---------------------------------------------------------------------------------------
            | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
            ---------------------------------------------------------------------------------------
            |   0 | SELECT STATEMENT          |           | 1000 | 11000 | 36682    (1)| 00:07:21 |
            |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1000 | 11000 | 36682      (1)| 00:07:21 |
            ---------------------------------------------------------------------------------------
            Predicate Information (identified by operation id):
            ---------------------------------------------------
                   1 - storage("FORMAT_ID"=5)
                       filter("FORMAT_ID"=5)
            SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# =
            s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan',
            'cell physical IO bytes saved by storage index');

            NAME                                                                     MB
            ---------------------------------------------------------------- ----------
            cell physical IO bytes saved by storage index                             0
            cell physical IO interconnect bytes returned by smart scan       .565643311



 64   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
OLTP Environments
 In OLTP environments, most queries and processes are
  based on highly selective data where database indexes are
  more viable
 Indexes used for more than just “selecting” data, for example:
      – Police Primary and Unique Key constraints
      – Reduce locking implications with Foreign Keys
      – Reduce sorting requirements
      – Reduce function-based processing
      – Provide additional selectivity data to the CBO


 65   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Storage Indexes - Unique Scan
With a storage index in place, a FTS is no longer really a FTS …
                      SQL> select album_id, artist_id from big_bowie where id = 42;
                      Elapsed: 00:00:00.02
                      Execution Plan
                      ---------------------------------------------------------------------------------------
                      | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                      ---------------------------------------------------------------------------------------
                      |   0 | SELECT STATEMENT          |           |     1 |    14 | 36653   (1)| 00:07:20 |
                      |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE |       1 |    14 | 36653   (1)| 00:07:20 |
                      ---------------------------------------------------------------------------------------
                      Predicate Information (identified by operation id):
                      ---------------------------------------------------
                         1 - storage("ID"=42)
                             filter("ID"=42)
                      Statistics
                      ----------------------------------------------------------
                                0 recursive calls
                                0 db block gets
                           134834 consistent gets
                           134809 physical reads
                                0 redo size
                              600 bytes sent via SQL*Net to client
                              524 bytes received via SQL*Net from client
                                2 SQL*Net roundtrips to/from client
                                0 sorts (memory)
                                0 sorts (disk)
                                1 rows processed
                      NAME                                                                     MB
                      ---------------------------------------------------------------- ----------
                      cell physical IO bytes saved by storage index                    1052.22656
                      cell physical IO interconnect bytes returned by smart scan       .000419617



 66   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Unique Scan
However, an index is even faster and potentially far more scalable …
         SQL> select album_id, artist_id from big_bowie where id = 42;
         Elapsed: 00:00:00.00
         Execution Plan
         --------------------------------------------------------------------------------------------
         | Id | Operation                    | Name         | Rows | Bytes | Cost (%CPU)| Time      |
         --------------------------------------------------------------------------------------------
         |   0 | SELECT STATEMENT            |              |     1 |    14 |     3   (0)| 00:00:01 |
         |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE     |     1 |    14 |     3   (0)| 00:00:01 |
         |* 2 |    INDEX UNIQUE SCAN         | BIG_BOWIE_PK |     1 |       |     2   (0)| 00:00:01 |
         --------------------------------------------------------------------------------------------
         Predicate Information (identified by operation id):
         ---------------------------------------------------
                2 - access("ID"=42)
         Statistics
         ----------------------------------------------------------
                   0 recursive calls
                   0 db block gets
                   4 consistent gets
                   0 physical reads
                   0 redo size
                 600 bytes sent via SQL*Net to client
                 524 bytes received via SQL*Net from client
                   2 SQL*Net roundtrips to/from client
                   0 sorts (memory)
                   0 sorts (disk)
                   1 rows processed



 67   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Primary and Unique Keys
Then there’s the issue of removing an index that enforces either a Primary or Unique
Key constraint …
SQL> drop index big_bowie_pk;
drop index big_bowie_pk
           *
ERROR at line 1:
ORA-02429: cannot drop index used for enforcement of unique/primary key

SQL> alter table big_bowie drop primary key;

Table altered


A Storage Index can not be used to enforce constraints.




 68   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Foreign Key Constraints
Indexes can be critical in preventing locking issues with regard to Foreign Key
Constraints…
SQL> create table albums (id number, name varchar2(50));
Table created.
SQL> insert into albums select rownum, table_name from dba_tables where rownum <=101;
101 rows created.
SQL> commit;
Commit complete.
SQL> alter table albums add constraint albums_pk primary key (id);
Table altered.
SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'ALBUMS', estimate_percent=>null,
method_opt=> 'FOR ALL COLUMNS SIZE 1');
PL/SQL procedure successfully completed.
SQL> alter table big_bowie add constraint albums_fk foreign key (album_id) referencing albums(id);
Table altered.



 69   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Foreign Key Constraints
 In Session 1 (no commit)
SQL> insert into big_bowie values (10000001, 1, 1, 1, sysdate, 1, 'TEST');

1 row created.

 In Session 2 (hangs !!)
SQL> delete albums where id = 101;




 In Session 3 (hangs !!)
SQL> insert into big_bowie values (10000002, 1,1,1,sysdate,1,'TEST2');



A Storage Index can not prevent Foreign Key locking related issues …

 70   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Foreign Key Constraints
In Session 1 (no commit)
SQL> create index big_bowie_album_id_i on big_bowie(album_id);

Index created.

SQL> insert into big_bowie values (10000001, 1, 1, 1, sysdate, 1, 'TEST');

1 row created.


In Session 2 (no longer hangs)
SQL> delete albums where id = 101;

1 row deleted.

In Session 3 (no longer hangs)
SQL> insert into big_bowie values (10000002, 1,1,1,sysdate,1,'TEST2');

1 row created.


 71   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Database Indexes and Sorts
Database indexes return data in a sorted manner and so can avoid expensive sort
operations …
           SQL> select * from big_bowie where album_id between 1 and 50 order by album_id;
           5000002 rows selected.
           Elapsed: 00:00:13.08
           Execution Plan
           ----------------------------------------------------------------------------------------------------
           | Id | Operation                    | Name                 | Rows | Bytes | Cost (%CPU)| Time      |
           ----------------------------------------------------------------------------------------------------
           |   0 | SELECT STATEMENT            |                      | 5049K|    443M| 79536   (1)| 00:15:55 |
           |   1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE             | 5049K|    443M| 79536   (1)| 00:15:55 |
           |* 2 |    INDEX RANGE SCAN          | BIG_BOWIE_ALBUM_ID_I | 5049K|        | 9916    (1)| 00:01:59 |
           ----------------------------------------------------------------------------------------------------
           Predicate Information (identified by operation id):
           ---------------------------------------------------
              2 - access("ALBUM_ID">=1 AND "ALBUM_ID"<=50)
           Statistics
           ----------------------------------------------------------
                     0 recursive calls
                     0 db block gets
                 80506 consistent gets
                     0 physical reads
                     0 redo size
             483419167 bytes sent via SQL*Net to client
                 11524 bytes received via SQL*Net from client
                  1002 SQL*Net roundtrips to/from client
                     0 sorts (memory)
                     0 sorts (disk)
               5000002 rows processed



 72   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Database Indexes and Sorts
               SQL> alter index big_bowie_album_id_i invisible;
               Index altered.
               SQL> select * from big_bowie where album_id between 1 and 50 order by album_id;
               5000002 rows selected.
               Elapsed: 00:00:18.89
               Execution Plan
               ------------------------------------------------------------------------------------------------
               | Id | Operation                   | Name      | Rows | Bytes |TempSpc| Cost (%CPU)| Time      |
               ------------------------------------------------------------------------------------------------
               |   0 | SELECT STATEMENT           |           | 5049K|    443M|       |    143K (1)| 00:28:48 |
               |   1 | SORT ORDER BY              |           | 5049K|    443M|   547M|    143K (1)| 00:28:48 |
               |* 2 |    TABLE ACCESS STORAGE FULL| BIG_BOWIE | 5049K|    443M|       |   36855 (1)| 00:07:23 |
               ------------------------------------------------------------------------------------------------
               Predicate Information (identified by operation id):
               ---------------------------------------------------
                  2 - storage("ALBUM_ID"<=50 AND "ALBUM_ID">=1)
                      filter("ALBUM_ID"<=50 AND "ALBUM_ID">=1)
               Statistics
               ----------------------------------------------------------
                       501 recursive calls
                        10 db block gets
                    134798 consistent gets
                    198875 physical reads
                         0 redo size
                 155412142 bytes sent via SQL*Net to client
                     11524 bytes received via SQL*Net from client
                      1002 SQL*Net roundtrips to/from client
                         0 sorts (memory)
                         1 sorts (disk)
                   5000002 rows processed
               NAME                                                                     MB
               ---------------------------------------------------------------- ----------
               cell physical IO bytes saved by storage index                    401.195313
               cell physical IO interconnect bytes returned by smart scan       476.618843



73   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
NULLs and Storage Indexes
Storage Indexes include NULL flag to determine which storage regions contain NULLs
                       SQL> select count(*) from big_bowie where total_sales is null;
                         COUNT(*)
                       ----------
                                0
                       Elapsed: 00:00:00.04
                       Execution Plan
                       ----------------------------------------------------------------------------------------
                       | Id | Operation                   | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                       ----------------------------------------------------------------------------------------
                       |   0 | SELECT STATEMENT           |           |     1 |     5 | 36686   (1)| 00:07:21 |
                       |   1 | SORT AGGREGATE             |           |     1 |     5 |            |          |
                       |* 2 |    TABLE ACCESS STORAGE FULL| BIG_BOWIE |     1 |     5 | 36686   (1)| 00:07:21 |
                       ----------------------------------------------------------------------------------------
                       Predicate Information (identified by operation id):
                       ---------------------------------------------------
                              2 - storage("TOTAL_SALES" IS NULL)
                                  filter("TOTAL_SALES" IS NULL)
                       NAME                                                                     MB
                       ---------------------------------------------------------------- ----------
                       cell physical IO bytes saved by storage index                    1053.19531
                       cell physical IO interconnect bytes returned by smart scan                0




   74   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Offloading Functions
               SQL> select id, album_id, mod(artist_id, 10) from dwh_bowie where album_id = 42;
               6400000 rows selected.
               Elapsed: 00:00:11.39
               Execution Plan
               ---------------------------------------------------------------------------------------
               | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
               ---------------------------------------------------------------------------------------
               |   0 | SELECT STATEMENT          |           | 6400K|     85M| 2348K (1)| 07:49:38 |
               |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 6400K|       85M| 2348K (1)| 07:49:38 |
               ---------------------------------------------------------------------------------------
               Predicate Information (identified by operation id):
               ---------------------------------------------------
                     1 - storage("ALBUM_ID"=42)
                         filter("ALBUM_ID"=42)
               Statistics
               ----------------------------------------------------------
                         1 recursive calls
                         0 db block gets
                   8626963 consistent gets
                   8625479 physical reads
                         0 redo size
                  82753965 bytes sent via SQL*Net to client
                     14593 bytes received via SQL*Net from client
                      1281 SQL*Net roundtrips to/from client
                         0 sorts (memory)
                         0 sorts (disk)
                   6400000 rows processed
               NAME                                                                     MB
               ---------------------------------------------------------------- ----------
               cell physical IO bytes saved by storage index                    44460.3828
               cell physical IO interconnect bytes returned by smart scan       129.252693



75   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Offloading Functions
Processing of many function calls can also be offloaded to the
storage cells.
To see the full list, simple run :
SQL> select name from v$sqlfn_metadata where offloadable = 'YES' order by name;



However, you can not base a storage index on a function;
Function-Based Storage Indexes are not supported …

Additionally, many functions can not currently be offloaded …

 76   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Function-Based Indexes
              SQL> select id, album_id, mod(artist_id, 10) from dwh_bowie where trunc(album_id)=42;
              6400000 rows selected.
              Elapsed: 00:00:28.71
              Execution Plan
              ---------------------------------------------------------------------------------------
              | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
              ---------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT          |           | 6400K|     85M| 2351K (1)| 07:50:14 |
              |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 6400K|       85M| 2351K (1)| 07:50:14 |
              ---------------------------------------------------------------------------------------
              Predicate Information (identified by operation id):
              ---------------------------------------------------
                    1 - storage(TRUNC("ALBUM_ID")=42)
                        filter(TRUNC("ALBUM_ID")=42)
              Statistics
              ----------------------------------------------------------
                        1 recursive calls
                        0 db block gets
                  8626963 consistent gets
                  8625479 physical reads
                        0 redo size
                 82753965 bytes sent via SQL*Net to client
                    14593 bytes received via SQL*Net from client
                     1281 SQL*Net roundtrips to/from client
                        0 sorts (memory)
                        0 sorts (disk)
                  6400000 rows processed
              NAME                                                                     MB
              ---------------------------------------------------------------- ----------
              cell physical IO bytes saved by storage index                    44460.3828   <= no change !!
              cell physical IO interconnect bytes returned by smart scan       264.957054



77   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Min/Mix Example
            SQL> select min(id) from dwh_bowie;
               MIN(ID)
            ----------
                     1
            Elapsed: 00:00:41.31
            Execution Plan
            ----------------------------------------------------------------------------------------
            | Id | Operation                   | Name      | Rows | Bytes | Cost (%CPU)| Time      |
            ----------------------------------------------------------------------------------------
            |   0 | SELECT STATEMENT           |           |     1 |     6 | 2345K (1)| 07:49:12 |
            |   1 | SORT AGGREGATE             |           |     1 |     6 |            |          |
            |   2 |   TABLE ACCESS STORAGE FULL| DWH_BOWIE |   640M| 3662M| 2345K (1)| 07:49:12 |
            ----------------------------------------------------------------------------------------
            Statist5ics
            ----------------------------------------------------------
                      0 recursive calls
                      0 db block gets
                8626963 consistent gets
                8625479 physical reads
                      0 redo size
                    525 bytes sent via SQL*Net to client
                    524 bytes received via SQL*Net from client
                      2 SQL*Net roundtrips to/from client
                      0 sorts (memory)
                      0 sorts (disk)
                      1 rows processed
            NAME                                                                     MB
            ---------------------------------------------------------------- ----------
            cell physical IO bytes saved by storage index                             0
            cell physical IO interconnect bytes returned by smart scan       7644.38194



78   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Min/Mix Example
           SQL> create index dwh_bowie_id_i on dwh_bowie(id);
           Index created.
           SQL> select min(id) from dwh_bowie;
              MIN(ID)
           ----------
                    1
           Elapsed: 00:00:00.01
           Execution Plan
           ---------------------------------------------------------------------------------------------
           | Id | Operation                   | Name           | Rows | Bytes | Cost (%CPU)| Time      |
           ---------------------------------------------------------------------------------------------
           |   0 | SELECT STATEMENT           |                |     1 |     6 |     4   (0)| 00:00:01 |
           |   1 | SORT AGGREGATE             |                |     1 |     6 |            |          |
           |   2 |   INDEX FULL SCAN (MIN/MAX)| DWH_BOWIE_ID_I |     1 |     6 |     4   (0)| 00:00:01 |
           ---------------------------------------------------------------------------------------------
           Statistics
           ----------------------------------------------------------
                     1 recursive calls
                     0 db block gets
                     4 consistent gets
                      3 physical reads
                     0 redo size
                   525 bytes sent via SQL*Net to client
                   524 bytes received via SQL*Net from client
                     2 SQL*Net roundtrips to/from client
                     0 sorts (memory)
                     0 sorts (disk)
                     1 rows processed



79   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Smart Scans and Serial DML
                SQL> update dwh_bowie set description = 'ZIGGY' where total_sales = 42;
                1472 rows updated.
                Elapsed: 00:15:00.38
                Execution Plan
                ----------------------------------------------------------------------------------------
                | Id | Operation                   | Name      | Rows | Bytes | Cost (%CPU)| Time      |
                ----------------------------------------------------------------------------------------
                |   0 | UPDATE STATEMENT           |           | 1264 | 84688 | 2350K (1)| 07:50:07 |
                |   1 | UPDATE                     | DWH_BOWIE |       |       |            |          |
                |* 2 |    TABLE ACCESS STORAGE FULL| DWH_BOWIE | 1264 | 84688 | 2350K (1)| 07:50:07 |
                ----------------------------------------------------------------------------------------
                Predicate Information (identified by operation id):
                ---------------------------------------------------
                   2 - storage("TOTAL_SALES"=42)
                       filter("TOTAL_SALES"=42)
                Statistics
                ----------------------------------------------------------
                          8 recursive calls
                       1525 db block gets
                    8632370 consistent gets
                    8622545 physical reads
                     485364 redo size
                        559 bytes sent via SQL*Net to client
                        749 bytes received via SQL*Net from client
                          3 SQL*Net roundtrips to/from client
                          2 sorts (memory)
                          0 sorts (disk)
                       1472 rows processed
                NAME                                                                     MB
                ---------------------------------------------------------------- ----------
                cell physical IO bytes saved by storage index                             0
                cell physical IO interconnect bytes returned by smart scan                0



80   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Smart Scans and Parallel DML
SQL> update /*+ parallel */ dwh_bowie set description = 'ZIGGY' where total_sales = 42;
1472 rows updated.
Elapsed: 00:00:18.26
Execution Plan
------------------------------------------------------------------------------------------------------------------------
| Id | Operation                      | Name      | Rows | Bytes | Cost (%CPU)| Time      |    TQ |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT              |           | 1264 | 84688 | 27171    (1)| 00:00:55 |        |      |            |
|   1 | UPDATE                        | DWH_BOWIE |       |       |            |          |        |      |            |
|   2 |   PX COORDINATOR              |           |       |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM)        | :TQ10000 | 1264 | 84688 | 27171     (1)| 00:00:55 | Q1,00 | P->S | QC (RAND) |
|   4 |     PX BLOCK ITERATOR         |           | 1264 | 84688 | 27171    (1)| 00:00:55 | Q1,00 | PCWC |             |
|* 5 |       TABLE ACCESS STORAGE FULL| DWH_BOWIE | 1264 | 84688 | 27171    (1)| 00:00:55 | Q1,00 | PCWP |             |
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   5 - storage("TOTAL_SALES"=42)
       filter("TOTAL_SALES"=42)
Statistics
----------------------------------------------------------
        336 recursive calls
       1525 db block gets
   10476664 consistent gets
    8625479 physical reads
     567008 redo size
        550 bytes sent via SQL*Net to client
        766 bytes received via SQL*Net from client
          3 SQL*Net roundtrips to/from client
          1 sorts (memory)
          0 sorts (disk)
       1472 rows processed
NAME                                                                     MB
---------------------------------------------------------------- ----------
cell physical IO bytes saved by storage index                    29342.4453
cell physical IO interconnect bytes returned by smart scan       5.97057343



  81   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Indexes and DML
An Index can still be the best and most scalable option with selective DML …
         SQL> create index dwh_bowie_total_sales_i on dwh_bowie(total_sales);
         Index created.
         SQL> update dwh_bowie set description = 'ZIGGY' where total_sales = 42;
         1472 rows updated.
         Elapsed: 00:00:00.92
         Execution Plan
         ---------------------------------------------------------------------------------------------
         | Id | Operation          | Name                    | Rows | Bytes | Cost (%CPU)| Time      |
         ---------------------------------------------------------------------------------------------
         |   0 | UPDATE STATEMENT |                          | 1264 | 84688 | 1270     (0)| 00:00:16 |
         |   1 | UPDATE            | DWH_BOWIE               |       |       |            |          |
         |* 2 |    INDEX RANGE SCAN| DWH_BOWIE_TOTAL_SALES_I | 1264 | 84688 |      6   (0)| 00:00:01 |
         ---------------------------------------------------------------------------------------------
         Predicate Information (identified by operation id):
         ---------------------------------------------------
            2 - access("TOTAL_SALES"=42)
         Statistics
         ----------------------------------------------------------
                   0 recursive calls
                1523 db block gets
                   7 consistent gets
                   0 physical reads
              508060 redo size
                 563 bytes sent via SQL*Net to client
                 750 bytes received via SQL*Net from client
                   3 SQL*Net roundtrips to/from client
                   1 sorts (memory)
                   0 sorts (disk)
                1472 rows processed



 82   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Data Warehouse Environments
  Constraint management may not be such an issue
  Typically, queries can be large, expensive affairs
  Use of Full Table/Index Scans more prevalent
  Smart Scans and Storage Indexes more viable
  Good opportunity to drop unnecessary indexes
  However, InfiniBand is not Infinite-Band
  However, overall load and scalability still a consideration
  However, database indexes can still be effective




83   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
DWH Join Example – Serial Execution
            SQL> select * from dwh_bowie d, albums a, formats f where d.album_id = a.id and d.format_id=f.id
            and a.name in ('TAB$', 'COL$') and f.name = 'I_USER#';
            64000 rows selected.
            Elapsed: 00:02:50.05
            Execution Plan
            ------------------------------------------------------------------------------------------
            | Id | Operation                     | Name      | Rows | Bytes | Cost (%CPU)|Time      |
            ------------------------------------------------------------------------------------------
            |   0 | SELECT STATEMENT             |           | 1600K|    177M| 2352K (1)|07:50:33 |
            |* 1 | HASH JOIN                     |           | 1600K|    177M| 2352K (1)|07:50:33 |
            |   2 |   MERGE JOIN CARTESIAN       |           |     2 |    48 |    36   (0)|00:00:01 |
            |* 3 |     TABLE ACCESS STORAGE FULL | FORMATS   |     1 |    11 |    18   (0)|00:00:01 |
            |   4 |    BUFFER SORT               |           |     2 |    26 |    18   (0)|00:00:01 |
            |* 5 |      TABLE ACCESS STORAGE FULL| ALBUMS    |     2 |    26 |    18   (0)|00:00:01 |
            |   6 |   TABLE ACCESS STORAGE FULL | DWH_BOWIE |    640M|    54G| 2349K (1)|07:49:56 |
            ------------------------------------------------------------------------------------------
            Predicate Information (identified by operation id):
            ---------------------------------------------------
                   1 - access("D"."ALBUM_ID"="A"."ID" AND "D"."FORMAT_ID"="F"."ID")
                   3 - storage("F"."NAME"='I_USER#')
                       filter("F"."NAME"='I_USER#')
                   5 - storage("A"."NAME"='COL$' OR "A"."NAME"='TAB$')
                       filter("A"."NAME"='COL$' OR "A"."NAME"='TAB$')
            NAME                                                                     MB
            ---------------------------------------------------------------- ----------
            cell physical IO bytes saved by storage index                             0
            cell physical IO interconnect bytes returned by smart scan       61084.5128



84   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Join Bloom Filter
 A bloom filter is a bitmap like structure (bit vector) that determines
  whether a value belongs to a given set or not
 Used since Oracle10g R2 in parallel join processing and since
  Oracle11g R1 in join-filter processing
 On Exadata the bloom filter is passed as an additional predicate so it
  can be overloaded to the storage cells making bloom filtering very
  efficient
 Following Parallel Query example highlights the potential efficiencies
  with the use of bloom filtering
 For an excellent article on Bloom Filters, see Christian Antognini’s
  article:
         – http://www.antognini.ch/papers/BloomFilters20080620.pdf

85   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
DWH Example – Parallel Execution
     SQL> select /*+ parallel */ * from dwh_bowie d, albums a, formats f where d.album_id = a.id and d.format_id=f.id and a.name in
     ('TAB$', 'COL$') and f.name = 'I_USER#';
     64000 rows selected.
     Elapsed: 00:00:03.34
     ------------------------------------------------------------------------------------------------------------------------------
     | Id | Operation                            | Name      | Rows | Bytes | Cost (%CPU)| Time      |    TQ |IN-OUT| PQ Distrib |
     ------------------------------------------------------------------------------------------------------------------------------
     |   0 | SELECT STATEMENT                    |           | 1600K|    177M| 27198 (1)| 00:00:55 |          |      |            |
     |   1 | PX COORDINATOR                      |           |       |       |            |          |        |      |            |
     |   2 |   PX SEND QC (RANDOM)               | :TQ10002 | 1600K|     177M| 27198 (1)| 00:00:55 | Q1,02 | P->S | QC (RAND) |
     |* 3 |     HASH JOIN                        |           | 1600K|    177M| 27198 (1)| 00:00:55 | Q1,02 | PCWP |               |
     |   4 |     PX RECEIVE                      |           |     2 |    48 |      5 (0)| 00:00:01 | Q1,02 | PCWP |              |
     |   5 |      PX SEND BROADCAST              | :TQ10001 |      2 |    48 |      5 (0)| 00:00:01 | Q1,01 | P->P | BROADCAST |
     |   6 |       MERGE JOIN CARTESIAN          |           |     2 |    48 |      5 (0)| 00:00:01 | Q1,01 | PCWP |              |
     |   7 |        BUFFER SORT                  |           |       |       |            |          | Q1,01 | PCWC |             |
     |   8 |         PX RECEIVE                  |           |     1 |    11 |      2 (0)| 00:00:01 | Q1,01 | PCWP |              |
     |   9 |          PX SEND BROADCAST          | :TQ10000 |      1 |    11 |      2 (0)| 00:00:01 | Q1,00 | P->P | BROADCAST |
     | 10 |            PX BLOCK ITERATOR         |           |     1 |    11 |      2 (0)| 00:00:01 | Q1,00 | PCWC |              |
     |* 11 |            TABLE ACCESS STORAGE FULL| FORMATS   |     1 |    11 |      2 (0)| 00:00:01 | Q1,00 | PCWP |              |
     | 12 |         BUFFER SORT                  |           |     2 |    26 |      3 (0)| 00:00:01 | Q1,01 | PCWP |              |
     | 13 |          PX BLOCK ITERATOR           |           |     2 |    26 |      2 (0)| 00:00:01 | Q1,01 | PCWC |              |
     |* 14 |          TABLE ACCESS STORAGE FULL | ALBUMS     |     2 |    26 |      2 (0)| 00:00:01 | Q1,01 | PCWP |              |
     | 15 |      PX BLOCK ITERATOR               |           |   640M|    54G| 27161 (1)| 00:00:55 | Q1,02 | PCWC |               |
     |* 16 |      TABLE ACCESS STORAGE FULL      | DWH_BOWIE |   640M|    54G| 27161 (1)| 00:00:55 | Q1,02 | PCWP |               |
     ------------------------------------------------------------------------------------------------------------------------------
     Predicate Information (identified by operation id):
     ---------------------------------------------------
        3 - access("D"."ALBUM_ID"="A"."ID" AND "D"."FORMAT_ID"="F"."ID")
       11 - storage("F"."NAME"='I_USER#')
            filter("F"."NAME"='I_USER#')
       14 - storage("A"."NAME"='COL$' OR "A"."NAME"='TAB$')
            filter("A"."NAME"='COL$' OR "A"."NAME"='TAB$')
       16 - storage(SYS_OP_BLOOM_FILTER(:BF0000,"D"."ALBUM_ID","D"."FORMAT_ID"))
            filter(SYS_OP_BLOOM_FILTER(:BF0000,"D"."ALBUM_ID","D"."FORMAT_ID"))
     NAME                                                                     MB
     ---------------------------------------------------------------- ----------
     cell physical IO bytes saved by storage index                    60251.3984
     cell physical IO interconnect bytes returned by smart scan       1161.76605



86    Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
DWH Example – Star Transformation
 If we now make relevant Bitmap Indexes visible again
       SQL> alter index dwh_bowie_album_id_i visible;
       Index altered.

       SQL> alter index dwh_bowie_format_i visible;
       Index altered.

       SQL> select * from dwh_bowie d, albums a, formats f where d.album_id = a.id and
       d.format_id=f.id and a.name in ('TAB$', 'COL$') and f.name = 'I_USER#';

       64000 rows selected.

       Elapsed: 00:00:00.34



In some scenarios, indexes still have a place in DWH environments as well. It all
depends …

  87   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
DWH Example – Star Transformation
              Execution Plan
              ---------------------------------------------------------------------------------------------------------
              | Id | Operation                           | Name                | Rows | Bytes| Cost (%CPU)| Time      |
              ---------------------------------------------------------------------------------------------------------
              |    0 | SELECT STATEMENT                  |                     |   198K|   28M|   319K (1)| 01:04:00 |
              |* 1 | HASH JOIN                           |                     |   198K|   28M|   319K (1)| 01:04:00 |
              |    2 |   MERGE JOIN CARTESIAN            |                     |     2 |    48|    36   (0)| 00:00:01 |
              |* 3 |      TABLE ACCESS STORAGE FULL      | FORMATS             |     1 |    11|    18   (0)| 00:00:01 |
              |    4 |    BUFFER SORT                    |                     |     2 |    26|    18   (0)| 00:00:01 |
              |* 5 |       TABLE ACCESS STORAGE FULL     | ALBUMS              |     2 |    26|    18   (0)| 00:00:01 |
              |    6 |   VIEW                            | VW_ST_4B85F3B9      | 1584K|   190M|   319K (1)| 01:03:59 |
              |    7 |    NESTED LOOPS                   |                     | 1584K|   172M|   319K (1)| 01:03:59 |
              |    8 |     BITMAP CONVERSION TO ROWIDS |                       | 1584K|    27M|   275   (2)| 00:00:04 |
              |    9 |      BITMAP AND                   |                     |       |      |            |          |
              | 10 |          BITMAP MERGE               |                     |       |      |            |          |
              | 11 |           BITMAP KEY ITERATION      |                     |       |      |            |          |
              |* 12 |           TABLE ACCESS STORAGE FULL| ALBUMS              |     2 |    26|    18   (0)| 00:00:01 |
              |* 13 |           BITMAP INDEX RANGE SCAN | DWH_BOWIE_ALBUM_ID_I |       |      |            |          |
              | 14 |          BITMAP MERGE               |                     |       |      |            |          |
              | 15 |           BITMAP KEY ITERATION      |                     |       |      |            |          |
              |* 16 |           TABLE ACCESS STORAGE FULL| FORMATS             |     1 |    11|    18   (0)| 00:00:01 |
              |* 17 |           BITMAP INDEX RANGE SCAN | DWH_BOWIE_FORMAT_I   |       |      |            |          |
              | 18 |       TABLE ACCESS BY USER ROWID    | DWH_BOWIE           |     1 |    96|   319K (1)| 01:03:56 |
              ---------------------------------------------------------------------------------------------------------
              Note
              -----
                 - star transformation used for this statement
              Statistics
              ----------------------------------------------------------
                         1 recursive calls
                         0 db block gets
                     2288 consistent gets
                         0 physical reads
                      476 redo size
                  2240022 bytes sent via SQL*Net to client
                      656 bytes received via SQL*Net from client
                       14 SQL*Net roundtrips to/from client
                         1 sorts (memory)
                         0 sorts (disk)
                    64000 rows processed




88   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Indexes – Skinny Tables
                    SQL> select blocks from dba_tables where table_name = 'DWH_BOWIE';
                        BLOCKS
                    ----------
                       8634533
                    SQL> select count(*) from dwh_bowie;
                      COUNT(*)
                    ----------
                     640000128
                    Elapsed: 00:00:40.31
                    Execution Plan
                    --------------------------------------------------------------------------------
                    | Id | Operation                    | Name      | Rows | Cost (%CPU)| Time     |
                    --------------------------------------------------------------------------------
                    |   0 | SELECT STATEMENT            |           |     1 | 2345K (1)| 07:49:12 |
                    |   1 | SORT AGGREGATE              |           |     1 |           |          |
                    |   2 |    TABLE ACCESS STORAGE FULL| DWH_BOWIE |   640M| 2345K (1)| 07:49:12 |
                    --------------------------------------------------------------------------------
                    Statistics
                    ----------------------------------------------------------
                              63 recursive calls
                               0 db block gets
                        8627017 consistent gets
                         8625479 physical reads
                               0 redo size
                             530 bytes sent via SQL*Net to client
                             524 bytes received via SQL*Net from client
                               2 SQL*Net roundtrips to/from client
                               6 sorts (memory)
                               0 sorts (disk)
                               1 rows processed
                    NAME                                                                     MB
                    ---------------------------------------------------------------- ----------
                    cell physical IO bytes saved by storage index                              0
                    cell physical IO interconnect bytes returned by smart scan       7644.35252



89   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Indexes – Skinny Tables
              SQL> create index dwh_bowie_album_id_i on dwh_bowie(album_id);
              Index created.
              SQL> select leaf_blocks from user_indexes where index_name = 'DWH_BOWIE_ALBUM_ID_I';
              LEAF_BLOCKS
              -----------
                  1250001
              SQL> select count(*) from dwh_bowie;
              Elapsed: 00:00:20.30
              Execution Plan
              ----------------------------------------------------------------------------------------------
              | Id | Operation                      | Name                 | Rows | Cost (%CPU)| Time      |
              ----------------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT              |                      |     1 |   342K (2)| 01:08:32 |
              |   1 | SORT AGGREGATE                |                      |     1 | |           |
              |   2 |   INDEX STORAGE FAST FULL SCAN| DWH_BOWIE_ALBUM_ID_I |   640M|   342K (2)| 01:08:32 |
              ----------------------------------------------------------------------------------------------
              Statistics
              ----------------------------------------------------------
                        1 recursive calls
                        0 db block gets
                  1253756 consistent gets
                  1252492 physical reads
                        0 redo size
                      530 bytes sent via SQL*Net to client
                      524 bytes received via SQL*Net from client
                        2 SQL*Net roundtrips to/from client
                        0 sorts (memory)
                        0 sorts (disk)
                        1 rows processed
              NAME                                                                     MB
              ---------------------------------------------------------------- ----------
              cell physical IO bytes saved by storage index                             0
              cell physical IO interconnect bytes returned by smart scan       3103.25166



90   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Bitmap Indexes – Really Skinny Tables
           SQL> create bitmap index dwh_bowie_album_id_i on dwh_bowie(album_id);
           Index created.
           SQL> select leaf_blocks from user_indexes where index_name = 'DWH_BOWIE_ALBUM_ID_I';
           LEAF_BLOCKS
           -----------
                 16086
           SQL> select count(*) from dwh_bowie;
           Elapsed: 00:00:00.22
           Execution Plan
           ------------------------------------------------------------------------------------------------------
           | Id | Operation                              | Name                 | Rows | Cost (%CPU)| Time      |
           ------------------------------------------------------------------------------------------------------
           |   0 | SELECT STATEMENT                      |                      |     1 | 14482   (1)| 00:02:54 |
           |   1 | SORT AGGREGATE                        |                      |     1 |            |          |
           |   2 |   BITMAP CONVERSION COUNT             |                      |   640M| 14482   (1)| 00:02:54 |
           |   3 |    BITMAP INDEX STORAGE FAST FULL SCAN| DWH_BOWIE_ALBUM_ID_I |       |            |          |
           ------------------------------------------------------------------------------------------------------
           Statistics
           ----------------------------------------------------------
                     0 recursive calls
                     0 db block gets
                 16143 consistent gets
                     0 physical reads
                     0 redo size
                   530 bytes sent via SQL*Net to client
                   524 bytes received via SQL*Net from client
                     2 SQL*Net roundtrips to/from client
                     0 sorts (memory)
                     0 sorts (disk)
                     1 rows processed
           NAME                                                                     MB
           ---------------------------------------------------------------- ----------
           cell physical IO bytes saved by storage index                             0
           cell physical IO interconnect bytes returned by smart scan                0



91   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Hybrid Columnar Compression (HCC)
SQL> create table tiny_dwh_bowie compress for query high as select * from dwh_bowie where 1=2;
Table created.
SQL> insert /*+ append */ into tiny_dwh_bowie select * from dwh_bowie;
640000128 rows created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'TINY_DWH_BOWIE', estimate_percent=>null,
method_opt=> 'FOR ALL COLUMNS SIZE 1');
PL/SQL procedure successfully completed.
SQL> create table tiny_dwh_bowie2 compress for archive high as select * from dwh_bowie where 1=2;
Table created.
SQL> insert /*+ append */ into tiny_dwh_bowie2 select * from tiny_dwh_bowie;
640000128 rows created.
SQL> commit;
Commit complete.
SQL> select table_name, blocks, round((blocks*8)/1024)                        MB, compress_for from user_tables where table_name like
'%DWH_BOWIE%';
TABLE_NAME                         BLOCKS         MB COMPRESS_FOR
------------------------------ ---------- ---------- ------------
DWH_BOWIE                         8634533      67457
TINY_DWH_BOWIE                     521645       4075 QUERY HIGH
TINY_DWH_BOWIE2                    403379       3151 ARCHIVE HIGH




  92   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
HCC and Smart Scans
          SQL> select * from dwh_bowie where album_id = 42;
          6400000 rows selected.
          Elapsed: 00:00:46.61
          Execution Plan
          ---------------------------------------------------------------------------------------
          | Id | Operation                  | Name      | Rows | Bytes | Cost (%CPU)| Time      |
          ---------------------------------------------------------------------------------------
          |   0 | SELECT STATEMENT          |           | 6400K|    561M| 2348K (1)| 07:49:38 |
          |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 6400K|      561M| 2348K (1)| 07:49:38 |
          ---------------------------------------------------------------------------------------
          SQL> select * from tiny_dwh_bowie where album_id = 42;
          6400000 rows selected.
          Elapsed: 00:00:33.54
          Execution Plan
          --------------------------------------------------------------------------------------------
          | Id | Operation                  | Name           | Rows | Bytes | Cost (%CPU)| Time      |
          --------------------------------------------------------------------------------------------
          |   0 | SELECT STATEMENT          |                | 6400K|    561M|   148K (5)| 00:29:38 |
          |* 1 | TABLE ACCESS STORAGE FULL| TINY_DWH_BOWIE | 6400K|      561M|   148K (5)| 00:29:38 |
          --------------------------------------------------------------------------------------------
          SQL> select * from tiny_dwh_bowie2 where album_id = 42;
          6400000 rows selected.
          Elapsed: 00:00:41.04
          Execution Plan
          ---------------------------------------------------------------------------------------------
          | Id | Operation                  | Name            | Rows | Bytes | Cost (%CPU)| Time      |
          ---------------------------------------------------------------------------------------------
          |   0 | SELECT STATEMENT          |                 | 6400K|    561M|   116K (6)| 00:23:13 |
          |* 1 | TABLE ACCESS STORAGE FULL| TINY_DWH_BOWIE2 | 6400K|      561M|   116K (6)| 00:23:13 |
          ---------------------------------------------------------------------------------------------



93   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
HCC and Indexes
If we create indexes in all three tables …
SQL> create index dwh_bowie_album_i on dwh_bowie(album_id);
Index created.
SQL> create index tiny_bowie_album_i on tiny_dwh_bowie(album_id);
Index created.
SQL> create index tiny_bowie2_album_i on tiny_dwh_bowie2(album_id);
Index created.
SQL> select index_name, leaf_blocks, clustering_factor from user_indexes where index_name
like '%BOWIE%ALBUM%';
INDEX_NAME                     LEAF_BLOCKS CLUSTERING_FACTOR
------------------------------ ----------- -----------------
DWH_BOWIE_ALBUM_I                  1250001           8876879
TINY_BOWIE_ALBUM_I                 1250001            224887
TINY_BOWIE2_ALBUM_I                1250001             84549


All are the same size but have vastly differing Clustering Factors

  94   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
HCC and Indexes
If we create indexes in all three tables and re-run with fully cached data …
              SQL> select * from dwh_bowie where album_id = 42;
              6400000 rows selected.
              Elapsed: 00:00:16.96
              Execution Plan
              -------------------------------------------------------------------------------------------------
              | Id | Operation                    | Name              | Rows | Bytes | Cost (%CPU)| Time      |
              -------------------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT            |                   | 6400K|    561M|   101K (1)| 00:20:18 |
              |   1 | TABLE ACCESS BY INDEX ROWID| DWH_BOWIE          | 6400K|    561M|   101K (1)| 00:20:18 |
              |* 2 |    INDEX RANGE SCAN          | DWH_BOWIE_ALBUM_I | 6400K|        | 12569 (1)| 00:02:31 |
              -------------------------------------------------------------------------------------------------
              SQL> select * from tiny_dwh_bowie where album_id = 42;
              6400000 rows selected.
              Elapsed: 00:00:21.16
              Execution Plan
              --------------------------------------------------------------------------------------------------
              | Id | Operation                    | Name               | Rows | Bytes | Cost(%CPU)| Time       |
              --------------------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT            |                    | 6400K|    561M| 14900   (1)| 00:02:59 |
              |   1 | TABLE ACCESS BY INDEX ROWID| TINY_DWH_BOWIE      | 6400K|    561M| 14900   (1)| 00:02:59 |
              |* 2 |    INDEX RANGE SCAN          | TINY_BOWIE_ALBUM_I | 6400K|        | 12569   (1)| 00:02:31 |
              --------------------------------------------------------------------------------------------------
              SQL> select * from tiny_dwh_bowie2 where album_id = 42;
              6400000 rows selected.
              Elapsed: 00:01:08.38
              Execution Plan
              ---------------------------------------------------------------------------------------------------
              | Id | Operation                    | Name                | Rows | Bytes | Cost (%CPU)| Time      |
              ---------------------------------------------------------------------------------------------------
              |   0 | SELECT STATEMENT            |                     | 6400K|    561M| 13497   (2)| 00:02:42 |
              |   1 | TABLE ACCESS BY INDEX ROWID| TINY_DWH_BOWIE2      | 6400K|    561M| 13497   (2)| 00:02:42 |
              |* 2 |    INDEX RANGE SCAN          | TINY_BOWIE2_ALBUM_I | 6400K|        | 12569   (1)| 00:02:31 |
              ---------------------------------------------------------------------------------------------------



 95   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
HCC and Indexes
 Index CBO costs can decrease due to decrease in CF
 Actual costs increase however when accessing HCC tables as
  the required data needs to be reconstructed/decompressed
 Especially so for COMPRESS FOR ARCHIVE
 This extra work burns significant CPU
 The CBO however does not consider these additional CPU
  costs in its calculations
 Indexes therefore more likely to be inappropriately selected by
  CBO with HCC
 96   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Exadata Smart Scans
Operations that don’t benefit from Smart Scans include:
 Index range scans.
 Scans of IOTs or Clustered Tables.
 Access to a compressed index.
 Access to a reverse key index.




 97   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
Index Organized Tables: No Smart Scan
     SQL> create table big_bowie_iot (id number constraint big_bowie_iot_pk primary key, album_id number, artist_id
     number, format_id number, release_date date, total_sales number, description varchar2(100)) organization index;
     Table created.
     SQL> insert into big_bowie_iot select * from big_bowie;
     10000000 rows created.
     SQL> commit;
     Commit complete.
     SQL> select * from big_bowie_iot where total_sales = 42;
     23 rows selected.
     Elapsed: 00:00:16.72
     Execution Plan
     -----------------------------------------------------------------------------------------
     | Id | Operation             | Name             | Rows | Bytes | Cost (%CPU)| Time      |
     -----------------------------------------------------------------------------------------
     |   0 | SELECT STATEMENT     |                  |    20 | 1840 | 36698    (1)| 00:07:21 |
     |* 1 | INDEX FAST FULL SCAN| BIG_BOWIE_IOT_PK |      20 | 1840 | 36698    (1)| 00:07:21 |
     -----------------------------------------------------------------------------------------
     Predicate Information (identified by operation id):
     ---------------------------------------------------
        1 - filter("TOTAL_SALES"=42)
     Statistics
     ----------------------------------------------------------
               0 recursive calls
               0 db block gets
          135672 consistent gets
          134280 physical reads
               0 redo size
            1972 bytes sent via SQL*Net to client
             535 bytes received via SQL*Net from client
               3 SQL*Net roundtrips to/from client
               0 sorts (memory)
               0 sorts (disk)
              23 rows processed



98   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
General Conclusions
 With Exadata, things run faster, FTS especially so
 Some indexes can become redundant as a result
 CBO not fully aware of reduced FTS costs
 CBO not fully aware of increased index costs associated with HCC
 With indexes in place, faster smart scans operations may be dismissed
 However, using an index should generally be no worse than in Non-
  Exadata environments (although HCC an exception)
 Database indexes still of value in numerous scenarios, especially in
  OLTP environments
 Need to understand benefits/advantages of smart scans and storage
  indexes and where there may have shortfalls
99   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
General Recommendations
 Easy to create an index, much harder and riskier to subsequently drop them
 When moving to Exadata, take the opportunity to review current indexes,
  especially in DWH environments which are often “over indexed”
 Use information in v$sql_plan, dba_hist_sql_plan, AWR reports to
  determine potentially problematic indexes
 But do not blindly drop indexes in the hope Exadata will just cope
  regardless …
 Use Invisible Indexes to test impact of potentially dropping an index
 Real Application Testing (RAT) of enormous use when migrating to Exadata



 100   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
richardfoote.wordpress.com
      An Oracle Indexing blog might still have some value yet !!!




101    Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
102   Copyright © 2012, Oracle and/or its affiliates. All rights reserved.

More Related Content

What's hot (20)

PPT
Ash masters : advanced ash analytics on Oracle
Kyle Hailey
 
PDF
Exadata Performance Optimization
Enkitec
 
PPTX
Understanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Guatemala User Group
 
PDF
Analyzing and Interpreting AWR
pasalapudi
 
PPTX
AWR and ASH Deep Dive
Kellyn Pot'Vin-Gorman
 
PDF
In Memory Database In Action by Tanel Poder and Kerry Osborne
Enkitec
 
PDF
Same plan different performance
Mauro Pagano
 
PDF
Redo internals ppt
Riyaj Shamsudeen
 
PPTX
Christo kutrovsky oracle, memory & linux
Kyle Hailey
 
PDF
Oracle Performance Tuning Fundamentals
Enkitec
 
PDF
Oracle Database SQL Tuning Concept
Chien Chung Shen
 
PPTX
All of the Performance Tuning Features in Oracle SQL Developer
Jeff Smith
 
PPSX
Oracle Performance Tuning Fundamentals
Carlos Sierra
 
PPT
Your tuning arsenal: AWR, ADDM, ASH, Metrics and Advisors
John Kanagaraj
 
PDF
Advanced RAC troubleshooting: Network
Riyaj Shamsudeen
 
PDF
Understanding oracle rac internals part 2 - slides
Mohamed Farouk
 
PDF
Oracle db performance tuning
Simon Huang
 
PPT
Oracle GoldenGate
oracleonthebrain
 
PDF
Chasing the optimizer
Mauro Pagano
 
PDF
Tanel Poder - Performance stories from Exadata Migrations
Tanel Poder
 
Ash masters : advanced ash analytics on Oracle
Kyle Hailey
 
Exadata Performance Optimization
Enkitec
 
Understanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Guatemala User Group
 
Analyzing and Interpreting AWR
pasalapudi
 
AWR and ASH Deep Dive
Kellyn Pot'Vin-Gorman
 
In Memory Database In Action by Tanel Poder and Kerry Osborne
Enkitec
 
Same plan different performance
Mauro Pagano
 
Redo internals ppt
Riyaj Shamsudeen
 
Christo kutrovsky oracle, memory & linux
Kyle Hailey
 
Oracle Performance Tuning Fundamentals
Enkitec
 
Oracle Database SQL Tuning Concept
Chien Chung Shen
 
All of the Performance Tuning Features in Oracle SQL Developer
Jeff Smith
 
Oracle Performance Tuning Fundamentals
Carlos Sierra
 
Your tuning arsenal: AWR, ADDM, ASH, Metrics and Advisors
John Kanagaraj
 
Advanced RAC troubleshooting: Network
Riyaj Shamsudeen
 
Understanding oracle rac internals part 2 - slides
Mohamed Farouk
 
Oracle db performance tuning
Simon Huang
 
Oracle GoldenGate
oracleonthebrain
 
Chasing the optimizer
Mauro Pagano
 
Tanel Poder - Performance stories from Exadata Migrations
Tanel Poder
 

Similar to Indexing in Exadata (20)

PDF
[INSIGHT OUT 2011] B26 optimising a two table join(jonathan lewis)
Insight Technology, Inc.
 
PDF
Indexing Strategies for Oracle Databases - Beyond the Create Index Statement
Sean Scott
 
PDF
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
InSync2011
 
PDF
Presentation indexing new features oracle 11g release 1 and release 2
xKinAnx
 
PDF
Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf
InSync2011
 
PDF
Bank Data Frank Peterson DB2 10-Early_Experiences_pdf
Surekha Parekh
 
PDF
DB2 9.7 Overview
Fuangwith Sopharath
 
PDF
Indexes overview
aioughydchapter
 
PPTX
Top 10 tips for Oracle performance
Guy Harrison
 
PDF
Percona Live 2012PPT: MySQL Query optimization
mysqlops
 
PPSX
Cost Based Oracle
Santosh Kangane
 
PPT
Compression ow2009 r2
carldudley
 
PDF
Exadata 11-2-overview-v2 11
Oracle BH
 
PDF
Inno Db Performance And Usability Patches
MySQLConference
 
PDF
Akiban Technologies: Renormalize
Ariel Weil
 
PDF
Solving performance problems in MySQL without denormalization
dmcfarlane
 
PDF
Akiban Technologies: Renormalize
Ariel Weil
 
PDF
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
InSync2011
 
PPTX
Indexing the MySQL Index: Key to performance tuning
OSSCube
 
PDF
MySQL optimisation Percona LeMug.fr
cyruss666
 
[INSIGHT OUT 2011] B26 optimising a two table join(jonathan lewis)
Insight Technology, Inc.
 
Indexing Strategies for Oracle Databases - Beyond the Create Index Statement
Sean Scott
 
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
InSync2011
 
Presentation indexing new features oracle 11g release 1 and release 2
xKinAnx
 
Database & Technology 1 _ Tom Kyte _ SQL Techniques.pdf
InSync2011
 
Bank Data Frank Peterson DB2 10-Early_Experiences_pdf
Surekha Parekh
 
DB2 9.7 Overview
Fuangwith Sopharath
 
Indexes overview
aioughydchapter
 
Top 10 tips for Oracle performance
Guy Harrison
 
Percona Live 2012PPT: MySQL Query optimization
mysqlops
 
Cost Based Oracle
Santosh Kangane
 
Compression ow2009 r2
carldudley
 
Exadata 11-2-overview-v2 11
Oracle BH
 
Inno Db Performance And Usability Patches
MySQLConference
 
Akiban Technologies: Renormalize
Ariel Weil
 
Solving performance problems in MySQL without denormalization
dmcfarlane
 
Akiban Technologies: Renormalize
Ariel Weil
 
Database & Technology 1 _ Clancy Bufton _ Flashback Query - oracle total reca...
InSync2011
 
Indexing the MySQL Index: Key to performance tuning
OSSCube
 
MySQL optimisation Percona LeMug.fr
cyruss666
 
Ad

More from Enkitec (20)

PDF
Using Angular JS in APEX
Enkitec
 
PDF
Controlling execution plans 2014
Enkitec
 
PDF
Engineered Systems: Environment-as-a-Service Demonstration
Enkitec
 
PDF
Think Exa!
Enkitec
 
PDF
In Search of Plan Stability - Part 1
Enkitec
 
PDF
Mini Session - Using GDB for Profiling
Enkitec
 
PDF
Profiling Oracle with GDB
Enkitec
 
PDF
Oracle Performance Tools of the Trade
Enkitec
 
PDF
SQL Tuning Tools of the Trade
Enkitec
 
PDF
Using SQL Plan Management (SPM) to Balance Plan Flexibility and Plan Stability
Enkitec
 
PDF
Oracle GoldenGate Architecture Performance
Enkitec
 
PDF
OGG Architecture Performance
Enkitec
 
PDF
APEX Security Primer
Enkitec
 
PDF
How Many Ways Can I Manage Oracle GoldenGate?
Enkitec
 
PDF
Understanding how is that adaptive cursor sharing (acs) produces multiple opt...
Enkitec
 
PDF
Sql tuning made easier with sqltxplain (sqlt)
Enkitec
 
PDF
Profiling the logwriter and database writer
Enkitec
 
PDF
Fatkulin hotsos 2014
Enkitec
 
PDF
Combining ACS Flexibility with SPM Stability
Enkitec
 
PDF
Why You May Not Need Offloading
Enkitec
 
Using Angular JS in APEX
Enkitec
 
Controlling execution plans 2014
Enkitec
 
Engineered Systems: Environment-as-a-Service Demonstration
Enkitec
 
Think Exa!
Enkitec
 
In Search of Plan Stability - Part 1
Enkitec
 
Mini Session - Using GDB for Profiling
Enkitec
 
Profiling Oracle with GDB
Enkitec
 
Oracle Performance Tools of the Trade
Enkitec
 
SQL Tuning Tools of the Trade
Enkitec
 
Using SQL Plan Management (SPM) to Balance Plan Flexibility and Plan Stability
Enkitec
 
Oracle GoldenGate Architecture Performance
Enkitec
 
OGG Architecture Performance
Enkitec
 
APEX Security Primer
Enkitec
 
How Many Ways Can I Manage Oracle GoldenGate?
Enkitec
 
Understanding how is that adaptive cursor sharing (acs) produces multiple opt...
Enkitec
 
Sql tuning made easier with sqltxplain (sqlt)
Enkitec
 
Profiling the logwriter and database writer
Enkitec
 
Fatkulin hotsos 2014
Enkitec
 
Combining ACS Flexibility with SPM Stability
Enkitec
 
Why You May Not Need Offloading
Enkitec
 
Ad

Recently uploaded (20)

PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PPTX
✨Unleashing Collaboration: Salesforce Channels & Community Power in Patna!✨
SanjeetMishra29
 
PDF
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
PDF
Python basic programing language for automation
DanialHabibi2
 
PDF
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
PDF
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
PDF
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
PPTX
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
PDF
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
SFWelly Summer 25 Release Highlights July 2025
Anna Loughnan Colquhoun
 
PPTX
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
PDF
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
✨Unleashing Collaboration: Salesforce Channels & Community Power in Patna!✨
SanjeetMishra29
 
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
Python basic programing language for automation
DanialHabibi2
 
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
SFWelly Summer 25 Release Highlights July 2025
Anna Loughnan Colquhoun
 
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 

Indexing in Exadata

  • 1. Indexing In Exadata Richard Foote Oracle Corporation
  • 2. Richard Foote • Working in IT for 25+ years (scary stuff) • Working with Oracle Database for 15+ years • Spent 19 years employed in Australian Federal Government in various IT roles, last 9 years as a senior DBA with the Australian Federal Police • Responsible for many large scale, mission critical, “life-dependant” classified Oracle systems • Previously a DBA Instructor with Oracle Corporation (1996 and 2002) • Since Nov 2011, re-joined Oracle Corporation as a Technical Solutions Consultant based in sunny Canberra • Spent much of this time playing with Exadata (one of the reasons I rejoined)  • Oracle OakTable Member since 2002 and Oracle ACE Director since 2008 (now Oracle Employee Ace) • Richard Foote’s Oracle Blog: http://richardfoote.wordpress.com/ • Spend as much free time as possible listening to the music of David Bowie !! 2 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 3. Exadata Innovations Exadata Storage Server Software  Intelligent storage • Hybrid Columnar Compression – Smart Scan query offload – 10x compression for warehouses – Scale-out storage – 15x compression for archives Data + + + remains compressed Uncompressed for scans • Smart Flash Cache and in Flash – Accelerates random I/O up to 30x primary backup – Doubles data scan rate Benefits test Multiply standby dev’t Compressed 3 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 4. Things can run so much faster in Exadata … With Non-Exadata … SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200; 266176 rows selected. Elapsed: 00:04:43.38 ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 266K| 23M| 2348K (1)| 07:49:45 | |* 1 | TABLE ACCESS FULL| DWH_BOWIE | 266K| 23M| 2348K (1)| 07:49:45 | ------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 8644512 consistent gets 8625479 physical reads 0 redo size 12279634 bytes sent via SQL*Net to client 195719 bytes received via SQL*Net from client 17747 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 266176 rows processed 4 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 5. Things can run so much faster in Exadata … With Exadata, what previously took minutes can take seconds … SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200; 266176 rows selected. Elapsed: 00:00:03.97 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 266K| 23M| 2348K (1)| 07:49:45 | |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 266K| 23M| 2348K (1)| 07:49:45 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42) filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 8626963 consistent gets 8625479 physical reads 0 redo size 12279634 bytes sent via SQL*Net to client 195719 bytes received via SQL*Net from client 17747 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 266176 rows processed 5 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 6. Indexing In Exadata … Are indexes needed anymore ??? 6 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 7. Worse - Indexes can get in the way … SQL> create bitmap index dwh_album_artist_i on dwh_bowie(artist_id, album_id); Index created. SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200; 266176 rows selected. Elapsed: 00:00:23.11 --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 266K| 23M| 78267 (1)| 00:15:40 | | 1 | TABLE ACCESS BY INDEX ROWID | DWH_BOWIE | 266K| 23M| 78267 (1)| 00:15:40 | | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | |* 3 | BITMAP INDEX RANGE SCAN | DWH_ALBUM_ARTIST_I | | | | | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("ARTIST_ID">=42 AND "ALBUM_ID"=42 AND "ARTIST_ID"<=4200) filter("ARTIST_ID">=42 AND "ARTIST_ID"<=4200 AND "ALBUM_ID"=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 291129 consistent gets 25337 physical reads 29728 redo size 28836174 bytes sent via SQL*Net to client 195719 bytes received via SQL*Net from client 17747 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 266176 rows processed 7 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 8. Indexing In Exadata … Are indexes evil? Should they just be dropped? Mr. Index, or Dr. Evil !! 8 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 9. What to do? Important Decision • Many suggest simply drop indexes once you move to Exadata • Indexes take up much storage (important consideration, especially with ¼ Exadata racks where storage is more limited) • A redundant index wastes space and resources to maintain • Indexes critical to performance (or they certainly used to be) • But can “get in the way” in Exadata • Once dropped, tricky to keep track of what indexes previously existed • As usual, the decision to drop or keep indexes not a straightforward one … 9 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 10. Let’s Go Back To The Basics Cost of using an Index: Basic Cost = blevel + ceil(effective index selectivity x leaf_blocks) + ceil(effective table selectivity x clustering_factor) + a bit of CPU … In Exadata, this is basically the same for uncompressed tables. With EHCC tables, there’s some additional CPU costs required to decompress rows. Therefore actual cost of using an Index can increase in Exadata 10 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 11. Let’s Go Back To The Basics Simplistically, cost of Full Table Scan: Cost = (((No. of table blocks / effective multi block read count) x multi block read time) + a bit of CPU) / single block read time The costing is still calculated the same in Exadata, however this may no longer represent the true costs… 11 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 12. Exadata Intelligent Storage Grid  Exadata cells implement smart scans to greatly reduce the data that needs to be processed by database – Only return relevant rows and columns to database – Offload predicate evaluation  Data reduction can be very large – Column and row reduction often decrease data to be returned to the database by 10x 12 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 13. Exadata Smart Scans  Full Scans (Tables/Indexes/MVs/Partitions)  Direct Path Reads (By-Passing Buffer Cache)  Smart Scan Optimizations, some of which include: – Column Projection – Predicate Filtering – Simple Joins – Function Off-Loading – Virtual Column Evaluation – HCC Decompression – Decryption  See MOS Notes 793845.1 and 50415.1 for more info on Direct Path Reads 13 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 14. Exadata Smart Scans - Benefits  CPU utilization on database nodes improves due to offload  Less data shipped to database nodes (generally …)  Query fully encrypted database by moving decryption from database to storage cell hardware  Full Table Scan performance can dramatically improve  Costs associated with Full Table Scan operation can therefore significantly decrease, especially with Storage Indexes kicking in  With index costs perhaps increasing and FTS costs perhaps decreasing, indexes in Exadata become less viable …  Not looking good for indexes !!! 14 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 15. Non-Exadata Chart: Indexes vs. FTS Cost Rows Returned Full Table Scan Index Scan 15 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 16. Non-Exadata Chart: Indexes vs. FTS (DWH) xx x x xx xx x xx xx xx xx Cost x x xx x x x x x x x xx Rows Returned Full Table Scan x Queries using indexes Index Scan 16 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 17. Non-Exadata Chart: Indexes vs. FTS (OLTP) x x Cost x x x x x xx xx x x x x xx x Rows Returned Full Table Scan Index Scan x Queries using indexes 17 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 18. Exadata Chart: Indexes vs. FTS Cost Rows Returned Full Table Scan Index Scan (on HCC tables) 18 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 19. Exadata Chart: Indexes vs. FTS (DWH) x xx x x x xx xxxx x x xx x x Cost x xx x x x x x x x xx Rows Returned Full Table Scan Index Scan x Queries using indexes 19 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 20. Exadata Chart: Indexes vs. FTS (OLTP) x x Cost x x x x x xxx xx x xx x x xx Rows Returned Full Table Scan Index Scan x Queries using indexes 20 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 21. Exadata Indexes vs. FTS (CBO Costs) x xx xx xx x x xx xx xx xx Cost x x xx x x x x x x x xx Rows Returned Full Table Scan Index Scan x Queries using indexes CBO Costs 21 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 22. Exadata Indexes vs. FTS (CBO Costs) x x x xx x x x xxxx x x x x x Cost x x xxx x x x x x x x xx Full Table Scan Rows Returned Index Scan x Queries using indexes FTS CBO Cost 22 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 23. Without Exadata Smart Scans Going back to the first example … SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200; 266176 rows selected. Elapsed: 00:04:43.38 ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 266K| 23M| 2348K (1)| 07:49:45 | |* 1 | TABLE ACCESS FULL| DWH_BOWIE | 266K| 23M| 2348K (1)| 07:49:45 | ------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 8644512 consistent gets 8625479 physical reads 0 redo size 12279634 bytes sent via SQL*Net to client 195719 bytes received via SQL*Net from client 17747 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 266176 rows processed 23 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 24. Smart Scan Example SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200; 266176 rows selected. Elapsed: 00:00:03.97 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 266K| 23M| 2348K (1)| 07:49:45 | |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 266K| 23M| 2348K (1)| 07:49:45 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42) filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 8626963 consistent gets 8625479 physical reads 0 redo size 12279634 bytes sent via SQL*Net to client 195719 bytes received via SQL*Net from client 17747 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 266176 rows processed 24 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 25. Smart Scan – How can you tell ? SQL> select sql_text, io_cell_offload_eligible_bytes, io_interconnect_bytes, io_cell_uncompressed_bytes, io_cell_offload_returned_bytes from v$sql where sql_id = 'admdhphbh1a1c'; SQL_TEXT -------------------------------------------------------------------------------- IO_CELL_OFFLOAD_ELIGIBLE_BYTES IO_INTERCONNECT_BYTES IO_CELL_UNCOMPRESSED_BYTES ------------------------------ --------------------- -------------------------- IO_CELL_OFFLOAD_RETURNED_BYTES ------------------------------ select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200 1.4132E+11 55217792 1.6718E+10 55217792 SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 59414.9453 cell physical IO interconnect bytes returned by smart scan 26.329895 25 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 26. Non-Smart Scan – CBO Costs The Same SQL> alter session set cell_offload_processing=false; Session altered. SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200; 266176 rows selected. Elapsed: 00:03:03.38 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 266K| 23M| 2348K (1)| 07:49:45 | |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 266K| 23M| 2348K (1)| 07:49:45 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("ALBUM_ID"=42 AND "ARTIST_ID"<=4200 AND "ARTIST_ID">=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 8644512 consistent gets 8625479 physical reads 0 redo size 12279634 bytes sent via SQL*Net to client 195719 bytes received via SQL*Net from client 17747 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 266176 rows processed CBO is not aware of smart scan benefits and FTS costs remain the same … 26 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 27. Less Efficient Index Chosen By CBO SQL> select * from dwh_bowie where album_id = 42 and artist_id between 42 and 4200; 266176 rows selected. Elapsed: 00:00:23.11 --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 266K| 23M| 78267 (1)| 00:15:40 | | 1 | TABLE ACCESS BY INDEX ROWID | DWH_BOWIE | 266K| 23M| 78267 (1)| 00:15:40 | | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | |* 3 | BITMAP INDEX RANGE SCAN | DWH_ALBUM_ARTIST_I | | | | | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("ARTIST_ID">=42 AND "ALBUM_ID"=42 AND "ARTIST_ID"<=4200) filter("ARTIST_ID">=42 AND "ARTIST_ID"<=4200 AND "ALBUM_ID"=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 291129 consistent gets 25337 physical reads 29728 redo size 28836174 bytes sent via SQL*Net to client 195719 bytes received via SQL*Net from client 17747 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 266176 rows processed Therefore existing indexes although maybe slower, appear much cheaper… 27 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 28. CBO and Smart Scans  The decision to go for Direct Reads and use a Smart Scan is not made by the CBO  The CBO is not aware of potential efficiencies provided by Smart Scans and costs Full Scans similar to Non-Exadata  Bug 10248538: OPTIMIZER COST MODEL NOT EXADATA-AWARE  Therefore, Full Scans are generally over-costed in Exadata, favoring Index Scan related execution paths  Simply dropping all indexes however is not the answer (to be discussed …)  Consider setting MBRC system stat to 128, assuming 8K block size to compensate (1MB default storage region size in storage cell)  Consider v$sql_plan, dba_hist_sql_plan searching for index plans with high cardinality values  Storage Indexes can make cost differentials even worse … 28 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 29. Storage Index – Basic Example Table Index • Exadata Storage Indexes maintain summary information about table data in memory A B C D – Store MIN and MAX values of columns 1 – Typically index entry for every MB of disk 3 Min B = 1 • Eliminates disk I/Os if MIN and MAX can never Max B = 5 match “where” clause of a query 5 5 • Completely automatic and transparent 8 Min B = 3 • Example: Select count(*) from table where B = 1; Max B =8 3 • FTS no longer really a FTS … 29 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 30. Storage Indexes – Demo Setup SQL> create table big_bowie (id number not null, album_id number not null, artist_id number not null, format_id number, release_date date, total_sales number, description varchar2(100)); Table created. SQL> create sequence bowie_seq order; Sequence created. SQL> create or replace procedure pop_big_bowie as 2 begin 3 for v_album_id in 1..100 loop 4 for v_artist_id in 1..100000 loop 5 insert into big_bowie values (bowie_seq.nextval, v_album_id, v_artist_id, ceil(dbms_random.value(0,5)) * 2, 6 trunc(sysdate-ceil(dbms_random.value(0,10000))), ceil(dbms_random.value(0,500000)), 'THE RISE AND FALL OF ZIGGY STARDUST AND THE SPIDERS FROM MARS'); 7 end loop; 8 commit; 9 end loop; 10 commit; 11 end; 12 / Procedure created. SQL> exec pop_big_bowie PL/SQL procedure successfully completed. 30 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 31. Storage Indexes – Demo Setup SQL> update big_bowie set format_id = 3 where mod(id,10000)=0; 1000 rows updated. SQL> commit; Commit complete. SQL> update big_bowie set format_id = 5 where id between 424242 and 425241; 1000 rows updated. SQL> commit; Commit complete. SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'BIG_BOWIE‘, method_opt=>'FOR ALL COLUMNS SIZE 1'); PL/SQL procedure successfully completed. SQL> select blocks from dba_tables where table_name = 'BIG_BOWIE'; BLOCKS ---------- 134809 This equates to approx. 1054 MB (a “typical” OLTP table) The DWH_BOWIE table is simply 64 times the BIG_BOWIE table 31 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 32. Storage Indexes – “Clustering Factor” ALBUM_ID column data is well clustered … SQL> select * from big_bowie where album_id = 42; 100000 rows selected. Elapsed: 00:00:00.27 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100K| 8984K| 36663 (1)| 00:07:20 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 100K| 8984K| 36663 (1)| 00:07:20 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ALBUM_ID"=42) filter("ALBUM_ID"=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 134834 consistent gets 134809 physical reads 0 redo size 4345496 bytes sent via SQL*Net to client 73850 bytes received via SQL*Net from client 6668 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 100000 rows processed 32 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 33. Storage Indexes – “Clustering Factor” SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 1042.24219 cell physical IO interconnect bytes returned by smart scan 9.56161499 The Storage Index has managed to avoid having to read approx. 99% of the table. Having data well clustered can result in Partition-Pruning like efficiencies when using an associated Storage Index … 33 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 34. Storage Indexes – “Clustering Factor” Note: Conventional database indexes love well clustered data as well … SQL> select * from big_bowie where album_id = 42; 100000 rows selected. Elapsed: 00:00:01.07 Execution Plan ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100K| 8984K| 1550 (1)| 00:00:19 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 100K| 8984K| 1550 (1)| 00:00:19 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_ALBUM_ID_I | 100K| | 199 (1)| 00:00:03 | ---------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ALBUM_ID"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1590 consistent gets 1550 physical reads 0 redo size 9689267 bytes sent via SQL*Net to client 733 bytes received via SQL*Net from client 21 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 100000 rows processed But is taking twice as long as FTS, despite “reported” physical reads much reduced… 34 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 35. Storage Indexes – “Clustering Factor” Even when all the data is cached … SQL> select * from big_bowie where album_id = 42; 100000 rows selected. Elapsed: 00:00:00.27 Execution Plan ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100K| 8984K| 1550 (1)| 00:00:19 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 100K| 8984K| 1550 (1)| 00:00:19 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_ALBUM_ID_I | 100K| | 199 (1)| 00:00:03 | ---------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ALBUM_ID"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1590 consistent gets 0 physical reads 0 redo size 9689267 bytes sent via SQL*Net to client 733 bytes received via SQL*Net from client 21 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 100000 rows processed Index is no more efficient than FTS, even though the index is extremely efficient … 35 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 36. Storage Indexes – “Clustering Factor” The TOTAL_SALES column however is not well clustered … SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142; 2009 rows selected. Elapsed: 00:00:01.25 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2040 | 26520 | 36700 (1)| 00:07:21 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 2040 | 26520 | 36700 (1)| 00:07:21 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("TOTAL_SALES"<=142 AND "TOTAL_SALES">=42) filter("TOTAL_SALES"<=142 AND "TOTAL_SALES">=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 134834 consistent gets 134809 physical reads 0 redo size 47506 bytes sent via SQL*Net to client 1987 bytes received via SQL*Net from client 135 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2009 rows processed 36 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 37. Storage Indexes – “Clustering Factor” SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 72.65625 cell physical IO interconnect bytes returned by smart scan .383415222 The Storage Index has only managed to avoid having to read approx. 7% of the table. The clustering of the data can make a huge impact to the effectiveness of Storage Indexes. Even though this query is only reading a fraction of the data as the previous query, it’s taking twice as long. The smart scan though is only returning a small fraction of the overall data back to the database. 37 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 38. Storage Indexes – “Clustering Factor” Note: Conventional indexes also hate poorly clustered tables … SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142; 2009 rows selected. Elapsed: 00:00:01.45 Execution Plan ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2040 | 26520 | 2048 (1)| 00:00:25 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 2040 | 26520 | 2048 (1)| 00:00:25 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_TOTAL_SALES_I | 2040 | | 7 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("TOTAL_SALES">=42 AND "TOTAL_SALES"<=142) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 2150 consistent gets 2005 physical reads 0 redo size 43311 bytes sent via SQL*Net to client 1987 bytes received via SQL*Net from client 135 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2009 rows processed This index is taking longer than the equivalent Exadata FTS … 38 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 39. Storage Indexes – “Clustering Factor” But on subsequent re-runs, when most of the data has been cached … SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142; 2009 rows selected. Elapsed: 00:00:00.02 Execution Plan ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes |Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 2040 | 26520 | 2048 (1)| 00:00:25 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 2040 | 26520 | 2048 (1)| 00:00:25 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_TOTAL_SALES_I | 2040 | | 7 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("TOTAL_SALES">=42 AND "TOTAL_SALES"<=142) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 2150 consistent gets 0 physical reads 0 redo size 43308 bytes sent via SQL*Net to client 1987 bytes received via SQL*Net from client 135 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2009 rows processed The index is now significantly faster than the FTS which performs consistently … 39 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 40. Database vs. Storage Indexes Have much in common: • Both can eliminate reading unnecessary data within a table • Efficiencies of both are directly impacted by the clustering of the data within the table • Both may need a period of “warming” up before optimal use • Both can combine multiple indexes to further increase efficiencies 40 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 41. Storage Indexes – Warm up On the first execution of this query since table creation: SQL> select artist_id, total_sales from big_bowie where album_id = 42; 100000 rows selected. Elapsed: 00:00:00.89 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100K| 1269K| 36663 (1)| 00:07:20 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 100K| 1269K| 36663 (1)| 00:07:20 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ALBUM_ID"=42) filter("ALBUM_ID"=42) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 114.601563 cell physical IO interconnect bytes returned by smart scan 1.77637482 41 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 42. Storage Indexes – Warm up Subsequent executions, many more IO bytes saved by “warm” storage index SQL> select artist_id, total_sales from big_bowie where album_id = 42; 100000 rows selected. Elapsed: 00:00:00.27 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100K| 1269K| 36663 (1)| 00:07:20 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 100K| 1269K| 36663 (1)| 00:07:20 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ALBUM_ID"=42) filter("ALBUM_ID"=42) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 1156.84375 cell physical IO interconnect bytes returned by smart scan 3.41764832 42 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 43. Database Indexes – Cache Sensitive SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142; 2009 rows selected. Elapsed: 00:00:01.45 Execution Plan ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2040 | 26520 | 2048 (1)| 00:00:25 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 2040 | 26520 | 2048 (1)| 00:00:25 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_TOTAL_SALES_I | 2040 | | 7 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("TOTAL_SALES">=42 AND "TOTAL_SALES"<=142) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 2150 consistent gets 2005 physical reads 0 redo size 43311 bytes sent via SQL*Net to client 1987 bytes received via SQL*Net from client 135 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2009 rows processed 43 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 44. Database Indexes – Cache Sensitive But on subsequent re-runs, when most of the data has been cached … SQL> select album_id, artist_id from big_bowie where total_sales between 42 and 142; 2009 rows selected. Elapsed: 00:00:00.02 Execution Plan ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2040 | 26520 | 2048 (1)| 00:00:25 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 2040 | 26520 | 2048 (1)| 00:00:25 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_TOTAL_SALES_I | 2040 | | 7 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("TOTAL_SALES">=42 AND "TOTAL_SALES"<=142) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 2150 consistent gets 0 physical reads 0 redo size 43308 bytes sent via SQL*Net to client 1987 bytes received via SQL*Net from client 135 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2009 rows processed The index is now significantly faster than previously 44 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 45. Exadata Smart Flash Cache  Improves Database Index performance  Random reads against tables and indexes are likely to have subsequent reads and normally will be cached and have their data subsequently delivered from the flash cache  10x -100x better performance than disk  Both table and index blocks cached 45 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 46. Storage Indexes – Combine First, we run a query using a storage index on the ALBUM_ID column SQL> select * from big_bowie where album_id <= 10; 1000002 rows selected. Elapsed: 00:00:06.41 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1009K| 88M| 36667 (1)| 00:07:21 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1009K| 88M| 36667 (1)| 00:07:21 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ALBUM_ID"<=10) filter("ALBUM_ID"<=10) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 947.367188 cell physical IO interconnect bytes returned by smart scan 94.2925186 46 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 47. Storage Indexes – Combine Next, we run a query using a storage index on the ARTIST_ID column SQL> select * from big_bowie where artist_id <= 10000; 1000002 rows selected. Elapsed: 00:00:06.85 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000K| 87M| 36676 (1)| 00:07:21 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1000K| 87M| 36676 (1)| 00:07:21 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ARTIST_ID"<=10000) filter("ARTIST_ID"<=10000) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 850.140625 cell physical IO interconnect bytes returned by smart scan 94.4599609 47 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 48. Storage Indexes – Combine Finally, we run a query using storage indexes on both columns SQL> select * from big_bowie where album_id <= 10 and artist_id <= 10000; 100002 rows selected. Elapsed: 00:00:00.52 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 100K| 9066K| 36675 (1)| 00:07:21 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 100K| 9066K| 36675 (1)| 00:07:21 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ARTIST_ID"<=10000 AND "ALBUM_ID"<=10) filter("ARTIST_ID"<=10000 AND "ALBUM_ID"<=10) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 1031.4375 cell physical IO interconnect bytes returned by smart scan 9.31826019 IO bytes saved by storage indexes is now greater than previous examples 48 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 49. Storage Index Advantages  Are created automatically and transparently  Used automatically if present during Smart Scans  Do not take up any physical storage (memory only)  Have negligible impact on DML statements  Effective in processing IS NULL predicates  Might make corresponding Database indexes redundant  As they’re used during Smart Scans, when used can return just the rows/columns of interest to the database 49 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 50. Storage Index Disadvantages  Limited to a max of 8 columns per table  May not exist on a particular column at a point in time  Not as “focused” (1MB storage region default vs. 1 data block)  Has limitations, can only use Min/Max as referenced data  Database indexes determines specific location of data while a SI can only determine where data can’t exist  Therefore SI can still access unnecessarily storage of no interest  Can not cache data in database buffer cache for general re-usability  The CBO is not aware of Storage Indexes savings  Not as general purpose as database indexes (can’t police constraints, avoid sorts, provide CBO statistics, etc.) 50 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 51. Storage Indexes: 8 Column Limit SQL> create table radiohead (id number, col1 number, col2 number, col3 number, col4 number, col5 number, col6 number, col7 number, col8 number, col9 number, col10 number, col11 number, col12 number, some_text varchar2(50)); Table created. SQL> insert into radiohead select rownum, mod(rownum,10), mod(rownum,100), mod(rownum,1000), mod(rownum,10000), mod(rownum,100000), mod(rownum,1000000), ceil(dbms_random.value(0,10)), ceil(dbms_random.value(0,100)), ceil(dbms_random.value(0,1000)), ceil(dbms_random.value(0,10000)), ceil(dbms_random.value(0,100000)), ceil(dbms_random.value(0,1000000)), 'OK COMPUTER' from dual connect by level <=2000000; 2000000 rows created. SQL> commit; Commit complete. SQL> insert/*+ append */ into radiohead select * from radiohead; 2000000 rows created. SQL> commit; Commit complete. SQL> insert/*+ append */ into radiohead select * from radiohead; 4000000 rows created. SQL> commit; Commit complete. SQL> insert/*+ append */ into radiohead select * from radiohead; 8000000 rows created. SQL> commit; Commit complete. SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'RADIOHEAD', estimate_percent=>null, method_opt=> 'FOR ALL COLUMNS SIZE 1'); 51 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 52. Storage Indexes: 8 Column Limit SQL> select * from radiohead where id = 42; 8 rows selected. Elapsed: 00:00:00.05 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 8 | 416 | 42425 (1)| 00:08:30 | |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 8 | 416 | 42425 (1)| 00:08:30 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ID"=121212) filter("ID"=121212) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 1333.99219 cell physical IO interconnect bytes returned by smart scan .164878845 Storage index created on the ID column … 52 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 53. Storage Indexes: 8 Column Limit Repeat with predicates based on each of the table columns SQL> select * from radiohead where col1=42; no rows selected Elapsed: 00:00:00.01 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 52 | 42440 (1)| 00:08:30 | |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 1 | 52 | 42440 (1)| 00:08:30 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("COL1"=42) filter("COL1"=42) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 2546.90625 cell physical IO interconnect bytes returned by smart scan .341438293 The storage index on the COL1 column is used as well (can be useful in situations when the required value doesn’t exist)… 53 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 54. Storage Indexes: 8 Column Limit A Storage index is also used on COL4 although because of the distribution of data, the saved I/Os is limited SQL> select * from radiohead where col4=42; 1600 rows selected. Elapsed: 00:00:00.68 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1600 | 83200 | 42486 (1)| 00:08:30 | |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 1600 | 83200 | 42486 (1)| 00:08:30 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("COL4"=42) filter("COL4"=42) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 2612.64063 <= + 66MB cell physical IO interconnect bytes returned by smart scan 32.3048401 54 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 55. Storage Indexes: 8 Column Limit A Storage index is also used on, COL5, COL6, COL7, Col8 and COL9 making a total of 8 storage indexes defined on this table SQL> select * from radiohead where col9=0; no rows selected Elapsed: 00:00:00.02 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 15984 | 811K| 42561 (1)| 00:08:31 | |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 15984 | 811K| 42561 (1)| 00:08:31 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("COL9"=0) filter("COL9"=0) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 8792.94531 cell physical IO interconnect bytes returned by smart scan 45.3872757 55 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 56. Storage Indexes: 8 Column Limit However although a smart scan is performed, a viable storage index is not now created on COL10 column with 8 existing storage indexes SQL> select * from radiohead where col10=42; 1536 rows selected. Elapsed: 00:00:00.73 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1600 | 83200 | 42577 (1)| 00:08:31 | |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 1600 | 83200 | 42577 (1)| 00:08:31 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("COL10"=42) filter("COL10"=42) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 8792.94531  No change cell physical IO interconnect bytes returned by smart scan 45.9288864 56 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 57. Storage Indexes: 8 Column Limit On this much more selective query on COL12, a new storage index is created SQL> select * from radiohead where col12=42; 8 rows selected. Elapsed: 00:00:00.39 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 19 | 988 | 42607 (1)| 00:08:32 | |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 19 | 988 | 42607 (1)| 00:08:32 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("COL12"=42) filter("COL12"=42) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 9526.01563 cell physical IO interconnect bytes returned by smart scan 53.5218124 57 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 58. Storage Indexes: 8 Column Limit If we go back to the first query on the ID column, the storage index is still used … SQL> select * from radiohead where id=42; 8 rows selected. Elapsed: 00:00:00.05 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 8 | 416 | 42425 (1)| 00:08:30 | |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 8 | 416 | 42425 (1)| 00:08:30 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ID"=42) filter("ID"=42) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 10726.9844 cell physical IO interconnect bytes returned by smart scan 53.5264816 58 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 59. Storage Indexes: 8 Column Limit But if we go back to the not so selective query on the COL4 column, the storage index is no longer used as it was previously … SQL> select * from radiohead where col4 = 4242; 1600 rows selected. Elapsed: 00:00:00.73 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1600 | 83200 | 42486 (1)| 00:08:30 | |* 1 | TABLE ACCESS STORAGE FULL| RADIOHEAD | 1600 | 83200 | 42486 (1)| 00:08:30 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("COL4"=4242) filter("COL4"=4242) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 10726.9844  No Change !! cell physical IO interconnect bytes returned by smart scan 54.1522598 The Storage Index on COL4 is replaced by the Storage Index on COL12 … 59 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 60. “Hidden” Values of Interest Returning to the BIG_BOWIE table, the FORMAT_ID column has values 2 – 10, but only a handful with a value of 3 and 5 … SQL> update big_bowie set format_id = 3 where mod(id,10000)=0; 1000 rows updated. SQL> commit; Commit complete. SQL> update big_bowie set format_id = 5 where id between 424242 and 425241; 1000 rows updated. SQL> commit; Commit complete. SQL> create index big_bowie_format_id_i on big_bowie(format_id); Index created. SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'BIG_BOWIE', method_opt=> 'FOR COLUMNS FORMAT_ID SIZE 10'); PL/SQL procedure successfully completed. 60 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 61. “Hidden” Values of Interest With a histogram in place, the CBO uses an index very effectively … SQL> select album_id, total_sales from big_bowie where format_id = 3; 1000 rows selected. Elapsed: 00:00:00.01 Execution Plan ----------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000 | 11000 | 72 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 1000 | 11000 | 72 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_FORMAT_ID_I | 1000 | | 4 (0)| 00:00:01 | ----------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("FORMAT_ID"=3) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1072 consistent gets 0 physical reads 0 redo size 22984 bytes sent via SQL*Net to client 1250 bytes received via SQL*Net from client 68 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1000 rows processed 61 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 62. “Hidden” Values of Interest Whereas value 3 was littered throughout the table, values 5 are all clustered together, making the index even more effective … SQL> select album_id, total_sales from big_bowie where format_id = 5; 1000 rows selected. Elapsed: 00:00:00.00 Execution Plan ----------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000 | 11000 | 72 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 1000 | 11000 | 72 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_FORMAT_ID_I | 1000 | | 4 (0)| 00:00:01 | ----------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("FORMAT_ID"=5) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 154 consistent gets 0 physical reads 0 redo size 22685 bytes sent via SQL*Net to client 1250 bytes received via SQL*Net from client 68 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1000 rows processed 62 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 63. “Hidden” Values of Interest Smart Scan performed but a storage index is totally ineffective as the required values are “hidden” between the min/max (2 – 10) range found in most 1MB storage regions SQL> alter index big_bowie_format_id_i invisible; Index altered. SQL> select album_id, total_sales from big_bowie where format_id = 3; 1000 rows selected. Elapsed: 00:00:00.80 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000 | 11000 | 36682 (1)| 00:07:21 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1000 | 11000 | 36682 (1)| 00:07:21 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("FORMAT_ID"=3) filter("FORMAT_ID"=3) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 0 cell physical IO interconnect bytes returned by smart scan .397476196 63 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 64. “Hidden” Values of Interest In both cases, Storage Index is not used with Database index considerably faster … SQL> select album_id, total_sales from big_bowie where format_id = 5; 1000 rows selected. Elapsed: 00:00:00.89 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000 | 11000 | 36682 (1)| 00:07:21 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1000 | 11000 | 36682 (1)| 00:07:21 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("FORMAT_ID"=5) filter("FORMAT_ID"=5) SQL> select name , value/1024/1024 MB from v$statname n, v$mystat s where n.statistic# = s.statistic# and n.name in ('cell physical IO interconnect bytes returned by smart scan', 'cell physical IO bytes saved by storage index'); NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 0 cell physical IO interconnect bytes returned by smart scan .565643311 64 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 65. OLTP Environments  In OLTP environments, most queries and processes are based on highly selective data where database indexes are more viable  Indexes used for more than just “selecting” data, for example: – Police Primary and Unique Key constraints – Reduce locking implications with Foreign Keys – Reduce sorting requirements – Reduce function-based processing – Provide additional selectivity data to the CBO 65 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 66. Storage Indexes - Unique Scan With a storage index in place, a FTS is no longer really a FTS … SQL> select album_id, artist_id from big_bowie where id = 42; Elapsed: 00:00:00.02 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 14 | 36653 (1)| 00:07:20 | |* 1 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1 | 14 | 36653 (1)| 00:07:20 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ID"=42) filter("ID"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 134834 consistent gets 134809 physical reads 0 redo size 600 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 1052.22656 cell physical IO interconnect bytes returned by smart scan .000419617 66 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 67. Unique Scan However, an index is even faster and potentially far more scalable … SQL> select album_id, artist_id from big_bowie where id = 42; Elapsed: 00:00:00.00 Execution Plan -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 14 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 1 | 14 | 3 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | BIG_BOWIE_PK | 1 | | 2 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ID"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 4 consistent gets 0 physical reads 0 redo size 600 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed 67 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 68. Primary and Unique Keys Then there’s the issue of removing an index that enforces either a Primary or Unique Key constraint … SQL> drop index big_bowie_pk; drop index big_bowie_pk * ERROR at line 1: ORA-02429: cannot drop index used for enforcement of unique/primary key SQL> alter table big_bowie drop primary key; Table altered A Storage Index can not be used to enforce constraints. 68 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 69. Foreign Key Constraints Indexes can be critical in preventing locking issues with regard to Foreign Key Constraints… SQL> create table albums (id number, name varchar2(50)); Table created. SQL> insert into albums select rownum, table_name from dba_tables where rownum <=101; 101 rows created. SQL> commit; Commit complete. SQL> alter table albums add constraint albums_pk primary key (id); Table altered. SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'ALBUMS', estimate_percent=>null, method_opt=> 'FOR ALL COLUMNS SIZE 1'); PL/SQL procedure successfully completed. SQL> alter table big_bowie add constraint albums_fk foreign key (album_id) referencing albums(id); Table altered. 69 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 70. Foreign Key Constraints In Session 1 (no commit) SQL> insert into big_bowie values (10000001, 1, 1, 1, sysdate, 1, 'TEST'); 1 row created. In Session 2 (hangs !!) SQL> delete albums where id = 101; In Session 3 (hangs !!) SQL> insert into big_bowie values (10000002, 1,1,1,sysdate,1,'TEST2'); A Storage Index can not prevent Foreign Key locking related issues … 70 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 71. Foreign Key Constraints In Session 1 (no commit) SQL> create index big_bowie_album_id_i on big_bowie(album_id); Index created. SQL> insert into big_bowie values (10000001, 1, 1, 1, sysdate, 1, 'TEST'); 1 row created. In Session 2 (no longer hangs) SQL> delete albums where id = 101; 1 row deleted. In Session 3 (no longer hangs) SQL> insert into big_bowie values (10000002, 1,1,1,sysdate,1,'TEST2'); 1 row created. 71 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 72. Database Indexes and Sorts Database indexes return data in a sorted manner and so can avoid expensive sort operations … SQL> select * from big_bowie where album_id between 1 and 50 order by album_id; 5000002 rows selected. Elapsed: 00:00:13.08 Execution Plan ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5049K| 443M| 79536 (1)| 00:15:55 | | 1 | TABLE ACCESS BY INDEX ROWID| BIG_BOWIE | 5049K| 443M| 79536 (1)| 00:15:55 | |* 2 | INDEX RANGE SCAN | BIG_BOWIE_ALBUM_ID_I | 5049K| | 9916 (1)| 00:01:59 | ---------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ALBUM_ID">=1 AND "ALBUM_ID"<=50) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 80506 consistent gets 0 physical reads 0 redo size 483419167 bytes sent via SQL*Net to client 11524 bytes received via SQL*Net from client 1002 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 5000002 rows processed 72 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 73. Database Indexes and Sorts SQL> alter index big_bowie_album_id_i invisible; Index altered. SQL> select * from big_bowie where album_id between 1 and 50 order by album_id; 5000002 rows selected. Elapsed: 00:00:18.89 Execution Plan ------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 5049K| 443M| | 143K (1)| 00:28:48 | | 1 | SORT ORDER BY | | 5049K| 443M| 547M| 143K (1)| 00:28:48 | |* 2 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 5049K| 443M| | 36855 (1)| 00:07:23 | ------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - storage("ALBUM_ID"<=50 AND "ALBUM_ID">=1) filter("ALBUM_ID"<=50 AND "ALBUM_ID">=1) Statistics ---------------------------------------------------------- 501 recursive calls 10 db block gets 134798 consistent gets 198875 physical reads 0 redo size 155412142 bytes sent via SQL*Net to client 11524 bytes received via SQL*Net from client 1002 SQL*Net roundtrips to/from client 0 sorts (memory) 1 sorts (disk) 5000002 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 401.195313 cell physical IO interconnect bytes returned by smart scan 476.618843 73 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 74. NULLs and Storage Indexes Storage Indexes include NULL flag to determine which storage regions contain NULLs SQL> select count(*) from big_bowie where total_sales is null; COUNT(*) ---------- 0 Elapsed: 00:00:00.04 Execution Plan ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 5 | 36686 (1)| 00:07:21 | | 1 | SORT AGGREGATE | | 1 | 5 | | | |* 2 | TABLE ACCESS STORAGE FULL| BIG_BOWIE | 1 | 5 | 36686 (1)| 00:07:21 | ---------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - storage("TOTAL_SALES" IS NULL) filter("TOTAL_SALES" IS NULL) NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 1053.19531 cell physical IO interconnect bytes returned by smart scan 0 74 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 75. Offloading Functions SQL> select id, album_id, mod(artist_id, 10) from dwh_bowie where album_id = 42; 6400000 rows selected. Elapsed: 00:00:11.39 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6400K| 85M| 2348K (1)| 07:49:38 | |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 6400K| 85M| 2348K (1)| 07:49:38 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage("ALBUM_ID"=42) filter("ALBUM_ID"=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 8626963 consistent gets 8625479 physical reads 0 redo size 82753965 bytes sent via SQL*Net to client 14593 bytes received via SQL*Net from client 1281 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 6400000 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 44460.3828 cell physical IO interconnect bytes returned by smart scan 129.252693 75 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 76. Offloading Functions Processing of many function calls can also be offloaded to the storage cells. To see the full list, simple run : SQL> select name from v$sqlfn_metadata where offloadable = 'YES' order by name; However, you can not base a storage index on a function; Function-Based Storage Indexes are not supported … Additionally, many functions can not currently be offloaded … 76 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 77. Function-Based Indexes SQL> select id, album_id, mod(artist_id, 10) from dwh_bowie where trunc(album_id)=42; 6400000 rows selected. Elapsed: 00:00:28.71 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6400K| 85M| 2351K (1)| 07:50:14 | |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 6400K| 85M| 2351K (1)| 07:50:14 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage(TRUNC("ALBUM_ID")=42) filter(TRUNC("ALBUM_ID")=42) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 8626963 consistent gets 8625479 physical reads 0 redo size 82753965 bytes sent via SQL*Net to client 14593 bytes received via SQL*Net from client 1281 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 6400000 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 44460.3828 <= no change !! cell physical IO interconnect bytes returned by smart scan 264.957054 77 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 78. Min/Mix Example SQL> select min(id) from dwh_bowie; MIN(ID) ---------- 1 Elapsed: 00:00:41.31 Execution Plan ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 6 | 2345K (1)| 07:49:12 | | 1 | SORT AGGREGATE | | 1 | 6 | | | | 2 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 640M| 3662M| 2345K (1)| 07:49:12 | ---------------------------------------------------------------------------------------- Statist5ics ---------------------------------------------------------- 0 recursive calls 0 db block gets 8626963 consistent gets 8625479 physical reads 0 redo size 525 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 0 cell physical IO interconnect bytes returned by smart scan 7644.38194 78 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 79. Min/Mix Example SQL> create index dwh_bowie_id_i on dwh_bowie(id); Index created. SQL> select min(id) from dwh_bowie; MIN(ID) ---------- 1 Elapsed: 00:00:00.01 Execution Plan --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 6 | 4 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 6 | | | | 2 | INDEX FULL SCAN (MIN/MAX)| DWH_BOWIE_ID_I | 1 | 6 | 4 (0)| 00:00:01 | --------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 4 consistent gets 3 physical reads 0 redo size 525 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed 79 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 80. Smart Scans and Serial DML SQL> update dwh_bowie set description = 'ZIGGY' where total_sales = 42; 1472 rows updated. Elapsed: 00:15:00.38 Execution Plan ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | UPDATE STATEMENT | | 1264 | 84688 | 2350K (1)| 07:50:07 | | 1 | UPDATE | DWH_BOWIE | | | | | |* 2 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 1264 | 84688 | 2350K (1)| 07:50:07 | ---------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - storage("TOTAL_SALES"=42) filter("TOTAL_SALES"=42) Statistics ---------------------------------------------------------- 8 recursive calls 1525 db block gets 8632370 consistent gets 8622545 physical reads 485364 redo size 559 bytes sent via SQL*Net to client 749 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 2 sorts (memory) 0 sorts (disk) 1472 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 0 cell physical IO interconnect bytes returned by smart scan 0 80 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 81. Smart Scans and Parallel DML SQL> update /*+ parallel */ dwh_bowie set description = 'ZIGGY' where total_sales = 42; 1472 rows updated. Elapsed: 00:00:18.26 Execution Plan ------------------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib | ------------------------------------------------------------------------------------------------------------------------ | 0 | UPDATE STATEMENT | | 1264 | 84688 | 27171 (1)| 00:00:55 | | | | | 1 | UPDATE | DWH_BOWIE | | | | | | | | | 2 | PX COORDINATOR | | | | | | | | | | 3 | PX SEND QC (RANDOM) | :TQ10000 | 1264 | 84688 | 27171 (1)| 00:00:55 | Q1,00 | P->S | QC (RAND) | | 4 | PX BLOCK ITERATOR | | 1264 | 84688 | 27171 (1)| 00:00:55 | Q1,00 | PCWC | | |* 5 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 1264 | 84688 | 27171 (1)| 00:00:55 | Q1,00 | PCWP | | ------------------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 5 - storage("TOTAL_SALES"=42) filter("TOTAL_SALES"=42) Statistics ---------------------------------------------------------- 336 recursive calls 1525 db block gets 10476664 consistent gets 8625479 physical reads 567008 redo size 550 bytes sent via SQL*Net to client 766 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1472 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 29342.4453 cell physical IO interconnect bytes returned by smart scan 5.97057343 81 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 82. Indexes and DML An Index can still be the best and most scalable option with selective DML … SQL> create index dwh_bowie_total_sales_i on dwh_bowie(total_sales); Index created. SQL> update dwh_bowie set description = 'ZIGGY' where total_sales = 42; 1472 rows updated. Elapsed: 00:00:00.92 Execution Plan --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | UPDATE STATEMENT | | 1264 | 84688 | 1270 (0)| 00:00:16 | | 1 | UPDATE | DWH_BOWIE | | | | | |* 2 | INDEX RANGE SCAN| DWH_BOWIE_TOTAL_SALES_I | 1264 | 84688 | 6 (0)| 00:00:01 | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("TOTAL_SALES"=42) Statistics ---------------------------------------------------------- 0 recursive calls 1523 db block gets 7 consistent gets 0 physical reads 508060 redo size 563 bytes sent via SQL*Net to client 750 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1472 rows processed 82 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 83. Data Warehouse Environments  Constraint management may not be such an issue  Typically, queries can be large, expensive affairs  Use of Full Table/Index Scans more prevalent  Smart Scans and Storage Indexes more viable  Good opportunity to drop unnecessary indexes  However, InfiniBand is not Infinite-Band  However, overall load and scalability still a consideration  However, database indexes can still be effective 83 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 84. DWH Join Example – Serial Execution SQL> select * from dwh_bowie d, albums a, formats f where d.album_id = a.id and d.format_id=f.id and a.name in ('TAB$', 'COL$') and f.name = 'I_USER#'; 64000 rows selected. Elapsed: 00:02:50.05 Execution Plan ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)|Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1600K| 177M| 2352K (1)|07:50:33 | |* 1 | HASH JOIN | | 1600K| 177M| 2352K (1)|07:50:33 | | 2 | MERGE JOIN CARTESIAN | | 2 | 48 | 36 (0)|00:00:01 | |* 3 | TABLE ACCESS STORAGE FULL | FORMATS | 1 | 11 | 18 (0)|00:00:01 | | 4 | BUFFER SORT | | 2 | 26 | 18 (0)|00:00:01 | |* 5 | TABLE ACCESS STORAGE FULL| ALBUMS | 2 | 26 | 18 (0)|00:00:01 | | 6 | TABLE ACCESS STORAGE FULL | DWH_BOWIE | 640M| 54G| 2349K (1)|07:49:56 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("D"."ALBUM_ID"="A"."ID" AND "D"."FORMAT_ID"="F"."ID") 3 - storage("F"."NAME"='I_USER#') filter("F"."NAME"='I_USER#') 5 - storage("A"."NAME"='COL$' OR "A"."NAME"='TAB$') filter("A"."NAME"='COL$' OR "A"."NAME"='TAB$') NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 0 cell physical IO interconnect bytes returned by smart scan 61084.5128 84 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 85. Join Bloom Filter  A bloom filter is a bitmap like structure (bit vector) that determines whether a value belongs to a given set or not  Used since Oracle10g R2 in parallel join processing and since Oracle11g R1 in join-filter processing  On Exadata the bloom filter is passed as an additional predicate so it can be overloaded to the storage cells making bloom filtering very efficient  Following Parallel Query example highlights the potential efficiencies with the use of bloom filtering  For an excellent article on Bloom Filters, see Christian Antognini’s article: – http://www.antognini.ch/papers/BloomFilters20080620.pdf 85 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 86. DWH Example – Parallel Execution SQL> select /*+ parallel */ * from dwh_bowie d, albums a, formats f where d.album_id = a.id and d.format_id=f.id and a.name in ('TAB$', 'COL$') and f.name = 'I_USER#'; 64000 rows selected. Elapsed: 00:00:03.34 ------------------------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib | ------------------------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1600K| 177M| 27198 (1)| 00:00:55 | | | | | 1 | PX COORDINATOR | | | | | | | | | | 2 | PX SEND QC (RANDOM) | :TQ10002 | 1600K| 177M| 27198 (1)| 00:00:55 | Q1,02 | P->S | QC (RAND) | |* 3 | HASH JOIN | | 1600K| 177M| 27198 (1)| 00:00:55 | Q1,02 | PCWP | | | 4 | PX RECEIVE | | 2 | 48 | 5 (0)| 00:00:01 | Q1,02 | PCWP | | | 5 | PX SEND BROADCAST | :TQ10001 | 2 | 48 | 5 (0)| 00:00:01 | Q1,01 | P->P | BROADCAST | | 6 | MERGE JOIN CARTESIAN | | 2 | 48 | 5 (0)| 00:00:01 | Q1,01 | PCWP | | | 7 | BUFFER SORT | | | | | | Q1,01 | PCWC | | | 8 | PX RECEIVE | | 1 | 11 | 2 (0)| 00:00:01 | Q1,01 | PCWP | | | 9 | PX SEND BROADCAST | :TQ10000 | 1 | 11 | 2 (0)| 00:00:01 | Q1,00 | P->P | BROADCAST | | 10 | PX BLOCK ITERATOR | | 1 | 11 | 2 (0)| 00:00:01 | Q1,00 | PCWC | | |* 11 | TABLE ACCESS STORAGE FULL| FORMATS | 1 | 11 | 2 (0)| 00:00:01 | Q1,00 | PCWP | | | 12 | BUFFER SORT | | 2 | 26 | 3 (0)| 00:00:01 | Q1,01 | PCWP | | | 13 | PX BLOCK ITERATOR | | 2 | 26 | 2 (0)| 00:00:01 | Q1,01 | PCWC | | |* 14 | TABLE ACCESS STORAGE FULL | ALBUMS | 2 | 26 | 2 (0)| 00:00:01 | Q1,01 | PCWP | | | 15 | PX BLOCK ITERATOR | | 640M| 54G| 27161 (1)| 00:00:55 | Q1,02 | PCWC | | |* 16 | TABLE ACCESS STORAGE FULL | DWH_BOWIE | 640M| 54G| 27161 (1)| 00:00:55 | Q1,02 | PCWP | | ------------------------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("D"."ALBUM_ID"="A"."ID" AND "D"."FORMAT_ID"="F"."ID") 11 - storage("F"."NAME"='I_USER#') filter("F"."NAME"='I_USER#') 14 - storage("A"."NAME"='COL$' OR "A"."NAME"='TAB$') filter("A"."NAME"='COL$' OR "A"."NAME"='TAB$') 16 - storage(SYS_OP_BLOOM_FILTER(:BF0000,"D"."ALBUM_ID","D"."FORMAT_ID")) filter(SYS_OP_BLOOM_FILTER(:BF0000,"D"."ALBUM_ID","D"."FORMAT_ID")) NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 60251.3984 cell physical IO interconnect bytes returned by smart scan 1161.76605 86 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 87. DWH Example – Star Transformation If we now make relevant Bitmap Indexes visible again SQL> alter index dwh_bowie_album_id_i visible; Index altered. SQL> alter index dwh_bowie_format_i visible; Index altered. SQL> select * from dwh_bowie d, albums a, formats f where d.album_id = a.id and d.format_id=f.id and a.name in ('TAB$', 'COL$') and f.name = 'I_USER#'; 64000 rows selected. Elapsed: 00:00:00.34 In some scenarios, indexes still have a place in DWH environments as well. It all depends … 87 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 88. DWH Example – Star Transformation Execution Plan --------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes| Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 198K| 28M| 319K (1)| 01:04:00 | |* 1 | HASH JOIN | | 198K| 28M| 319K (1)| 01:04:00 | | 2 | MERGE JOIN CARTESIAN | | 2 | 48| 36 (0)| 00:00:01 | |* 3 | TABLE ACCESS STORAGE FULL | FORMATS | 1 | 11| 18 (0)| 00:00:01 | | 4 | BUFFER SORT | | 2 | 26| 18 (0)| 00:00:01 | |* 5 | TABLE ACCESS STORAGE FULL | ALBUMS | 2 | 26| 18 (0)| 00:00:01 | | 6 | VIEW | VW_ST_4B85F3B9 | 1584K| 190M| 319K (1)| 01:03:59 | | 7 | NESTED LOOPS | | 1584K| 172M| 319K (1)| 01:03:59 | | 8 | BITMAP CONVERSION TO ROWIDS | | 1584K| 27M| 275 (2)| 00:00:04 | | 9 | BITMAP AND | | | | | | | 10 | BITMAP MERGE | | | | | | | 11 | BITMAP KEY ITERATION | | | | | | |* 12 | TABLE ACCESS STORAGE FULL| ALBUMS | 2 | 26| 18 (0)| 00:00:01 | |* 13 | BITMAP INDEX RANGE SCAN | DWH_BOWIE_ALBUM_ID_I | | | | | | 14 | BITMAP MERGE | | | | | | | 15 | BITMAP KEY ITERATION | | | | | | |* 16 | TABLE ACCESS STORAGE FULL| FORMATS | 1 | 11| 18 (0)| 00:00:01 | |* 17 | BITMAP INDEX RANGE SCAN | DWH_BOWIE_FORMAT_I | | | | | | 18 | TABLE ACCESS BY USER ROWID | DWH_BOWIE | 1 | 96| 319K (1)| 01:03:56 | --------------------------------------------------------------------------------------------------------- Note ----- - star transformation used for this statement Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 2288 consistent gets 0 physical reads 476 redo size 2240022 bytes sent via SQL*Net to client 656 bytes received via SQL*Net from client 14 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 64000 rows processed 88 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 89. Indexes – Skinny Tables SQL> select blocks from dba_tables where table_name = 'DWH_BOWIE'; BLOCKS ---------- 8634533 SQL> select count(*) from dwh_bowie; COUNT(*) ---------- 640000128 Elapsed: 00:00:40.31 Execution Plan -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2345K (1)| 07:49:12 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 640M| 2345K (1)| 07:49:12 | -------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 63 recursive calls 0 db block gets 8627017 consistent gets 8625479 physical reads 0 redo size 530 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 1 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 0 cell physical IO interconnect bytes returned by smart scan 7644.35252 89 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 90. Indexes – Skinny Tables SQL> create index dwh_bowie_album_id_i on dwh_bowie(album_id); Index created. SQL> select leaf_blocks from user_indexes where index_name = 'DWH_BOWIE_ALBUM_ID_I'; LEAF_BLOCKS ----------- 1250001 SQL> select count(*) from dwh_bowie; Elapsed: 00:00:20.30 Execution Plan ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 342K (2)| 01:08:32 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX STORAGE FAST FULL SCAN| DWH_BOWIE_ALBUM_ID_I | 640M| 342K (2)| 01:08:32 | ---------------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 1253756 consistent gets 1252492 physical reads 0 redo size 530 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 0 cell physical IO interconnect bytes returned by smart scan 3103.25166 90 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 91. Bitmap Indexes – Really Skinny Tables SQL> create bitmap index dwh_bowie_album_id_i on dwh_bowie(album_id); Index created. SQL> select leaf_blocks from user_indexes where index_name = 'DWH_BOWIE_ALBUM_ID_I'; LEAF_BLOCKS ----------- 16086 SQL> select count(*) from dwh_bowie; Elapsed: 00:00:00.22 Execution Plan ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 14482 (1)| 00:02:54 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | BITMAP CONVERSION COUNT | | 640M| 14482 (1)| 00:02:54 | | 3 | BITMAP INDEX STORAGE FAST FULL SCAN| DWH_BOWIE_ALBUM_ID_I | | | | ------------------------------------------------------------------------------------------------------ Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 16143 consistent gets 0 physical reads 0 redo size 530 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed NAME MB ---------------------------------------------------------------- ---------- cell physical IO bytes saved by storage index 0 cell physical IO interconnect bytes returned by smart scan 0 91 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 92. Hybrid Columnar Compression (HCC) SQL> create table tiny_dwh_bowie compress for query high as select * from dwh_bowie where 1=2; Table created. SQL> insert /*+ append */ into tiny_dwh_bowie select * from dwh_bowie; 640000128 rows created. SQL> commit; Commit complete. SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'TINY_DWH_BOWIE', estimate_percent=>null, method_opt=> 'FOR ALL COLUMNS SIZE 1'); PL/SQL procedure successfully completed. SQL> create table tiny_dwh_bowie2 compress for archive high as select * from dwh_bowie where 1=2; Table created. SQL> insert /*+ append */ into tiny_dwh_bowie2 select * from tiny_dwh_bowie; 640000128 rows created. SQL> commit; Commit complete. SQL> select table_name, blocks, round((blocks*8)/1024) MB, compress_for from user_tables where table_name like '%DWH_BOWIE%'; TABLE_NAME BLOCKS MB COMPRESS_FOR ------------------------------ ---------- ---------- ------------ DWH_BOWIE 8634533 67457 TINY_DWH_BOWIE 521645 4075 QUERY HIGH TINY_DWH_BOWIE2 403379 3151 ARCHIVE HIGH 92 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 93. HCC and Smart Scans SQL> select * from dwh_bowie where album_id = 42; 6400000 rows selected. Elapsed: 00:00:46.61 Execution Plan --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6400K| 561M| 2348K (1)| 07:49:38 | |* 1 | TABLE ACCESS STORAGE FULL| DWH_BOWIE | 6400K| 561M| 2348K (1)| 07:49:38 | --------------------------------------------------------------------------------------- SQL> select * from tiny_dwh_bowie where album_id = 42; 6400000 rows selected. Elapsed: 00:00:33.54 Execution Plan -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6400K| 561M| 148K (5)| 00:29:38 | |* 1 | TABLE ACCESS STORAGE FULL| TINY_DWH_BOWIE | 6400K| 561M| 148K (5)| 00:29:38 | -------------------------------------------------------------------------------------------- SQL> select * from tiny_dwh_bowie2 where album_id = 42; 6400000 rows selected. Elapsed: 00:00:41.04 Execution Plan --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6400K| 561M| 116K (6)| 00:23:13 | |* 1 | TABLE ACCESS STORAGE FULL| TINY_DWH_BOWIE2 | 6400K| 561M| 116K (6)| 00:23:13 | --------------------------------------------------------------------------------------------- 93 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 94. HCC and Indexes If we create indexes in all three tables … SQL> create index dwh_bowie_album_i on dwh_bowie(album_id); Index created. SQL> create index tiny_bowie_album_i on tiny_dwh_bowie(album_id); Index created. SQL> create index tiny_bowie2_album_i on tiny_dwh_bowie2(album_id); Index created. SQL> select index_name, leaf_blocks, clustering_factor from user_indexes where index_name like '%BOWIE%ALBUM%'; INDEX_NAME LEAF_BLOCKS CLUSTERING_FACTOR ------------------------------ ----------- ----------------- DWH_BOWIE_ALBUM_I 1250001 8876879 TINY_BOWIE_ALBUM_I 1250001 224887 TINY_BOWIE2_ALBUM_I 1250001 84549 All are the same size but have vastly differing Clustering Factors 94 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 95. HCC and Indexes If we create indexes in all three tables and re-run with fully cached data … SQL> select * from dwh_bowie where album_id = 42; 6400000 rows selected. Elapsed: 00:00:16.96 Execution Plan ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6400K| 561M| 101K (1)| 00:20:18 | | 1 | TABLE ACCESS BY INDEX ROWID| DWH_BOWIE | 6400K| 561M| 101K (1)| 00:20:18 | |* 2 | INDEX RANGE SCAN | DWH_BOWIE_ALBUM_I | 6400K| | 12569 (1)| 00:02:31 | ------------------------------------------------------------------------------------------------- SQL> select * from tiny_dwh_bowie where album_id = 42; 6400000 rows selected. Elapsed: 00:00:21.16 Execution Plan -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost(%CPU)| Time | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6400K| 561M| 14900 (1)| 00:02:59 | | 1 | TABLE ACCESS BY INDEX ROWID| TINY_DWH_BOWIE | 6400K| 561M| 14900 (1)| 00:02:59 | |* 2 | INDEX RANGE SCAN | TINY_BOWIE_ALBUM_I | 6400K| | 12569 (1)| 00:02:31 | -------------------------------------------------------------------------------------------------- SQL> select * from tiny_dwh_bowie2 where album_id = 42; 6400000 rows selected. Elapsed: 00:01:08.38 Execution Plan --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6400K| 561M| 13497 (2)| 00:02:42 | | 1 | TABLE ACCESS BY INDEX ROWID| TINY_DWH_BOWIE2 | 6400K| 561M| 13497 (2)| 00:02:42 | |* 2 | INDEX RANGE SCAN | TINY_BOWIE2_ALBUM_I | 6400K| | 12569 (1)| 00:02:31 | --------------------------------------------------------------------------------------------------- 95 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 96. HCC and Indexes  Index CBO costs can decrease due to decrease in CF  Actual costs increase however when accessing HCC tables as the required data needs to be reconstructed/decompressed  Especially so for COMPRESS FOR ARCHIVE  This extra work burns significant CPU  The CBO however does not consider these additional CPU costs in its calculations  Indexes therefore more likely to be inappropriately selected by CBO with HCC 96 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 97. Exadata Smart Scans Operations that don’t benefit from Smart Scans include:  Index range scans.  Scans of IOTs or Clustered Tables.  Access to a compressed index.  Access to a reverse key index. 97 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 98. Index Organized Tables: No Smart Scan SQL> create table big_bowie_iot (id number constraint big_bowie_iot_pk primary key, album_id number, artist_id number, format_id number, release_date date, total_sales number, description varchar2(100)) organization index; Table created. SQL> insert into big_bowie_iot select * from big_bowie; 10000000 rows created. SQL> commit; Commit complete. SQL> select * from big_bowie_iot where total_sales = 42; 23 rows selected. Elapsed: 00:00:16.72 Execution Plan ----------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 20 | 1840 | 36698 (1)| 00:07:21 | |* 1 | INDEX FAST FULL SCAN| BIG_BOWIE_IOT_PK | 20 | 1840 | 36698 (1)| 00:07:21 | ----------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("TOTAL_SALES"=42) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 135672 consistent gets 134280 physical reads 0 redo size 1972 bytes sent via SQL*Net to client 535 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 23 rows processed 98 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 99. General Conclusions  With Exadata, things run faster, FTS especially so  Some indexes can become redundant as a result  CBO not fully aware of reduced FTS costs  CBO not fully aware of increased index costs associated with HCC  With indexes in place, faster smart scans operations may be dismissed  However, using an index should generally be no worse than in Non- Exadata environments (although HCC an exception)  Database indexes still of value in numerous scenarios, especially in OLTP environments  Need to understand benefits/advantages of smart scans and storage indexes and where there may have shortfalls 99 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 100. General Recommendations  Easy to create an index, much harder and riskier to subsequently drop them  When moving to Exadata, take the opportunity to review current indexes, especially in DWH environments which are often “over indexed”  Use information in v$sql_plan, dba_hist_sql_plan, AWR reports to determine potentially problematic indexes  But do not blindly drop indexes in the hope Exadata will just cope regardless …  Use Invisible Indexes to test impact of potentially dropping an index  Real Application Testing (RAT) of enormous use when migrating to Exadata 100 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 101. richardfoote.wordpress.com An Oracle Indexing blog might still have some value yet !!! 101 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.
  • 102. 102 Copyright © 2012, Oracle and/or its affiliates. All rights reserved.