Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.server -> Re: FBI? MAX? INDEX FULL SCAN (MIN/MAX)?

Re: FBI? MAX? INDEX FULL SCAN (MIN/MAX)?

From: Charles Hooper <hooperc2000_at_yahoo.com>
Date: 12 Mar 2007 04:18:09 -0700
Message-ID: <1173698289.062368.46790@p10g2000cwp.googlegroups.com>


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'));



| Id | Operation | Name | Starts | E-Rows | A- Rows | A-Time | Buffers |
|   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);

END;
/

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

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US