Quote:
Originally posted by jimpen
If you have a primary key or even if you don't, but have a column is always filled, the more efficient way is Select Count(<PKFieldName>) as opposed to the wildcard.
That way it only looks at one column, and not a whole table.
|
Sorry, not quite:
SQL> create table t (
2 id int primary key,
3 y char (200) default 'x'
4 );
Table created.
SQL> insert into t (id) select rownum from all_objects where rownum < 1000;
999 rows created.
Here i've inserted about 200k worth of data - to avoid Oracle performing the 'small table less than 5 blocks' optimization, and making it consider the index.
SQL> commit;
Commit complete.
Now we use the RBO:
SQL> set autotrace on
SQL> select count(*) from t;
COUNT(*)
----------
999
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T'
SQL> select count(id) from t;
COUNT(ID)
----------
999
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T'
Same plan using either count(*) or count(id).
Now we use the CBO:
SQL> exec dbms_stats.gather_table_stats (ownname=>user,tabname=>'T',cascade=>true);
PL/SQL procedure successfully completed.
SQL> select count(*) from t;
COUNT(*)
----------
999
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1)
1 0 SORT (AGGREGATE)
2 1 INDEX (FAST FULL SCAN) OF 'SYS_C0011518' (UNIQUE) (Cost= 1 Card=999)
SQL> select count(id) from t;
COUNT(ID)
----------
999
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1)
1 0 SORT (AGGREGATE)
2 1 INDEX (FAST FULL SCAN) OF 'SYS_C0011518' (UNIQUE) (Cost= 1 Card=999)
Again, same plan using either count(*) or count(id).
Note that it uses the index only (not the table) even if using the wildcard.
For completeness, let's use the count(1) trick someone uses:
SQL> select count(1) from t;
COUNT(1)
----------
999
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1)
1 0 SORT (AGGREGATE)
2 1 INDEX (FAST FULL SCAN) OF 'SYS_C0011518' (UNIQUE) (Cost= 1 Card=999)
Same plan again.
Alberto