| Oracle FAQ | Your Portal to the Oracle Knowledge Grid | |
Home -> Community -> Usenet -> c.d.o.server -> Re: Most selective columns first (was: Re: Key Compression vs. Selectivity)
Robert Klemme a écrit :
> On 18.12.2006 07:35, hasta_l3_at_hotmail.com wrote:
> > Jonathan Lewis a écrit :
> >> "Robert Klemme" <shortcutter_at_googlemail.com> wrote in message
> >>> The general rule of thumb for indexing is to put the most selective
> >>> columns first in order to foster fast lookups. (Of course there are
> >>> other considerations involved, which single index covers most queries
> >>> etc.)
> >
> > Jonathan and Robert....
> >
> > Why would the rule of thumb "put the most selective column first"
> > be a good one to any degree ?
> >
> > (let's assume that permutations of index columns don't
> > impact the number of queries covered)
>
> Because - that's at least the theory - more selective columns cut down
> the number of rows faster than less selective columns. Assume you have
> a people table with gender and year of birth. Gender has low
> selectivity, so if you query by gender="male" and year="1984" with the
> gender column first in the index, the first index seek step just cuts
> the number of records (and thus key entries) in half (roughly) while
> selection on year will select a much smaller portion of the data
> (assuming not every person in that table was born in 1984).
Yes, Robert.
However, as pointed out by Tom Kyte, a quick test I just performed does not seem to confirm the theory.
I dont claim to understand why....
Regards
create table test(Gender char(1), DateOfBirth DATE, filler INTEGER);
begin
for filler in 1..100000 loop
for year in 1920..2006 loop
insert into test(Gender, DateOfBirth, filler) values('M',
to_date(year, 'yyyy'), filler);
insert into test(Gender, DateOfBirth, filler) values('F', to_date(year, 'yyyy'), filler);
end loop;
end loop;
end;
commit;
create index idx_gd on test(Gender, DateOfBirth);
create index idx_dg on test(DateOfBirth, Gender);
---
SQL> alter system flush buffer_cache;
Système modifié.
SQL> select /*+INDEX(test idx_gd) */ count(*) from test where gender =
'M' and DateOfBirth = to_date
(1980, 'yyyy');
COUNT(*)
----------
100000
Plan d'exécution
----------------------------------------------------------
Plan hash value: 2862478417
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 12 | 294 (2)|
00:00:04 |
| 1 | SORT AGGREGATE | | 1 | 12 | |
|
|* 2 | INDEX RANGE SCAN| IDX_GD | 89592 | 1049K| 294 (2)|
00:00:04 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("GENDER"='M' AND "DATEOFBIRTH"=TO_DATE('1980','yyyy'))
Note
-----
- dynamic sampling used for this statement
Statistiques
----------------------------------------------------------
5 recursive calls
0 db block gets
370 consistent gets
641 physical reads
0 redo size
419 bytes sent via SQL*Net to client
381 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> alter system flush buffer_cache;
Système modifié.
SQL> select /*+INDEX(test idx_dg) */ count(*) from test where gender =
'M' and DateOfBirth = to_date
(1980, 'yyyy');
COUNT(*)
----------
100000
Plan d'exécution
----------------------------------------------------------
Plan hash value: 366629259
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 12 | 294 (2)|
00:00:04 |
| 1 | SORT AGGREGATE | | 1 | 12 | |
|
|* 2 | INDEX RANGE SCAN| IDX_DG | 89592 | 1049K| 294 (2)|
00:00:04 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DATEOFBIRTH"=TO_DATE('1980','yyyy') AND "GENDER"='M')
Note
-----
- dynamic sampling used for this statement
Statistiques
----------------------------------------------------------
4 recursive calls
0 db block gets
370 consistent gets
641 physical reads
0 redo size
419 bytes sent via SQL*Net to client
381 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
Received on Mon Dec 18 2006 - 04:55:55 CST
![]() |
![]() |