Bonjour à tous.

Je débute l'étude du plan d'exécution, et j'avoue qu'il y a une chose qui m'échappe dans ce qui suit.
Le problème : j'ai une grosse table d'environ 80 millions de ligne. Les requêtes qui l'attaquent filtrent une de ses colonnes d'après un ensemble de valeur dans un IN. Cette colonne peut prendre environ 400 valeurs différentes.
Voici une requête que l'on pourraît passer sur cette table, et son plan d'exécution :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
SELECT Id, colonne_filtree, autre_colonne
    FROM grande_table
    WHERE colonne_filtree IN ('100', '102', '200', '202')
      AND autre_colonne = '200612'      
 
 Plan d'exécution
----------------------------------------------------------     
 0      SELECT STATEMENT Optimizer=CHOOSE (Cost=11525 Card=12779 Bytes=306696)
 1    0   INLIST ITERATOR 
 2    1     TABLE ACCESS (BY INDEX ROWID) OF 'GRANGE_TABLE' (Cost=11525Card=12779 Bytes=306696)
 3    2       INDEX (RANGE SCAN) OF 'IDX_GRANGE_TABLE' (NON-UNIQUE) (Cost=52 Card=12779)
La requête est longue vu que pour chaque valeur dans le IN, on scanne l'index puis la table (enfin, d'après ce que je comprends de ce plan...).

J'ai donc voulu utiliser une autre table qui contient les 400 codes présents dans colonne_filtree pour que l'itération se fasse sur cette petite table avant d'opérer une jointure sur ma grande table.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT Id, colonne_filtree, autre_colonne
    FROM petite_table, grande_table
    WHERE code = colonne_filtree
      AND code IN ('100', '102', '200', '202')
      AND autre_colonne = '200612'
 
Plan d'exécution
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=326 Card=133 Bytes=3724)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'GRANDE_TABLE' (Cost=81 Card=33 Bytes=792)
   2    1     NESTED LOOPS (Cost=326 Card=133 Bytes=3724)
   3    2       INLIST ITERATOR
   4    3         INDEX (RANGE SCAN) OF 'IDX_PETITE_TABLE' (UNIQUE) (Cost=2 Card=4 Bytes=16)
   5    2       INLIST ITERATOR
   6    5         INDEX (RANGE SCAN) OF 'IDX_GRANDE_TABLE' (NON-UNIQUE) (Cost=51 Card=33)
Donc si je comprends bien, le INLIST ITERATOR va bien chercher dans ma petite_table (plutôt dans son index), mais aussi dans celui de ma grande_table ! Certe, cette fois-ci, la table elle-même n'est scannée qu'en fin de traitement, mais son index reste dans l'itérateur...
C'est normal ??
Est-ce que je comprends tout de travers ??