[Explain plan]Fonctionnement du INLIST ITERATOR.
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:
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:
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 ??