| Oracle FAQ | Your Portal to the Oracle Knowledge Grid | |
|  |  | |||
Home -> Community -> Usenet -> c.d.o.server -> Re: FBI? MAX? INDEX FULL SCAN (MIN/MAX)?
On Mar 12, 4:26 am, "lfree" <a..._at_a.a> wrote:
> FBI? MAX?  INDEX FULL SCAN (MIN/MAX)?
>
> select * from v$version
> BANNER
> ----------------------------------------------------------------
> Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
> PL/SQL Release 10.2.0.1.0 - Production
> CORE    10.2.0.1.0      Production
> TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
> NLSRTL Version 10.2.0.1.0 - Production
>
> scott> create table t as select * from all_objects;
>
> scott> create index if_t_object_name on t(lower(object_name));
>
> scott> create index i_t_object_name on t(object_name);
>
> scott>BEGIN
>   SYS.DBMS_STATS.GATHER_TABLE_STATS (
>       OwnName        => 'SCOTT'
>      ,TabName        => 'T'
>     ,Method_Opt        => 'FOR ALL COLUMNS SIZE 1 '
>     ,Degree            => 4
>     ,Cascade           => TRUE;
> END;
>
> scott> set autotrace traceonly ;
> scott> select max(object_name) from t ;
>
> Plan hash value: 348001784
>
> ----------------------------------------------------------------------------
> ------------------
> | Id  | Operation                  | Name            | Rows  | Bytes | Cost
> (%CPU)| Time     |
> ----------------------------------------------------------------------------
> ------------------
> |   0 | SELECT STATEMENT           |                 |     1 |    24 |     2
> (0)| 00:00:01 |
> |   1 |  SORT AGGREGATE            |                 |     1 |    24 |
> |          |
> |   2 |   INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_NAME | 50031 |  1172K|     2
> (0)| 00:00:01 |
> ----------------------------------------------------------------------------
> ------------------
>
>           0  recursive calls
>           0  db block gets
>           2  consistent gets
>           0  physical reads
>           0  redo size
>         439  bytes sent via SQL*Net to client
>         384  bytes received via SQL*Net from client
>           2  SQL*Net roundtrips to/from client
>           0  sorts (memory)
>           0  sorts (disk)
>           1  rows processed
>
> scott> select max(lower(object_name)) from t ;
>
> Plan hash value: 3320467716
>
> ----------------------------------------------------------------------------
> --------------
> | Id  | Operation             | Name             | Rows  | Bytes | Cost
> (%CPU)| Time     |
> ----------------------------------------------------------------------------
> --------------
> |   0 | SELECT STATEMENT      |                  |     1 |    24 |    57
> (2)| 00:00:01 |
> |   1 |  SORT AGGREGATE       |                  |     1 |    24 |
> |          |
> |   2 |   INDEX FAST FULL SCAN| IF_T_OBJECT_NAME | 50031 |  1172K|    57
> (2)| 00:00:01 |
> ----------------------------------------------------------------------------
> --------------
>
>           0  recursive calls
>           0  db block gets
>         253  consistent gets
>           0  physical reads
>           0  redo size
>         446  bytes sent via SQL*Net to client
>         384  bytes received via SQL*Net from client
>           2  SQL*Net roundtrips to/from client
>           0  sorts (memory)
>           0  sorts (disk)
>           1  rows processed
>
> why use FBI query max(lower(object_name)) ? execute plan is "INDEX FAST FULL
> SCAN".
Tested on Oracle 10.2.0.2 64 bit:
The setup:
CREATE TABLE T1 (
  C1 NUMBER(12),
  C2 NUMBER(12,8) NOT NULL,
  PRIMARY KEY (C1));
Insert 7200 rows into the table, and calculate the value of SIN for
the degree value in C1:
INSERT INTO
  T1
SELECT
  ROWNUM C1,
  ROUND(SIN(ROWNUM*3.141592/180),8) C2
FROM
  DUAL
CONNECT BY
  LEVEL<=360*20;
COMMIT;
Create two function based indexes on the table, the first of which
should contain values that are identical to the contents of C2:
CREATE INDEX IND_T1 ON T1(ROUND(SIN(C1*3.141592/180),8));
CREATE INDEX IND_T1_2 ON T1(ROUND(COS(C1*3.141592/180),8));
Gather statatistics on the table and indexes:
EXEC
DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'TABLE_OWNER_HERE',TABNAME=>'T1',CASCADE=>TRUE);
Let DBMS Xplan return additional details:
ALTER SESSION SET STATISTICS_LEVEL=ALL;
The first test, see if the primary key index on C1 will be used:
SELECT
  MAX(C1)
FROM
  T1;
Check the DBMS Xplan output:
SELECT
  *
FROM
  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS'));
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Starts | E-Rows |A-Rows | A-Time | Buffers |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 2 | | 2 | INDEX FULL SCAN (MIN/MAX)| SYS_C0022496 | 1 | 7200 | 1 |00:00:00.01 | 2 | -----------------------------------------------------------------------------------------------------
Now, let's see if Oracle uses the same technique on the first function
based index that we created:
SELECT
  MAX(ROUND(SIN(C1*3.141592/180),8))
FROM
  T1;
SELECT
  *
FROM
  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS'));
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.18 | 24 | | 2 | INDEX FAST FULL SCAN| SYS_C0022496 | 1 | 7200 | 7200 |00:00:00.01 | 24 | ------------------------------------------------------------------------------------------------
Oracle did not even bother to use the function based index. Instead, it performed a fast full scan of the primary key index.
Now, let's force Oracle to use the function based index:
SELECT /*+ INDEX(T1 IND_T1) */
  MAX(ROUND(SIN(C1*3.141592/180),8))
FROM
  T1;
SELECT
  *
FROM
  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS'));
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 2 | | 2 | FIRST ROW | | 1 | 7200 | 1 |00:00:00.01 | 2 | | 3 | INDEX FULL SCAN (MIN/MAX)| IND_T1 | 1 | 7200 | 1 |00:00:00.01 | 2 | ------------------------------------------------------------------------------------------------
Oracle used the function based index this time, and made use of the MIN/MAX as it did with the primary key index.
Let's gather statistics like you did and repeat the test.
BEGIN
  DBMS_STATS.GATHER_TABLE_STATS (
    OwnName        => 'TABLE_OWNER_HERE',
    TabName        => 'T1',
    Method_Opt        => 'FOR ALL COLUMNS SIZE 1 ',
    Degree            => 4,
    Cascade           => TRUE);
ALTER SYSTEM FLUSH SHARED_POOL; The SQL statements produced the same DBMS Xplans.
I suggest that you compare the output of DBMS Xplan with the SET AUTOTRACE TRACEONLY output to see if the plans are the same.
Charles Hooper
PC Support Specialist
K&M Machine-Fabricating, Inc.
Received on Mon Mar 12 2007 - 06:18:09 CDT
|  |  |