Thursday, May 26, 2011

Enabling Stored Outlines

rajesh@ORA10GR2> create table t
  2  nologging
  3  as
  4  select rownum as x,
  5        rpad('*',80,'*')||mod(rownum,10) as id,
  6        a.*
  7  from all_objects a;

Table created.

Elapsed: 00:00:04.12
rajesh@ORA10GR2>
rajesh@ORA10GR2> create index t_ind on t(id) nologging;

Index created.

Elapsed: 00:00:00.45
rajesh@ORA10GR2>
rajesh@ORA10GR2> begin
  2     dbms_stats.gather_table_stats(
  3     ownname =>user,
  4     tabname =>'T',
  5     estimate_percent=>dbms_stats.auto_sample_size,
  6     method_opt=>'for all indexed columns size 1',
  7     cascade => false);
  8  end;
  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.04
rajesh@ORA10GR2>

I have a B*Tree index defined on a Varchar2(80) column, having B*Tree index beyond Varchar2(32) data's will not provide efficient histograms which leads to improper cardinality and poor access paths and plans.

rajesh@ORA10GR2> variable x varchar2(100);
rajesh@ORA10GR2>
rajesh@ORA10GR2> exec :x := rpad('*',80,'*')||'11';

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.00
rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace traceonly explain statistics;
rajesh@ORA10GR2>
rajesh@ORA10GR2> select x,id
  2  from t
  3  where id = :x;

no rows selected

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4986 |   462K|   296   (2)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| T    |  4986 |   462K|   296   (2)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID"=:X)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1300  consistent gets
          0  physical reads
          0  redo size
        322  bytes sent via SQL*Net to client
        385  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

rajesh@ORA10GR2>

It took 1300 IO's, The optimizer skiped using index because Histograms doesn't yeild proper cardinality. so poor cardinality = poor plan.

Now let's see what happens when we force using index to this query.

rajesh@ORA10GR2> select /*+ index(t,t_ind) */ x,id
  2  from t
  3  where id = :x;

no rows selected

Elapsed: 00:00:00.04

Execution Plan
----------------------------------------------------------
Plan hash value: 1376202287
-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |  4986 |   462K|  1364   (1)| 00:00:17 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  4986 |   462K|  1364   (1)| 00:00:17 |
|*  2 |   INDEX RANGE SCAN          | T_IND |  4986 |       |    67   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID"=:X)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          3  consistent gets
          3  physical reads
          0  redo size
        322  bytes sent via SQL*Net to client
        385  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace off;

One best way to Tie this Explain plan ( plan using index) to this query is using Stored Outlines.

rajesh@ORA10GR2> ALTER SESSION SET CREATE_STORED_OUTLINES = TRUE;

Session altered.

Elapsed: 00:00:00.00
rajesh@ORA10GR2>
rajesh@ORA10GR2> alter session set optimizer_mode = first_rows;

Session altered.

Elapsed: 00:00:00.00
rajesh@ORA10GR2>
rajesh@ORA10GR2> select x,id
  2  from t
  3  where id = :x;

no rows selected

Elapsed: 00:00:00.04
rajesh@ORA10GR2>
rajesh@ORA10GR2> ALTER SESSION SET CREATE_STORED_OUTLINES = FALSE;

Session altered.

Elapsed: 00:00:00.00
rajesh@ORA10GR2>
rajesh@ORA10GR2> alter session set optimizer_mode = all_rows;

Session altered.

Elapsed: 00:00:00.00
rajesh@ORA10GR2>
rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace traceonly explain statistics;
rajesh@ORA10GR2>
rajesh@ORA10GR2> select x,id
  2  from t
  3  where id = :x;

no rows selected

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4986 |   462K|   296   (2)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| T    |  4986 |   462K|   296   (2)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID"=:X)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1300  consistent gets
          0  physical reads
          0  redo size
        322  bytes sent via SQL*Net to client
        385  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace off;

As you see these outlines are not used by optimizer, untill they are enabled either at session (or) instance level.

rajesh@ORA10GR2>
rajesh@ORA10GR2> alter session set use_stored_outlines=default;

Session altered.

Elapsed: 00:00:00.00
rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace traceonly explain statistics;
rajesh@ORA10GR2>
rajesh@ORA10GR2> select x,id
  2  from t
  3  where id = :x;

no rows selected

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1376202287
-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |  4986 |   462K|  1364   (1)| 00:00:17 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  4986 |   462K|  1364   (1)| 00:00:17 |
|*  2 |   INDEX RANGE SCAN          | T_IND |  4986 |       |    67   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID"=:X)
Note
-----
   - outline "SYS_OUTLINE_11052622281360902" used for this statement

Statistics
----------------------------------------------------------
         35  recursive calls
        135  db block gets
         24  consistent gets
          0  physical reads
        596  redo size
        322  bytes sent via SQL*Net to client
        385  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
          0  rows processed

rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace off;
rajesh@ORA10GR2>
rajesh@ORA10GR2>

The other way to enable the outlines at Instance level is

rajesh@ORA10GR2> connect sys/oracle as sysdba
Connected.
sys@ORA10GR2>
sys@ORA10GR2> alter system set use_stored_outlines = default;

System altered.

Elapsed: 00:00:00.00
sys@ORA10GR2>
sys@ORA10GR2> connect rajesh/oracle
Connected
rajesh@ORA10GR2>
rajesh@ORA10GR2> exec :x := rpad('*',80,'*')||'11';

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01
rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace traceonly explain statistics;
rajesh@ORA10GR2>
rajesh@ORA10GR2> select x,id
  2  from t
  3  where id = :x;

no rows selected

Elapsed: 00:00:00.00

Execution Plan
----------------------------------------------------------
Plan hash value: 1376202287
-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |  4986 |   462K|  1364   (1)| 00:00:17 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  4986 |   462K|  1364   (1)| 00:00:17 |
|*  2 |   INDEX RANGE SCAN          | T_IND |  4986 |       |    67   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID"=:X)
Note
-----
   - outline "SYS_OUTLINE_11052622281360902" used for this statement

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        322  bytes sent via SQL*Net to client
        385  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace off;

But remember that once database is bounced, you have to enable the outline's either at session level (or) instance level. If not the optimizer will not use the outlines.

rajesh@ORA10GR2>
rajesh@ORA10GR2>
rajesh@ORA10GR2>
rajesh@ORA10GR2> connect sys/oracle as sysdba
Connected.
sys@ORA10GR2>
sys@ORA10GR2>
sys@ORA10GR2> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
sys@ORA10GR2>
sys@ORA10GR2> startup;
ORACLE instance started.

Total System Global Area  612368384 bytes
Fixed Size                  1292036 bytes
Variable Size             218106108 bytes
Database Buffers          385875968 bytes
Redo Buffers                7094272 bytes
Database mounted.
Database opened.
sys@ORA10GR2>
sys@ORA10GR2> connect rajesh/oracle
Connected.

rajesh@ORA10GR2> variable x varchar2(100);
rajesh@ORA10GR2>
rajesh@ORA10GR2> exec :x := rpad('*',80,'*')||'11';

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01
rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace traceonly explain statistics;
rajesh@ORA10GR2>
rajesh@ORA10GR2> select x,id
  2  from t
  3  where id = :x;

no rows selected

Elapsed: 00:00:00.28

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  4986 |   462K|   296   (2)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| T    |  4986 |   462K|   296   (2)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID"=:X)

Statistics
----------------------------------------------------------
        361  recursive calls
          0  db block gets
       1367  consistent gets
       1302  physical reads
          0  redo size
        322  bytes sent via SQL*Net to client
        385  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
          0  rows processed

rajesh@ORA10GR2>
rajesh@ORA10GR2> set autotrace off;
rajesh@ORA10GR2>
rajesh@ORA10GR2>

Also outlines cannot be enabled at database level.

sys@ORA10GR2> alter database set use_stored_outlines = default;
alter database set use_stored_outlines = default
                   *
ERROR at line 1:
ORA-02231: missing or invalid option to ALTER DATABASE

Elapsed: 00:00:00.04
sys@ORA10GR2>

No comments:

Post a Comment