site:enseignement:master:bdr:tmejointure
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
site:enseignement:master:bdr:tmejointure [23/02/2018 16:48] – [Exercice préliminaire] hubert | site:enseignement:master:bdr:tmejointure [14/03/2019 09:51] (Version actuelle) – [Divers] hubert | ||
---|---|---|---|
Ligne 3: | Ligne 3: | ||
====== TME Jointure ====== | ====== TME Jointure ====== | ||
- | ==version | + | /* |
+ | |||
+ | TME pour BDR | ||
+ | |||
+ | Voir l' | ||
+ | |||
+ | |||
+ | */ | ||
+ | |||
+ | ==version | ||
Ligne 13: | Ligne 22: | ||
- | Le TME dure 2 séances. Faire l'ex1 pendant la première séance et l'ex2 pendant la deuxième. L'ex3 est facultatif. | + | Le TME dure 2 séances. |
** Ne pas oublier de consulter les <fc # | ** Ne pas oublier de consulter les <fc # | ||
+ | |||
<showif isloggedin> | <showif isloggedin> | ||
- | + | **<fc # | |
</ | </ | ||
+ | |||
===== Préparation du TME ===== | ===== Préparation du TME ===== | ||
Lire l' | Lire l' | ||
Ligne 29: | Ligne 40: | ||
| emacs tmeJointure.sql & | éditer le fichier à compléter pendant le TME| | | emacs tmeJointure.sql & | éditer le fichier à compléter pendant le TME| | ||
| **Alt-x** my/ | | **Alt-x** my/ | ||
- | | aller sur le paragraphe contenant @base3 et faire Ctrl-C Ctrl-C | créer vos tables J, C, F, les index et les statistiques nécessaires à l' | + | | aller sur le paragraphe contenant @baseJCF |
Les tables d'un club de sport sont : | Les tables d'un club de sport sont : | ||
Ligne 51: | Ligne 62: | ||
| | ||
</ | </ | ||
+ | puis terminer chaque requête par | ||
+ | @p4 | ||
+ | |||
+ | |||
+ | <showif isloggedin> | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
===== Exercice préliminaire | ===== Exercice préliminaire | ||
Combien de n-uplets ont chacune des relations J, C, F et BigJoueur? | Combien de n-uplets ont chacune des relations J, C, F et BigJoueur? | ||
+ | Quel est le coût d' | ||
+ | |||
<code sql> | <code sql> | ||
explain plan for | explain plan for | ||
Ligne 60: | Ligne 83: | ||
</ | </ | ||
- | Quel est le coût d' | ||
Combien de pages ont chacune des relations ? | Combien de pages ont chacune des relations ? | ||
Ligne 66: | Ligne 88: | ||
select table_name, num_rows as cardinalite, | select table_name, num_rows as cardinalite, | ||
from user_tables; | from user_tables; | ||
+ | | ||
+ | select table_name, num_rows as cardinalite, | ||
+ | from all_tables | ||
+ | where table_name=' | ||
</ | </ | ||
Ligne 78: | Ligne 104: | ||
===== Exercice 1 : Jointure entre 2 relations ===== | ===== Exercice 1 : Jointure entre 2 relations ===== | ||
+ | |||
+ | |||
+ | |||
+ | === Question 1) === | ||
+ | |||
+ | /* Jointure par hachage */ | ||
+ | |||
On considère la requête **R1**. | On considère la requête **R1**. | ||
<code sql> | <code sql> | ||
- | | + | explain plan for |
- | | + | select J.licence, C.nom |
- | | + | |
- | | + | |
+ | | ||
+ | @p4 | ||
</ | </ | ||
- | Ecrire en français ce que retourne | + | a) Traduisez |
- | === Question 1) Jointure par hachage === | + | <showif isloggedin> |
- | Afficher | + | <fc # |
- | Dessiner l' | + | </showif> |
- | La jointure par hachage entre deux tables s' | + | b) Affichez le plan **P1** de cette requête. Quel est le nom de l' |
- | | + | |
- | * Etape 2) lire la relation | + | |
- | a) Quel est le coût du plan ? Est-il égal à la somme des coûts du parcours séquentiel de J et C ? | ||
- | Observer que le coût est le même lorsqu' | + | <showif isloggedin> |
- | < | + | |
- | select /*+ ordered */ J.licence, C.nom | + | < |
- | FROM J, C | + | REPONSE: |
- | where J.cnum = C.cnum | + | ---------------------------------------------------------------- |
- | and J.salaire > 10; | + | | Id | Operation |
+ | ---------------------------------------------------------------- | ||
+ | | | ||
+ | |* 1 | HASH JOIN | | ||
+ | | | ||
+ | |* 3 | | ||
+ | ---------------------------------------------------------------- | ||
</ | </ | ||
+ | |||
+ | <fc # | ||
+ | |||
+ | <code ascii> | ||
+ | REPONSE: | ||
+ | 0 | ||
+ | | | ||
+ | 1 | ||
+ | / \ | ||
+ | 2 | ||
+ | 2=Club et proj sur cnum, | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | c) Quelle table est lue en premier, J ou C, pourquoi ? | ||
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | </ | ||
+ | |||
+ | |||
+ | d) Quel est le coût de P1 ? Expliquer comment le coût est calculé en fonction des coûts d' | ||
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | </fc> | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Question 2) === | ||
+ | On considère la requête **R2**. | ||
+ | |||
+ | <showif isloggedin> | ||
+ | < | ||
+ | </ | ||
<code sql> | <code sql> | ||
- | | + | explain plan for |
- | FROM C, J | + | select J.licence, C.nom |
- | | + | from J, C |
- | | + | |
+ | | ||
+ | @p4 | ||
</ | </ | ||
- | b) On remplace la table Joueur par une table plus grande ' | + | a) Afficher et dessiner le plan **P2** de cette requête. |
+ | |||
+ | <showif isloggedin> | ||
+ | |||
+ | < | ||
+ | | Id | Operation | ||
+ | ---------------------------------------------------------------- | ||
+ | | 0 | SELECT STATEMENT | ||
+ | |* 1 | HASH JOIN | ||
+ | |* 2 | TABLE ACCESS FULL| J | 1000 | 14000 | 68 | ||
+ | | 3 | TABLE ACCESS FULL| C | 5000 | 60000 | 7 | ||
+ | ---------------------------------------------------------------- | ||
+ | |||
+ | Predicate Information | ||
+ | ---------------------- | ||
+ | 1 - access(J.CNUM=C.CNUM) | ||
+ | 2 - filter(SALAIRE< | ||
+ | </ | ||
+ | |||
+ | |||
+ | <fc # | ||
+ | Réponse: | ||
+ | |||
+ | 2=joueurs et selection et proj | ||
+ | |||
+ | 3=club et proj | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | b) Quelle table est lue en premier J ou C, pourquoi ? | ||
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | la table Joueur car on ne sélectionne que 1000 Joueurs (sur 50 000 Joueurs) pour la jointure. La taille des 1000 Joueurs (14Ko) est plus petite celle des Clubs (60Ko). | ||
+ | </fc> | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | c) Quel est le coût de **P2** ? | ||
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | le coût de P2 est le même que P1 bien qu'on inverse l' | ||
+ | cout(C) + cout(J) = cout(J) + cout(C) | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | /* question d) spécifique a l'UE BDR */ | ||
+ | |||
+ | d) On remplace la table Joueur par une table plus grande ' | ||
Observer que la jointure dans l' | Observer que la jointure dans l' | ||
Ligne 127: | Ligne 260: | ||
where j.cnum = c.cnum; | where j.cnum = c.cnum; | ||
</ | </ | ||
- | Le coût total de la jointure est la somme du coûts | + | |
+ | Sachant que le coût total de la jointure est la somme du coût de lecture des tables plus le coût de constuire la HashMap (cf. colonne TmpSpc). En déduire le coût de construction de la HashMap. | ||
Enlever maintenant la directive '' | Enlever maintenant la directive '' | ||
Ligne 133: | Ligne 267: | ||
- | c) Observer que lorsque le prédicat de sélection sur le salaire n'est pas très sélectif, le plan est toujours le même. Répondre en remplaçant sal>10 par sal>100, ..., sal> | + | === Question 3) === |
- | d) On étudie maintenant le cas où le prédicat de sélection est très sélectif. Expliquer le plan de la requête | + | On considère |
<code sql> | <code sql> | ||
- | select J.licence, C.nom | + | explain plan for |
- | from C, j | + | |
- | where J.cnum = C.cnum | + | from C, J |
- | and salaire < 10050; | + | where J.cnum = C.cnum |
+ | and C.nom in (' | ||
+ | @p4 | ||
</ | </ | ||
+ | |||
+ | a) Affichez le plan **P3** de cette requête. Quel est le nom de l' | ||
+ | |||
+ | |||
+ | <showif isloggedin> | ||
< | < | ||
- | | Id | Operation | + | | Id | Operation |
- | -------------------------------------------------------------------------------------------- | + | ------------------------------------------------------------------------------ |
- | | 0 | SELECT STATEMENT | + | | 0 | SELECT STATEMENT |
- | |* | + | | |
- | | 2 | TABLE ACCESS | + | | 2 | NESTED LOOPS |
- | |* | + | |* 3 | |
- | | 4 | TABLE ACCESS | + | |* |
- | -------------------------------------------------------------------------------------------- | + | | 5 | TABLE ACCESS |
- | Predicate Information: | + | ------------------------------------------------------------------------------ |
- | 1 - access(" | + | |
- | 3 - access(" | + | Predicate Information : |
+ | | ||
+ | | ||
</ | </ | ||
+ | <fc #008000> | ||
+ | **Reponse: NESTED LOOP | ||
+ | **</ | ||
+ | </ | ||
- | ===Question 2) Jointure par boucles imbriquées avec index sur l' | ||
- | a) Expliquer le plan de la requête | + | |
+ | b) Détailler les étapes | ||
+ | |||
+ | <showif isloggedin> | ||
+ | **<fc # | ||
+ | * Lire la table Club et sélectionner les 2 clubs. Proj sur division et cnum | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | c) Quel est le coût du plan exprimé en fonction du coût pour lire une table, un index et pour lire un nuplet seul. | ||
+ | |||
+ | |||
+ | <showif isloggedin> | ||
+ | **<fc # | ||
+ | * lire la table C: cout(lire C)=7 et sélectionner 2 clubs | ||
+ | * pour chaque | ||
+ | * lire l' | ||
+ | * pour chaque rowid | ||
+ | * lire un joueur: cout(lire nuplet) =1 | ||
+ | |||
+ | cout(P3) = cout(C) + 2 * ( cout(index) + 10 * cout(lire nuplet) ) | ||
+ | = | ||
+ | = 29 | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | === Question 4) === | ||
+ | /* | ||
+ | Jointure par boucles imbriquées avec index sur l' | ||
+ | */ | ||
+ | |||
+ | On considère | ||
<code sql> | <code sql> | ||
- | select J.licence, C.nom | + | explain plan for |
- | from C, j | + | |
- | where J.cnum = C.cnum | + | from C, J |
- | and salaire | + | where J.cnum = C.cnum |
+ | and J.salaire | ||
+ | @p4 | ||
</ | </ | ||
+ | Affichez le plan **P4** de cette requête, expliquer ses étapes et son coût. | ||
+ | |||
+ | |||
+ | <showif isloggedin> | ||
< | < | ||
- | | Id | Operation | + | | Id | Operation |
- | --------------------------------------------------------------------------------------------- | + | ---------------------------------------------------------------------------------- |
- | | 0 | SELECT STATEMENT | + | | 0 | SELECT STATEMENT |
- | | 1 | NESTED LOOPS | + | | 1 | NESTED LOOPS |
- | | 2 | | + | | 2 | |
- | | 3 | TABLE ACCESS BY INDEX ROWID| J | | + | | 3 | TABLE ACCESS BY INDEX ROWID| J | |
- | |* 4 | INDEX RANGE SCAN | I_J_SALAIRE | | + | |* 4 | INDEX RANGE SCAN | I_J_SALAIRE | |
- | |* 5 | INDEX UNIQUE SCAN | I_C_CNUM | + | |* 5 | INDEX UNIQUE SCAN | I_C_CNUM |
- | | 6 | TABLE ACCESS BY INDEX ROWID | C | 1 | | + | | 6 | TABLE ACCESS BY INDEX ROWID | C | 1 | 7 | 1 |
- | --------------------------------------------------------------------------------------------- | + | ---------------------------------------------------------------------------------- |
- | Predicate Information : | + | |
- | 4 - access("SALAIRE"<10006) | + | Predicate Information |
- | | + | --------------------- |
+ | 4 - access(J.SALAIRE> | ||
+ | 5 - access(J.CNUM=C.CNUM) | ||
</ | </ | ||
+ | | ||
+ | <fc #008000> REPONSE:</ | ||
+ | |||
+ | * Accès à l' | ||
+ | * Pour chaque rowid, | ||
+ | * Lire le nuplet correspondant de la table Joueur et projeter sur //cnum// et //licence// | ||
+ | * Le cnum permet d' | ||
+ | * Le rowid permet de lire le nuplet correpondant de la table Club et projeter sur l' | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Exercice 2: Directives USE_NL et USE_HASH pour une jointure ===== | ||
+ | |||
+ | Objectif : comprendre la notion de choix entre 2 plans equivalents, | ||
+ | |||
+ | Etant donné une requête on voudrait construire un autre plan équivalent à celui que propose l' | ||
+ | |||
+ | Pour cela on ajoute une **directive** pour forcer l' | ||
+ | * La directive '' | ||
+ | * La directive '' | ||
+ | |||
+ | Reprendre les requêtes R1 à R4 de l' | ||
+ | |||
+ | === Question 1 === | ||
+ | On veut évaluer R1 avec une jointure par boucles imbriquées | ||
- | b) On veut utiliser l' | ||
<code sql> | <code sql> | ||
| | ||
Ligne 193: | Ligne 415: | ||
and J.salaire > 10; | and J.salaire > 10; | ||
</ | </ | ||
- | Dessiner l' | ||
- | L' | ||
- | Quel est le coût de ce plan ? Expliquer comment il est obtenu à partir | + | Expliquer |
- | des feuilles. | + | |
- | | + | |
+ | |||
+ | === Question 2 === | ||
+ | On veut évaluer R2 avec une jointure par boucles imbriquées | ||
- | Inversement, | ||
<code sql> | <code sql> | ||
- | | + | |
- | FROM C,J | + | from J, C |
where J.cnum = C.cnum | where J.cnum = C.cnum | ||
- | and J.salaire | + | and J.salaire |
</ | </ | ||
- | Dessiner l' | ||
- | c) | + | Expliquer le plan. Vérifier que son coût est supérieur à celui de P2. |
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | < | ||
+ | | Id | Operation | ||
+ | ------------------------------------------------------------------------------ | ||
+ | | 0 | SELECT STATEMENT | ||
+ | | 1 | NESTED LOOPS | ||
+ | | 2 | | ||
+ | |* 3 | TABLE ACCESS FULL | J | 50000 | | ||
+ | |* 4 | INDEX UNIQUE SCAN | I_C_CNUM | 1 | | | ||
+ | | 5 | TABLE ACCESS BY INDEX ROWID| C | 1 | 12 | | ||
+ | ------------------------------------------------------------------------------ | ||
+ | Predicate Information | ||
+ | ----------------------- | ||
+ | 3 - filter(" | ||
+ | 4 - access(" | ||
+ | </code> | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | === Question 3 === | ||
+ | On veut évaluer R3 avec une jointure par hachage | ||
- | Comparer les plans obtenus pour **R2** avec ou sans index | ||
<code sql> | <code sql> | ||
- | select /*+ no_index(J I_J_salaire) */ J.licence, C.nom | + | explain plan for |
- | | + | |
- | | + | from C, J |
- | | + | where J.cnum = C.cnum |
+ | and C.nom in (' | ||
+ | @p4 | ||
</ | </ | ||
- | ===== Exercice 2. Jointure entre 3 relations | + | Expliquer le plan. Vérifier que son coût est supérieur à celui de P3 (de l' |
- | Soit la requête R3 : | + | |
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | < | ||
+ | | Id | Operation | ||
+ | ---------------------------------------------------------------- | ||
+ | | 0 | SELECT STATEMENT | ||
+ | |* 1 | HASH JOIN | ||
+ | |* 2 | TABLE ACCESS FULL| C | 2 | 30 | 7 | ||
+ | | 3 | TABLE ACCESS FULL| J | 50000 | | ||
+ | ---------------------------------------------------------------- | ||
+ | Predicate Information | ||
+ | ---------------------- | ||
+ | 1 - access(" | ||
+ | 2 - filter(" | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | === Question 4 === | ||
+ | On veut évaluer R4 avec une jointure par hachage | ||
<code sql> | <code sql> | ||
- | select /*+ use_nl(J,C,F) */ c.nom, f.budget | + | explain plan for |
+ | | ||
+ | from C, J | ||
+ | where J.cnum = C.cnum | ||
+ | and J.salaire between 10000 and 10001; | ||
+ | @p4 | ||
+ | </ | ||
+ | |||
+ | Expliquer le plan. Vérifier que son coût est supérieur à celui de P4. | ||
+ | |||
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | < | ||
+ | | Id | Operation | ||
+ | --------------------------------------------------------------------------------- | ||
+ | | 0 | SELECT STATEMENT | ||
+ | |* 1 | HASH JOIN | ||
+ | | 2 | TABLE ACCESS BY INDEX ROWID| J | 3 | 42 | 5 | ||
+ | |* 3 | INDEX RANGE SCAN | I_J_SALAIRE | 3 | | 2 | ||
+ | | 4 | TABLE ACCESS FULL | C | ||
+ | --------------------------------------------------------------------------------- | ||
+ | Predicate Information | ||
+ | --------------------- | ||
+ | 1 - access(" | ||
+ | 3 - access(" | ||
+ | </code> | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Exercice 3. ORDRE des jointures entre 3 relations ===== | ||
+ | Soit la requête R5 : | ||
+ | <code sql> | ||
+ | explain plan for | ||
+ | | ||
from J, C, F | from J, C, F | ||
- | WHERE J.cnum = C.cnum | + | where J.cnum = C.cnum |
and c.division=1 and J.salaire > 59000 | and c.division=1 and J.salaire > 59000 | ||
and j.sport = ' | and j.sport = ' | ||
+ | @p4 | ||
</ | </ | ||
- | |||
- | La directive USE_NL permet d' | ||
On sait (cf. cours) qu'il y a 6 ordres de jointure possibles pour évaluer cette requête. | On sait (cf. cours) qu'il y a 6 ordres de jointure possibles pour évaluer cette requête. | ||
+ | La directive '' | ||
+ | Par exemple, l' | ||
+ | <code sql> | ||
+ | explain plan for | ||
+ | select /*+ ORDERED */ C.nom, F.budget | ||
+ | from C, F, J | ||
+ | where J.cnum = C.cnum and C.cnum = F.cnum and J.cnum = F.cnum | ||
+ | and C.division=1 and J.salaire > 59000 | ||
+ | and J.sport = ' | ||
+ | @p4 | ||
+ | </ | ||
- | a) Compléter | + | a) Avec la directive '' |
- | ^ ordre ^ coût ^ | + | Expliquer chaque plan et compléter le tableau |
- | | J, C, F | 88 | | + | |
- | | ... | ... | | + | |
- | | F, J, C | ... | | + | |
- | D' | + | ^ |
+ | | C, F, J | HASH | HASH | | ||
+ | | C, J, F | | | ||
+ | | F, C, J | | | ||
+ | | F, J, C | | | ||
+ | | J, C, F | | | ||
+ | | J, F, C | | | ||
- | Rmq: veillez à bien expliciter les 3 prédicats de jointure dans la clause where. | ||
- | /** ANCIENNE REMARQUE ENLEVEE | ||
- | Pourquoi l' | ||
- | Remplacer le prédicat de jointure | ||
- | */ | ||
- | b) Modifier R3 en une requête R4 de jointure et de sélection avec index : modifier seulement la valeur du salaire (59000) pour que le plan obtenu choisisse l' | + | <showif isloggedin> |
+ | <fc # | ||
- | c) On force les index sur les attributs | + | <fc # |
+ | |||
+ | < | ||
+ | ----------------------------------------------------------------- | ||
+ | | Id | Operation | ||
+ | ----------------------------------------------------------------- | ||
+ | | 0 | SELECT STATEMENT | ||
+ | |* 1 | HASH JOIN | | 1 | 40 | 82 | ||
+ | |* 2 | TABLE ACCESS FULL | J | 5 | 90 | 68 | ||
+ | |* 3 | HASH JOIN | | ||
+ | |* 4 | TABLE ACCESS FULL| C | 2500 | 37500 | 7 | ||
+ | | 5 | TABLE ACCESS FULL| F | 5000 | 35000 | 5 | ||
+ | ----------------------------------------------------------------- | ||
+ | </code> | ||
+ | |||
+ | <fc # | ||
+ | < | ||
+ | ------------------------------------------------------------------------------ | ||
+ | | Id | Operation | ||
+ | ------------------------------------------------------------------------------ | ||
+ | | 0 | SELECT STATEMENT | ||
+ | | 1 | NESTED LOOPS | ||
+ | | 2 | | ||
+ | |* 3 | HASH JOIN | ||
+ | |* 4 | TABLE ACCESS FULL | C | 2500 | 37500 | | ||
+ | |* 5 | TABLE ACCESS FULL | ||
+ | |* 6 | INDEX UNIQUE SCAN | I_F_CNUM | 1 | | | ||
+ | | 7 | TABLE ACCESS BY INDEX ROWID| F | 1 | 7 | | ||
+ | ------------------------------------------------------------------------------ | ||
+ | </code> | ||
+ | |||
+ | <fc # | ||
+ | < | ||
+ | ----------------------------------------------------------------- | ||
+ | | Id | Operation | ||
+ | ----------------------------------------------------------------- | ||
+ | | 0 | SELECT STATEMENT | ||
+ | |* 1 | HASH JOIN | | 1 | 40 | 82 | ||
+ | |* 2 | TABLE ACCESS FULL | J | 5 | 90 | 68 | ||
+ | |* 3 | HASH JOIN | | ||
+ | | 4 | TABLE ACCESS FULL| F | 5000 | 35000 | 5 | ||
+ | |* 5 | TABLE ACCESS FULL| C | 2500 | 37500 | 7 | ||
+ | ----------------------------------------------------------------- | ||
+ | </code> | ||
+ | |||
+ | <fc # | ||
+ | < | ||
+ | ------------------------------------------------------------------------------ | ||
+ | | Id | Operation | ||
+ | ------------------------------------------------------------------------------ | ||
+ | | 0 | SELECT STATEMENT | ||
+ | | 1 | NESTED LOOPS | ||
+ | | 2 | | ||
+ | |* 3 | HASH JOIN | ||
+ | | 4 | TABLE ACCESS FULL | F | 5000 | 35000 | | ||
+ | |* 5 | TABLE ACCESS FULL | J | 5 | 90 | 68 | ||
+ | |* 6 | INDEX UNIQUE SCAN | I_C_CNUM | 1 | | | ||
+ | |* 7 | TABLE ACCESS BY INDEX ROWID| | ||
+ | ------------------------------------------------------------------------------ | ||
+ | </code> | ||
+ | |||
+ | <fc # | ||
+ | < | ||
+ | -------------------------------------------------------------------------------- | ||
+ | | Id | Operation | ||
+ | -------------------------------------------------------------------------------- | ||
+ | | 0 | SELECT STATEMENT | ||
+ | | 1 | NESTED LOOPS | ||
+ | | 2 | | ||
+ | | 3 | NESTED LOOPS | ||
+ | |* 4 | TABLE ACCESS FULL | J | 5 | 90 | 68 | ||
+ | |* 5 | TABLE ACCESS BY INDEX ROWID| C | 1 | 15 | 1 | ||
+ | |* 6 | INDEX UNIQUE SCAN | I_C_CNUM | 1 | | 0 | ||
+ | |* 7 | INDEX UNIQUE SCAN | I_F_CNUM | 1 | | 0 | ||
+ | | 8 | TABLE ACCESS BY INDEX ROWID | F | 1 | 7 | 1 | ||
+ | -------------------------------------------------------------------------------- | ||
+ | </ | ||
+ | <fc # | ||
+ | < | ||
+ | -------------------------------------------------------------------------------- | ||
+ | | Id | Operation | ||
+ | -------------------------------------------------------------------------------- | ||
+ | | 0 | SELECT STATEMENT | ||
+ | | 1 | NESTED LOOPS | ||
+ | | 2 | | ||
+ | | 3 | NESTED LOOPS | ||
+ | |* 4 | TABLE ACCESS FULL | J | 5 | 90 | 68 | ||
+ | | 5 | TABLE ACCESS BY INDEX ROWID| F | 1 | 7 | 1 | ||
+ | |* 6 | INDEX UNIQUE SCAN | I_F_CNUM | 1 | | 0 | ||
+ | |* 7 | INDEX UNIQUE SCAN | I_C_CNUM | 1 | | 0 | ||
+ | |* 8 | TABLE ACCESS BY INDEX ROWID | C | 1 | 15 | 1 | ||
+ | -------------------------------------------------------------------------------- | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | b) D' | ||
+ | |||
+ | |||
+ | c) Proposer un plan pour R5 qui utilise l' | ||
<code sql> | <code sql> | ||
- | | + | |
from J, C, F | from J, C, F | ||
- | where J.cnum = C.cnum and C.cnum = F.cnum | + | where J.cnum = C.cnum and C.cnum = F.cnum and J.cnum = F.cnum |
and c.division=1 and J.salaire > 59000 | and c.division=1 and J.salaire > 59000 | ||
and j.sport = ' | and j.sport = ' | ||
</ | </ | ||
- | Dessiner le plan obtenu. | + | Dessiner le plan obtenu. |
+ | |||
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | < | ||
+ | ----------------------------------------------------------------------------------- | ||
+ | | Id | Operation | ||
+ | ----------------------------------------------------------------------------------- | ||
+ | | 0 | SELECT STATEMENT | ||
+ | | 1 | NESTED LOOPS | ||
+ | | 2 | | ||
+ | | 3 | NESTED LOOPS | ||
+ | |* 4 | TABLE ACCESS BY INDEX ROWID| J | ||
+ | |* 5 | INDEX RANGE SCAN | I_J_SALAIRE | 997 | | ||
+ | | 6 | TABLE ACCESS BY INDEX ROWID| F | ||
+ | |* 7 | INDEX UNIQUE SCAN | I_F_CNUM | ||
+ | |* 8 | INDEX UNIQUE SCAN | I_C_CNUM | ||
+ | |* 9 | TABLE ACCESS BY INDEX ROWID | C | ||
+ | ----------------------------------------------------------------------------------- | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | d) Proposer un plan pour R5 qui utilise | ||
- | ===== Exercice 3. Forme des arbres de jointure (FACULTATIF) ===== | ||
- | a) Soit R4: | ||
<code sql> | <code sql> | ||
- | | + | explain plan for |
- | | + | |
- | | + | from J, C, F |
+ | where J.cnum = C.cnum and C.cnum = F.cnum | ||
+ | and C.division=1 and J.salaire > 59000 | ||
+ | and J.sport = ' | ||
+ | @p4 | ||
</ | </ | ||
- | Dessiner | + | Dessiner |
+ | |||
+ | <showif isloggedin> | ||
+ | <fc # | ||
+ | < | ||
+ | ------------------------------------------------------------------------------------ | ||
+ | | Id | Operation | ||
+ | ------------------------------------------------------------------------------------ | ||
+ | | 0 | SELECT STATEMENT | ||
+ | | 1 | NESTED LOOPS | ||
+ | | 2 | | ||
+ | |* 3 | HASH JOIN | ||
+ | |* 4 | TABLE ACCESS FULL | ||
+ | | 5 | TABLE ACCESS BY INDEX ROWID| C | 2500 | 37500 | 23 (0)| | ||
+ | |* 6 | INDEX RANGE SCAN | I_C_DIVISION | 2500 | | ||
+ | |* 7 | INDEX UNIQUE SCAN | I_F_CNUM | ||
+ | | 8 | TABLE ACCESS BY INDEX ROWID | F | 1 | 7 | | ||
+ | ------------------------------------------------------------------------------------ | ||
+ | </ | ||
+ | </ | ||
+ | |||
- | b) Compléter la clause WHERE de R4 pour obtenir | ||
- | C,F,J | ||
- | c) Ajouter une 4ème table **Z** et proposer une requête de jointure entre les 4 tables de telle sorte que | ||
- | le plan de moindre coût ne soit pas un arbre linéaire à gauche. C'est à dire que le coût de P1 soit inférieur à P2 avec : | ||
- | * P1 = (J join C) join (F join Z) | ||
- | * P2 = ( (J join C) join F) join Z ou tout autre arbre linéaire à gauche. | ||
Ligne 316: | Ligne 794: | ||
+ | [[http:// | ||
- | Aller vers [[site: | + | Aller vers [[site: |
site/enseignement/master/bdr/tmejointure.1519400915.txt.gz · Dernière modification : de hubert