Bonsoir,
je fais des tests simples pour en apprendre plus sur plans d'exécution/optim,etc... Et je tombes sur un cas qui me semble curieux (mais je ne suis pas sûr de ma compréhension des plans d'exécution suivants) :
Je possède deux tables de tests :
- modele (id_modele varchar2(20), libelle_modele(varchar2(20)))
=> dont le champ id_modele varchar2(20) est la PK
- vehicule (id_vehicule number(3), id_modele (varchar2(20), libelle_vehicule(varchar2(20))))
=> qui possede une fk sur la table modele via le champ id_modele
Un index est donc créé pour la PK de la table modele et autre pour la FK de la table vehicule... (j'utilise une clé varchar2 pour simuler une clé naturelle)
J'insere dans ma table "modele" 23 modeles fictifs de véhicules.
J'insère dans ma table "vehicule" 284 véhicules fictifs qui pointent aléatoirement sur un des 30 modèles créés précédemment.
Je lance la commande suivante dans l'espoir de collecter des stats fraîches :
Je fais une jointure simple de ce type :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 begin DBMS_STATS.GATHER_DATABASE_STATS(); end; /
Le plan pour cette requête donne :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 select m.libelle_modele,v.id_modele from vehicule v, modele m where m.id_modele = v.id_modele;
Je me dis que l'optimiseur à jugé qu'il était inutile d'utiliser l'index et qu'un acces full scan était le plus optimal...
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
16
17
18
19
20
21
22
23
24
25
26
27
28
29 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time -------------------------------------------------------------------------- | 0 | SELECT STATE.. | | 22 | 2750 | 7 (15)| 00:0| |* 1 | HASH JOIN | | 22 | 2750 | 7 (15)| 00: | | 2 | TABLE ACCESS FULL| MODELE | 23| 782 | 3 (0)| 00:0 | 3 | TABLE ACCESS FULL| VEHICULE | 284 | 25844 | 3 (0)| 00:0 -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("M"."ID_MODELE"="V"."ID_MODELE") Statistiques ---------------------------------------------------------- 8 recursive calls 0 db block gets 18 consistent gets 0 physical reads 0 redo size 5080 bytes sent via SQL*Net to client 396 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 23 rows processed
(Mais à quoi correspond l'utilisation du hash join dans ce cas ?)
Je change la requête ainsi :
et maintenant le résultat devient :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 select v.id_vehicule, (select m.libelle_modele from modele m where m.id_modele = v.id_modele) from vehicule v;
Sauriez-vous répondre à ces questions :
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
16
17
18
19
20
21
22
23
24
25
26
27 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time --------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 284 | 25844 | 3 (0)| 00:00 |* 1 | INDEX RANGE SCAN | FK_ID_MODELE | 1 | 20 | 1 (0)| | 2 | TABLE ACCESS FULL| VEHICULE | 284 | 25844 | 3 (0)| 00:00 -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("M"."ID_MODELE"=:B1) Statistiques ---------------------------------------------------------- 8 recursive calls 0 db block gets 18 consistent gets 0 physical reads 0 redo size 5080 bytes sent via SQL*Net to client 396 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 23 rows processed
Pourquoi le côut est-il moins élevé dans ce cas (divisé par 2)?
Pourquoi l'optimiseur n'a-t-il pas utilisé l'index via un range scan dans la première requête?
Merci d'avance pour votre aide,
Lek.
Partager