Bonjour !
Ma requête : (retouchée pour garder l'anonymat )
1 2 3 4 5 6 7
|
SELECT *
FROM MaTable A JOIN MaTable B
ON a.id_compte = b.id_compte
AND a.etat = b.etat
WHERE a.id_compte = (SELECT id_compte FROM TableRef C WHERE nom_compte = 'X')
ORDER BY a.unchamp |
Donne le plan d'exécution suivant :
SELECT STATEMENT 1 142 179K
SORT ORDER BY 1 142 179K
HASH JOIN 1 142 179K
TABLE ACCESS BY INDEX ROWID MaTable 3802 193K 1104
INDEX RANGE SCAN IndexTable1 15209 79
TABLE ACCESS BY INDEX ROWID TableRef 1 33 2
INDEX UNIQUE SCAN IndexRef1 1 1
TABLE ACCESS FULL MaTable 1897K 162M 178K
C'est pas très lisible, mais l'important est de voir que le CBO choisit FTS alors que ça aurait été sympa de lire IndexTable1...
Ce qu'il faut noter, c'est que
(SELECT id_compte FROM TableRef C WHERE nom_compte = 'X')
Renvoie une seule ligne. (y'a un index unique)
Maintenant, si on substitue directement la valeur, ça donne la requête suivante :
1 2 3 4 5 6 7
|
SELECT *
FROM MaTable A JOIN MaTable B
ON a.id_compte = b.id_compte
AND a.etat = b.etat
WHERE a.id_compte = 378
ORDER BY a.unchamp |
Et là, le plan correspondant est :
0 SELECT STATEMENT 1 142 2217
1 SORT ORDER BY 1 142 2217
2 HASH JOIN 1 142 2211
3 TABLE ACCESS BY INDEX ROWID MaTable 3802 193K 1104
4 INDEX RANGE SCAN IndexTable1 15209 79
5 TABLE ACCESS BY INDEX ROWID MaTable 3802 334K 1104
6
INDEX RANGE SCAN IndexTable1 15209 79
=> C'est ce dont on a toujours rêvé !
Est-ce que quelqu'un sait pourquoi ?
A vrai dire, je n'ai pas ce problème en général : je stocke l'identifiant du compte dans une variable. Mais il s'agit là d'une vieille requête...
Ce que j'aimerais, c'est avoir une explication rationnelle du phénomène, ce qui me fournirait des arguments solides pour ensuite convaincre mes amis de faire attention à ce "détail".
PS : comme on a en ce moment des petits problèmes de perf, on a un peu de mal à savoir ce qui est vraiment du à des requêtes pourries, ou a des problèmes de stats, ou des paramètres systèmes, ...
Merci !
Partager