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: What's fast way to get total of records

Re: What's fast way to get total of records

From: Richard Foote <richard.foote_at_bigpond.com>
Date: Fri, 26 Sep 2003 14:47:05 GMT
Message-ID: <JjYcb.124396$bo1.38791@news-server.bigpond.net.au>

"Daniel Roy" <danielroy10junk_at_hotmail.com> wrote in message news:3722db.0309260603.17dd078a_at_posting.google.com...
> > I rather doubt there is one for Oracle. If there is a primary key or
> > otherwise not null index, it could be used in the count(*) and make
> > it faster than a table scan.
>
> I created a test case to see if Oracle would use an index to count the
> number of records, and it seems that we need to give a hint, otherwise
> it just uses a FTS. Note that I use CBO on 9.2:
>
> Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
> With the Partitioning, OLAP and Oracle Data Mining options
> JServer Release 9.2.0.1.0 - Production
>
> SQL> create table tst (x char(1));
>
> Table created.
>
> Elapsed: 00:00:01.02
> SQL> set timing off
> SQL> truncate table plan_table;
>
> Table truncated.
>
> SQL> explain plan for
> 2 select count(*) from tst;
>
> Explained.
>
> SQL> select * from table(dbms_xplan.display);
>
> PLAN_TABLE_OUTPUT
> --------------------------------------------------------------------------



>
> -------------------------------------------------------------------------
> | Id | Operation | Name | Rows | Bytes | Cost
> (%CPU)|
> -------------------------------------------------------------------------
> | 0 | SELECT STATEMENT | | 1 | | 3
 (34)|
> | 1 | SORT AGGREGATE | | 1 | |
> |
> | 2 | TABLE ACCESS FULL | TST | 41 | | 3
> (34)|
> -------------------------------------------------------------------------
>
> 8 rows selected.
>
> SQL> alter table tst add primary key(x);
>
> Table altered.
>
> SQL> truncate table plan_table;
>
> Table truncated.
>
> SQL> explain plan for
> 2 select count(*) from tst;
>
> Explained.
>
> SQL> select * from table(dbms_xplan.display);
>
> PLAN_TABLE_OUTPUT
> --------------------------------------------------------------------------


>
> -------------------------------------------------------------------------
> | Id | Operation | Name | Rows | Bytes | Cost
> (%CPU)|
> -------------------------------------------------------------------------
> | 0 | SELECT STATEMENT | | 1 | | 3
 (34)|
> | 1 | SORT AGGREGATE | | 1 | |
> |
> | 2 | TABLE ACCESS FULL | TST | 41 | | 3
> (34)|
> -------------------------------------------------------------------------
>
> 8 rows selected.
>
> SQL> truncate table plan_table;
>
> Table truncated.
>
> SQL> select index_name from user_indexes where table_name = 'TST';
>
> INDEX_NAME
> ------------------------------
> SYS_C003106
>
> SQL> explain plan for
> 2 select /*+ index(tst, SYS_C003106) */ count(*) from tst;
>
> Explained.
>
> SQL> select * from table(dbms_xplan.display);
>
> PLAN_TABLE_OUTPUT
> --------------------------------------------------------------------------


>
> --------------------------------------------------------------------------
> | Id | Operation | Name | Rows | Bytes | Cost
> (%CPU)|
> --------------------------------------------------------------------------
> | 0 | SELECT STATEMENT | | 1 | | 27
 (4)|
> | 1 | SORT AGGREGATE | | 1 | |
> |
> | 2 | INDEX FULL SCAN | SYS_C003106 | 41 | | 27
> (4)|
> --------------------------------------------------------------------------
>
> 8 rows selected.
>
> Therefore, if you have an index on non-null field (such as a one
> associated to a PK), it's probably faster to include it in a hint as I
> did, in order to replace the FTS by an index full scan. Note also that
> presumably the "sort aggregate" step would be avoided if the index is
> defined as unique (I didn't test that).
>

Hi Daniel,

Perhaps the following modifications to your test case might prove constructive:

  1. Create a table that has a decent number of rows. The CBO is going to look favourably to FTS of minute tables.
  2. Analyze the tables to give the CBO half a decent chance

SQL> create table bowie as select * from dba_source;

Table created.

SQL> alter table bowie modify (owner constraint bowie_nn not null);

Table altered.

SQL> create index bowie_idx on bowie(owner);

Index created.

SQL> analyze table bowie compute statistics;

Table analyzed.

SQL> set autotrace traceonly
SQL> select count(*) from bowie;

Execution Plan


   0 SELECT STATEMENT Optimizer=CHOOSE (Cost=34 Card=1)    1 0 SORT (AGGREGATE)

   2    1     INDEX (FAST FULL SCAN) OF 'BOWIE_IDX' (NON-UNIQUE) (Cost
          =34 Card=145249)

And not a hint in site ....

Beware of assuming action A caused result B. It could will be that unknown or unsuspecting action or effect C, D, E, ......

Generally, the CBO will choose the cheapest path, give a chance (be it FTS, Index Scan, whatever )

Cheers

Richard Received on Fri Sep 26 2003 - 09:47:05 CDT

Original text of this message

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