INSIA Bases de données SIGL 3 Optimisation – 3 : la
Transcription
INSIA Bases de données SIGL 3 Optimisation – 3 : la
INSIA Bases de données SIGL 3 Optimisation – 3 : la commannde Explain Bertrand LIAUDET SOMMAIRE SOMMAIRE 1 LE CALCUL DE COUT ET LA COMMANDE EXPLAIN 1. Principe du passage du SQL au langage impératif. La jointure indexée Distinction entre jointure indexée unique (EQ_REF) et jointure indexé multiple (REF) 3 Pourquoi choisir une solution plutôt qu’une autre ? Calcul de coût et arbre algébrique indexé Les restrictions dans les arbres algébriques indexés 2. Présentation générale de la commande EXPLAIN Présentation de l’explain de MySQL (explain plan sous ORACLE) Les différents types d’index de l’explain Tous les Attributs de l’explain 3. Etudes de cas 1 : EXPLAIN de requêtes sans tables 2 : EXPLAIN de requêtes mono-tables sans fonction de groupe 3 : EXPLAIN de requêtes mono-tables avec distinct, fonction de groupe ou order by 4 : EXPLAIN de jointure naturelle - 1 5 : EXPLAIN de jointure naturelle - 2 6 : EXPLAIN de jointure artificielle 7 : EXPLAIN de select imbriqué 4. Autour de l’EXPLAIN ANALYZE TABLE nomTable SHOW INDEX RAPPELS de la syntaxe de création des index STRAIGHT_JOIN FORCE INDEX et IGNORE INDEX 3 3 3 INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 1/36 - Bertrand LIAUDET 5 6 6 9 9 9 10 11 11 13 15 17 21 23 26 30 30 30 31 32 32 FORCER LE TRI OPTIMIZE TABLE nomTable SHOW TABLE STATUS FROM nomBD BENCHMARK TP Utilisation de l’EXPLAIN Première partie Deuxième partie : Faire l’arbre algébrique avec coût de tous les EXPLAIN Troisième partie : Faire l’arbre algébrique avec coût de tous les EXPLAIN Quatrième partie : Faire l’arbre algébrique avec coût de tous les EXPLAIN Première édition : mars 2008 Deuxième édition : septembre 2008 INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 2/36 - Bertrand LIAUDET 33 33 34 34 35 35 35 35 35 36 LE CALCUL DE COUT ET LA COMMANDE EXPLAIN 1. Principe du passage du SQL au langage impératif. Le passage du SQL au langage impératif va essnetiellement mixer l’analyse de l’arbre algébrique et les possibilités offertes par les index et l’algorithmique des index. Pour cela, on va définir la jointure indexée qui est une opération d’algorithmique impérative. La jointure indexée - opération d’algorithmique impérative - non commutative - Principe : on part d’une première table que l’on parcourt entièrement et, pour chaque tuple, on fait la jointure avec la deuxième table en utilisant un index de cette deuxième table ce qui permet un accès direct. Exemple Si on veut tous les abus avec le nom des buveurs, on fait une jointure indexé entre ABUSER et les BUVEURS qui consistera à récupérer, pour chaque tuple de ABUSER, le tuple de BUVEURS correspondant. Le lien se faisant par NB qui est un attribut indexé de BUVEURS, la recherche sera une recherche dichotomique. Le nombre d’accès disques pour récupérer les buveurs des abus sera celui du nombre de tuples dans la table ABUSER. On a alors une jointure indexée unique. Distinction entre jointure indexée unique (EQ_REF) et jointure indexé multiple (REF) Dans l’exemple précédent, on a une jointure indexée unique (EQ_REF dans le vocabulaire de l’EXPLAIN MySQL) car l’index utilisé est un index unique (index de la clé primaire des BUVEURS : NB. Une jointure indexée multiple (REF dans le vocabulaire de l’EXPLAIN MySQL) est une jointure indexée qui utilise un index multiple (non unique). Exemple On veut maintenant tous les abus leur date et avec le nom des buveurs et le cru du vin. Réponse SQL Select a.nb, b.nom, a .date, v.nv, v.cru from abuser a, vins v, buveurs b where a.nv=v.nv and a.nb=b.nb ; Première solution INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 3/36 - Bertrand LIAUDET On peut commencer par faire une jointure indexée unique entre ABUSER et BUVEURS puis une autre jointure indexée unique entre ABUSER et VINS. Graphe des jointures indexés : A date(S) 1 1 B NB(S) V nom(S) La flèche en pointillé avec un 1 : NV (S) Cru (S) 1 : signifie qu’on a une jointure indexée unique. Arbre algébrique indexé : Ce type d’arbre est toujours linéaire et utilise des jointures indexées uniques et multiples. Il n’est pas nécessaire de préciser les projections. Par contre on précisera les restrictions spécifiques s’il y a lieu. J( ; NV) A J( ;.NB) Eq_ref B Eq_ref V Le caractère non commutatif de la jointure et son type unique ou multiple est précisé sur la branche de la table contenant l’index. EQ_REF pour unique, REF pour multiple. L’arbre se lit ainsi : on part des ABUSER, on y associe les BUVEURS par jointure indexées unique puis les VINS par jointure indexées unique. Deuxième solution On peut aussi commencer par une jointure indexée multiple entre BUVEURS et ABUSER (car le NB de ABUSER est indexé en tant que clé primaire) qui sera suivi par une jointure indexée unique entre ABUSER et VINS. A noter qu’on ne pourrait pas faire une jointure indexée multiple entre BUVEURS et VINS car le NV de ABUSER n’est pas indexé. La jointure indexée multiple consiste à partir de la table des BUVEURS, puis à récupérer, pour chaque tuple de BUVEURS, les tuples de ABUSER correspondant. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 4/36 - Bertrand LIAUDET Graphe des jointures indexés : A N date(S) 1 B NB(S) V nom(S) La flèche en pointillé avec un 1 : La flèche en pointillé avec un N : NV (S) Cru (S) 1 : signifie qu’on a une jointure indexée unique. N : signifie qu’on a une jointure indexée multiple. Arbre algébrique indexé : Ce type d’arbre est toujours linéaire et utilise des jointures indexées uniques et multiples. Il n’est pas nécessaire de préciser les projections. Par contre on précisera les restrictions spécifiques s’il y a lieu. J( ; NV) J( ;.NB) Ref A Eq_ref V B Le caractère non commutatif de la jointure et son type unique ou multiple est précisé sur la branche de la table contenant l’index. EQ_REF pour unique, REF pour multiple. L’arbre se lit ainsi : on part des BUVEURS, on y associe les ASSOCIER par jointure indexée multiple puis les VINS par jointure indexée unique. Pourquoi choisir une solution plutôt qu’une autre ? C’est l’optimiseur qui tranche, en fonction des index, des statistiques de la métabase et de son heuristique. Le principe général consiste à limiter le nombre d’accès disques, soit, en première approximation, le nombre de tuples parcourus. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 5/36 - Bertrand LIAUDET Calcul de coût et arbre algébrique indexé On va inscrire dans l’arbre algébrique indexé le nombre de tuples récupés dans chaque table. Première solution ALL A (250) J( ; NV) (250) Eq_ref (1) J( ;.NB) (250) V (50) Eq_ref (1) B (100) Le nombre d’accès diques, en première approximation, sera: 250 + 250*1 + 250*1 = 750 (250 de A + 250 de A * 1 de B + 250 de J(A,B) * 1 de V) Deuxième solution J( ; NV) Ref (2,5) A (250) J( ;.NB) (250) ALL B (100) Eq_ref (1) V (50) Le 2,5 correspond au nombre moyen de tuples de ABUSER à récupérer à chaque recherche indexée à partir d’un tuple de BUVEURS : c’est 250/100. Le nombre d’accès diques, en première approximation, sera: 100 + 100*2,5 + 250*1 = 600 (100 de B + 100 de B * 2,5 de A + 250 de J(A,B) * 1 de V) Cette solution est donc meilleure que la précédente : ce sera celle proposée par l’EXPLAIN. Les restrictions dans les arbres algébriques indexés Exemple On veut maintenant tous les abus de quantité = 4 avec leur date et avec le nom des buveurs et le cru du vin. On pose une sélectivité de 5% pour la restriction quantité=4 Réponse SQL INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 6/36 - Bertrand LIAUDET Select a.nb, b.nom, a .date, v.nv, v.cru from abuser a, vins v, buveurs b where a.nv=v.nv and a.nb=b.nb and quantite = 4; Première solution On commence par faire une restriction sur ABUSER puis une jointure indexée unique entre ABUSER et BUVEURS puis une autre jointure indexée unique entre ABUSER et VINS. Arbre algébrique indexé et calcul de coût J( ; NV) (12,5) Eq_ref (1) J( ;.NB) (12,5) V (50) Eq_ref (1) R(q=4) 5% (12,5) B (100) ALL A (250) Le nombre d’accès diques, en première approximation, sera: 250 + 12,5*1 + 12,5*1 = 300 (250 de A + 12,5 de A restreint * 1 de B + 12,5 de J(A,B) * 1 de V) Les 250 de A pourrait être ramené à 12,5 si l’attribut quantité était indexé : on obtiendrait alors 37,5 au calcul de coût. J( ; NV) (12,5) Eq_ref (1) J( ;.NB) (12,5) V (50) Eq_ref (1) R(q=4) 5% (12,5) B (100) Eq_ref (12,5) A (250) Deuxième solution On commence par une jointure indexée multiple entre BUVEURS et ABUSER (car le NB de ABUSER est indexé en tant que clé primaire) qui sera suivi par une jointure indexée unique entre ABUSER et VINS. J( ; NV) Eq_ref (1) R(q=4) 5% (12,5) V (50) J( ;.NB) (250) Ref (2,5) A (250) B (100) INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 7/36 - Bertrand LIAUDET La restriction à 5 % intervient après chaque accès (par la jointure indexée multiple) aux tuples de ABUSER correspondant à un tuple de BUVEURS. Le 2,5 correspond au nombre moyen de tuples de ABUSER à récupérer à chaque recherche indexée à partir d’un tuple de BUVEURS : c’est 250/100. Le nombre d’accès diques, en première approximation, sera: 100 + 100*2,5 + 12,5*1 = 362,5 (100 de B + 100 de B * 2,5 de A =250 + 12,5 de J(A,B) * 1 de V) La restriction n’a pas d’influence sur les accès disques. Conclusion Les restrictions sur la table d’index interviennent après la jointure indexée. Les deux solutions se valent (300 contre 362,5). L’ajout d’un index rend la première solution nettement plus performante (37, contre 300). INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 8/36 - Bertrand LIAUDET 2. Présentation générale de la commande EXPLAIN Présentation de l’explain de MySQL (explain plan sous ORACLE) • La commande explain permet d’analyser le plan d’exécution d’une requête. • Syntaxe : EXPLAIN requête. • Le résultat de la commande est une table qui contient 10 attributs. • Chaque ligne concerne une table de la requête analysée. • Etant donné le grand nombre d’attributs de la table résultat de l’explain, on utilisera le plus souvent la présentation « page » (\G) pour faciliter la lecture des résultats. • Explain décrit le plan d’exécution de la requête. • Il permet de savoir dans quel ordre les traitements sont effectués • Il permet aussi de faire un calcul de coût. • Explain permet de voir si on peut avoir intérêt à ajouter des index aux tables afin d’obtenir un select plus rapide. • Le principal paramètre du plan d’exécution concerne la gestion des index. L’explain définit plusieurs types de parcours des tuples, parcours plus ou moins indexés. Les différents types d’index de l’explain C’est le quatrième attribut de l’explain qui définit le type de l’index. Il y a 9 principaux types d’index : ALL, INDEX, RANGE, REF, INDEX_SUBQUERY, EQ_REF, UNIQUE_SUBQUERY, CONST, SYSTEME. 4 : type Précise le type de parcours de la table : avec ou sans index, selon le type d’index. Liste de la moins bonne à la meilleure : ALL correspond au moins bon type de parcours : tous les tuples de la table sont parcourus. INDEX correspond à un parcours identique à ALL à ceci près que c’est l’arbre d’index qui est balayé car toutes les informations utiles s’y trouvent. Les informations utiles sont donc toutes indexées. RANGE correspond à une recherche sur un intervalle avec un index. REF correspond à un parcours indexé des tuples avec un index non unique. Cela correspond généralement à un passage de 1 vers N, de table jointe à la table maître. INDEX_SUBQUERY correspond à un parcours identique à REF pour une sous-requête de type « DEPENDANT_SUBQUERY ». EQ_REF correspond à un parcours indexé des tuples avec un index unique. Cela correspond à un passage de 1 vers 1, de la table maître à la table jointe. C’est le meilleur type de jointure possible. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 9/36 - Bertrand LIAUDET UNIQUE_SUBQUERY correspond à un parcours identique à EQ_REF pour une sous-requête de type « DEPENDANT_SUBQUERY ». CONST correspond à l’usage d’une valeur constante dans la restriction. En cas de restriction de jointure, cette valeur est remontée dans l’évaluation d’un select précédent. SYSTEM correspond au cas rare où une table ne contient qu’une seule ligne. Tous les Attributs de l’explain Le tableau ci-dessous explicite les principales valeurs possibles pour tous les attributs de l’explain. Pour avoir toutes les informations : http://dev.mysql.com/doc/refman/5.0/fr/explain.html 1 : id Identifiant du Select de la requête (qui peut en contenir plusieurs en cas d’imbrication). Id vaut NULL pour le résultat des UNION. 2 : select_type Précise le type de select. “Simple” est le type le plus courant : requêtes mono-select. Les autres types concernent les requêtes multi-select. “Primary” : type du select de la requête principale (requête imbricante ou première requête de l’union). “Union” : type du select principal de la ou des requêtes venant après la première requête de l’union. “Dependant Subquery” : type du select principal d’une sous-requête de type imbrication dans le where. “Derived” : type du select principal d’une sous-requête de type imbriqué dans le from. “Dependant union” : type du select principal de la ou des requêtes venant après la première requête de l’union., la première requête étant de type « subquery » ou « derived ». “Union Result” : type de la table résultat d’une union. C’est une table supplémentaire dans l’EXPLAIN. 3 : table Nom de la table à laquelle la ligne de l’EXPLAIN se réfère. 4 : type Précise le type de parcours de la table : avec ou sans index, selon le type d’index. 5 : possible_keys Indique quels index MySQL peut utiliser. Pour voir quels index possède une table : show index from table ; 6 : key Indique quel index MySQL a effectivement utilisé. 7 : key_len Indique la longueur de la clé de l’index utilisé. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 10/36 - Bertrand LIAUDET 3. 8 : ref Ref indique le critère d’accès à l’index. On a une recherche indexée dans la table. La valeur de l’index (6 : key ) peut être comparé à : « CONST » : une valeur constante. « attribut » : la valeur d’un attribut d’une autre table qui fait référence à l’index (6 : key). C’est le cas des jointures. « FUNC » la valeur d’une expression du select imbriquant. C’est le cas du select imbriqué. 9 : rows Estimation du nombre de lignes de la table que MySQL pense devoir parcourir pour exécuter la requêtes. 10 : extra Précise différentes informations supplémentaires. « No tables used » précise qu’il n’y a pas de tables dans le select. « Using where » précise que le select utilise un where. « Using index » précise que le select utilise un index. « Using filesort » signifie qu’il y a un tri (order by et group by). « Using temporary » signifie qu’il y a un regroupement (distinct et group by). Les différents types d’extra peuvent être cumulés. S’il n’y a pas d’index (possible key et key à NULL) : on peut se demander si on ne pourrait pas indexer l’attribut du where. Etudes de cas 1 : EXPLAIN de requêtes sans tables Explain peut s’appliquer à toutes les requêtes, même celles qui ne contiennent pas de table. select 4*3; mysql> select 4*3; +-----+ | 4*3 | +-----+ | 12 | +-----+ 1 row in set (0.00 sec) mysql> explain select 4*3\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: NULL type: NULL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: NULL Extra: No tables used 1 row in set (0.00 sec) INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 11/36 - Bertrand LIAUDET select user(); mysql> select user(); +----------------+ | user() | +----------------+ | root@localhost | +----------------+ 1 row in set (0.01 sec) mysql> explain select user()\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: NULL type: NULL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: NULL Extra: No tables used 1 row in set (0.00 sec) Attributs de l’explain 1 : id N° du select de l’explain. Il n’y en a qu’un. 2 : select_type Précise le type de select. “Simple” est le type pour un select mono-table. 10 : extra Precise différentes informations supplémentaires. « No tables used » précise qu’il n’y a pas de tables dans le select. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 12/36 - Bertrand LIAUDET 2 : EXPLAIN de requêtes mono-tables sans fonction de groupe On part de la table suivante : mysql> show create table emp; | emp | CREATE TABLE `emp` ( `NE` int(11) NOT NULL, `NOM` varchar(10) NOT NULL, `JOB` enum('PRESIDENT','MANAGER','SALESMAN','CLERK','ANALYST') default NULL, `DATEMB` date default NULL, `SAL` float(7,2) default NULL, `COMM` float(7,2) default NULL, `ND` int(11) NOT NULL, `NEchef` int(11) default NULL, PRIMARY KEY (`NE`) ) ENGINE=MyISAM Select * from emp; mysql> explain select * from emp\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: emp type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: 1 row in set (0.01 sec) Le résultat est le même avec des tables MyISAM sans clé primaire ou en InnoDB avec clés primaires et clés étrangères. Attributs de l’explain 3 : table Précise la table à laquelle la ligne de l’explain se réfère. 4 : type Précise le type de parcours de la table : avec ou sans index, selon le type d’index. ALL correspond au moins bon type de parcours : tous les tuples de la table sont passés en revue. 9 : rows Estimation du nombre de lignes de la table que MySQL pense devoir parcourir pour exécuter la requêtes. Select * from emp where nd=10 mysql> explain select * from emp where nd=10\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: emp type: ALL INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 13/36 - Bertrand LIAUDET possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: Using where 1 row in set (0.00 sec) Attributs de l’explain 10 : extra « Using where » précise que le select utilise un where. Etant donné que par ailleurs, il n’y a pas d’index (possible key et key à NULL) : on peut se demander si on ne pourrait pas indexer l’attribut du where. Alter table emp add index (nd) On indexe l’attribut “nd”. mysql> Alter table emp add index (nd) ; Query OK, 14 rows affected (0.30 sec) mysql> explain select * from emp where nd=10\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: emp type: ref possible_keys: ND key: ND key_len: 5 ref: const rows: 3 Extra: 1 row in set (0.03 sec) Attributs de l’explain 4 : type REF correspond à un parcours indexé des tuples avec un index non unique. Seuls les tuples vérifiant la conditions sont passés en revue. 5 : possible_keys indique quels index MySQL peut utiliser. 6 : key Indique quel index MySQL a effectivement utilisé. 7 : key_len Indique la longueur de la clé de l’index utilisé. 8 : ref « CONST » indique que l’index est comparé à une valeur constante (10 dans l’exemple). 9 : row On a 3 tuples. Cela correspond à la cardinalité du prédicat : nd=10. Cette cardinalité est une information de la métabase. Dans l’explain précédent, on obtient une recherche indexé avec index multiple produisant 3 tuples. On obtient les mêmes résultat en InnoDB avec déclaration de clé étrangère. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 14/36 - Bertrand LIAUDET 3 : EXPLAIN de requêtes mono-tables avec distinct, fonction de groupe ou order by Select count(nd) from emp mysql> explain select count(nd) from emp\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: emp type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: 1 row in set (0.00 sec) Select distinct nd from emp mysql> explain select distinct nd from emp\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: emp type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: Using temporary 1 row in set (0.00 sec) Select * from emp order by nd mysql> explain select * from emp order by nd\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: emp type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: Using filesort 1 row in set (0.00 sec) Select nd, count (*) from emp group by job mysql> explain select job, count(*) from emp group by job\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: emp type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 15/36 - Bertrand LIAUDET Extra: Using temporary; Using filesort 1 row in set (0.00 sec) Attributs de l’explain 10 : extra « Using filesort » signifie qu’il y a un tri (order by et group by). « Using temporary » signifie qu’il y a un regroupement (distinct et group by). Etant donné que par ailleurs, il n’y a pas d’index (possible key et key à NULL) : on peut se demander si on ne pourrait pas indexer l’attribut de l’order by, du distinct ou du group by. Group by sur attribut indexé : select nd, count (*) from emp group by nd mysql> explain select nd, count(*) from emp group by nd\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: emp type: index possible_keys: NULL key: ND key_len: 4 ref: NULL rows: 14 Extra: Using index 1 row in set (0.01 sec) Attributs de l’explain 4 : type REF correspond à un parcours séquentiel de l’index : toute l’information (nd) est dans l’index (nd). 10 : extra « Using index » signifie qu’il y a un index Moteur InnoDB On obtient des résultats facilement interprétables en InnoDB. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 16/36 - Bertrand LIAUDET 4 : EXPLAIN de jointure naturelle - 1 Requête traitée Tous les employés avec le nom de leur département. select e.ne, e.nom, d.nd, d.nom from emp e, dept d where e.nd=d.n Version myISAM sans clé primaire mysql> explain select e.ne, e.nom, d.nd, d.nom from emp e, dept d where e.nd=d.nd\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: e type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: d type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 16 Extra: Using where 2 rows in set (0.00 sec) Attributs de l’explain 2 : type Select « SIMPLE » (mono-select), sur les tables « emp » et « dept » 4 : type type « ALL » : tous les tuples sont parcourus séquentiellement : pour chaque tuple de la table des employés on parcourt tous les tuples de la tables des départements. Il n’y a ni a pas d’index. 9 : row Il faudra parcourir « 14 » * « 16 » rows soit 224 tuples. 10 : extra « Using where » signifie qu’il y a un where : un attribut qu’on pourrait indexer : en l’occurrence soit e. ND, soit d.ND. Version myISAM avec clé primaire mysql> Explain select e.ne, e.nom, d.nd, d.nom from emp e, dept d where e.nd=d.n d\G *************************** 1. row *************************** id: 1 INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 17/36 - Bertrand LIAUDET select_type: SIMPLE table: e type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: d type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: empdept.e.ND rows: 1 Extra: 2 rows in set (0.06 sec) Attributs de l’explain 4 : type Type « ALL » : tous les employés sont parcourus séquentiellement. On en trouve 14. Pour chaque tuple de la table des employés on a un parcours indexé des tuples avec un index unique (EQ_REF). Cela correspond à un passage de 1 vers 1, de la table maître à la table jointe. C’est le meilleur type de jointure possible. 9 : row Il faudra parcourir « 14 » * « 1 » rows soit 14 tuples. 6 : key 8 : ref Dans la table d, l’index, c’est la clé primaire (ND) qui fait référence au ND de la table e. Noter que le ND de la table e n’a pas besoin d’être indexé. Arbre algébrique indexé correspondant J-P( ;E.ND=D.ND ; E.NE, E.nom, D.ND, D.nom) (14) REF (1) P(E.NE, nom, E.ND) (14) P(D.ND, D.nom) ALL E (14) D (16) Version myISAM avec clé primaire et une restriction supplémentaire indexée Requête Tous les employés MANAGER avec le nom de leur départements. select e.ne, e.nom, d.nd, d.nom from emp e, dept d where e.nd=d.n INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 18/36 - Bertrand LIAUDET and job = MANAGER Version sans indexation de “job” Si on n’indexe pas « job », on obtient le même résultat que sans restriction : il faut parcourir tous les tuples de la tables des employés. Card(E) * Sélectivité(E ; JOB=MANAGER) * 1 JN-P( ;E.ND=D.ND ;V.NV) EQ_REF (1) Card(E) * Sélectivité(E ; JOB=MANAGER) R-P( ; ; ND, nom) R-P( ; JOB=MANAGER; NE, nom, ND) ALL E D Dans l’arbre, on montre le nombre de tuples résultats. Le nombre de tuples parcourus est donné en supprimant la sélectivité dans le cas du ALL, soit : Card(E). Version avec indexation de “job” mysql> alter table emp add index (job); Query OK, 14 rows affected (0.18 sec) Enregistrements: 14 Doublons: 0 Avertissements: 0 mysql> explain select e.ne, e.nom, d.nd, d.nom from emp e, dept d where e.nd=d.nd and e.job = 'MANAGER'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: e type: ref possible_keys: JOB key: JOB key_len: 2 ref: const rows: 3 Extra: Using where *************************** 2. row *************************** id: 1 select_type: SIMPLE table: d type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: empdeptisam.e.ND rows: 1 Extra: 2 rows in set (0.03 sec) Attributs de l’explain INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 19/36 - Bertrand LIAUDET 4 : type Type « REF » : on parcourt la table des employés avec un index non unique (REF) sur JOB. On en trouve 3 tuples. Pour chaque tuple de la table des employés dont le job= « MANAGER », on a un parcours indexé des tuples avec un index unique (EQ_REF). Cela correspond à un passage de 1 vers 1, de la table maître à la table jointe. C’est le meilleur type de jointure possible. 9 : row Il faudra parcourir « 3 » * « 1 » rows soit 3 tuples. 6 : key 8 : ref Dans la table e, l’index, c’est JOB fait référence à une valeur constante (MANAGER).. Arbre algébrique simplifié correspondant Card(E) * Sélectivité(E ; JOB=MANAGER) * 1 JN-P( ;E.ND=D.ND ;V.NV) EQ_REF Card(E) * Sélectivité(E ; JOB=MANAGER) = 3 R-P( ; ; ND, nom) R-P( ; JOB=MANAGER; NE, nom, ND) REF (3) E D Dans l’arbre, on montre à la fois le nombre de tuples parcourus et le nombre de tuples résultats. Moteur InnoDE On obtient les mêmes résultats en InnoDB. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 20/36 - Bertrand LIAUDET 5 : EXPLAIN de jointure naturelle - 2 Requête traitée Tous les employés leurs départements, leurs chefs et le département de leur chefs. select * from emp e, dept d, emp echef, dept dchef where e.nd=d.nd and e.nechef=echef.ne and echef.nd=dchef.nd ; Version myISAM avec clé primaire mysql> explain select * from emp e, dept d, emp echef, dept dchef where e.nd=d.nd and e.nechef=echef.ne and echef.nd=dchef.nd\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: e type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: echef type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: empdeptisam.e.NEchef rows: 1 Extra: *************************** 3. row *************************** id: 1 select_type: SIMPLE table: d type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: empdeptisam.e.ND rows: 1 Extra: *************************** 4. row *************************** id: 1 select_type: SIMPLE table: dchef type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: empdeptisam.echef.ND rows: 1 Extra: INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 21/36 - Bertrand LIAUDET 4 rows in set (0.00 sec) Attributs de l’explain 4 : type 9 : row Type « ALL » : on parcourt toute la table des employés. Type « EQ_REF » : pour chaque employé, il y a un accès direct au département, à son chef et au département de son chef. EQ_REF caractérise un index unique. Cela correspond à un passage de 1 vers 1, de la table maître à la table jointe. C’est le meilleur type de jointure possible. Il faudra parcourir « 14 » * « 1 » * « 1 » * « 1 » rows soit 14 tuples. Arbre algébrique simplifié correspondant Card(E) * 1 * 1 * 1 JN-P( ;Echef.ND=Dchef.ND ;*) EQ_REF (1) 4 : Dchef Card(E) * 1 * 1 JN-P( ;E.ND=D.ND ;*) EQ_REF (1) D Card(E) * 1 JN-P( ;E.NEchef=Echef.NE ;*) E (Card(E)) EQ_REF (1) Echef Dans l’arbre, on montre à la fois le nombre de tuples parcourus et le nombre de tuples résultats. Moteur InnoDE On obtient les mêmes résultats en InnoDB. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 22/36 - Bertrand LIAUDET 6 : EXPLAIN de jointure artificielle Requête traitée Tous les employés qui ont le même job qu’un employé du département 20. select distinct e1.ne, e1.nom from emp e1, emp e2 where e1.job=e2.job and e2.nd=20 ; Version myISAM sans index autre que la clé primaire mysql> explain select distinct e1.ne, e1.nom from emp e1, emp e2 where e1.job=e2.job and e2.nd=20\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: e1 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: Using temporary *************************** 2. row *************************** id: 1 select_type: SIMPLE table: e2 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: Using where; Distinct 2 rows in set (0.01 sec) Attributs de l’explain 4 : type Type « ALL » : on parcourt la table des employés EMP1, et pour chaque tuple, on parcourt la table des employés EMP2. 9 : row Il faudra parcourir « 14 » * « 14 » rows soit 196 tuples. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 23/36 - Bertrand LIAUDET Arbre algébrique simplifié correspondant Card(E) * Card(E) * selectivité (E ; ND=20) + restriction du distinct R-P( ; E2.ND=20; job) Card(E) * Card(E) JA-P( ;E1.JOB=E2.JOB ; E1.NE, E1.nom, E2.ND) ALL Card(E) Card(E) P( ; ; NE, nom, job) R-P( ; ND=20 ; ND, job) ALL E1 E2 Version myISAM avec indexation de JOB et ND mysql> alter table emp add index(job); Query OK, 14 rows affected (0.19 sec) Enregistrements: 14 Doublons: 0 Avertissements: 0 mysql> alter table emp add index(nd); Query OK, 14 rows affected (0.21 sec) Enregistrements: 14 Doublons: 0 Avertissements: 0 mysql> explain select distinct e1.ne, e1.nom from emp e1, emp e2 where e1.job=e2.job and e2.nd=20\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: e2 type: ref possible_keys: JOB,ND key: ND key_len: 4 ref: const rows: 4 Extra: Using temporary *************************** 2. row *************************** id: 1 select_type: SIMPLE table: e1 type: ref possible_keys: JOB key: JOB key_len: 2 ref: empdeptisam.e2.JOB rows: 3 Extra: Using where 2 rows in set (0.03 sec) Attributs de l’explain 4 : type Type « REF » : on parcourt la table des employés E2 avec un index non unique (REF) sur ND qui fait référence à une valeur constante. On en trouve INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 24/36 - Bertrand LIAUDET 4 tuples. Pour chaque tuple, on parcourt la table des employés avec un index non unique (REF) sur JOB qui fait référence à E2.JOB. On en trouve 2 tuples. 9 : row Il faudra parcourir « 4 » * « 3 » rows soit 12 tuples. 10 : extra Using temporary signale le distinct. Anoter : avec la version indexée, l’ordre de parcours des table à changé : on commence par E2 et on finit par E1. Arbre algébrique simplifié correspondant Distinct() : Restriction inconnue 4*3 JA-P( ;E1.JOB=E2.JOB ; E1.NE, E1.nom) REF (3) Card(E) * Sélectivité(E ; ND=20) = 4 P(; NE, nom, job) R-P( ; ND=20 ; job) REF E2 E1 A noter : la sélectivité de E1 est une sélectivité d’attribut tandis que celle de E2 est une sélectivité de prédicat. On pourrait aussi faire le calcul avec une sélectivité d’attribut pour E2 : ce serait moins précis car la sélectivité d’attribut donne seulement une valeur moyenne. Moteur InnoDE On obtient les mêmes résultats en InnoDB. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 25/36 - Bertrand LIAUDET 7 : EXPLAIN de select imbriqué Requête équivalente à une jointure naturelle Tous les employés MANAGER de CHICAGO Requête avec jointure select e.ne, e.nom from emp e, dept d where e.nd=d.nd and job = ‘MANAGER’ and d.ville=’CHICAGO’; mysql> explain select e.ne, e.nom from emp e, dept d where e.nd=d.nd and job = 'MANAGER' and d.ville='CHICAGO'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: e type: ref possible_keys: JOB key: JOB key_len: 2 ref: const rows: 3 Extra: Using where *************************** 2. row *************************** id: 1 select_type: SIMPLE table: d type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: empdeptisam.e.ND rows: 1 Extra: Using where 2 rows in set (0.00 sec) 9 : row 3* 1 = 3 tuples passés en revue. Requête imbriquée select ne, nom from emp where job=’MANAGER’ and nd = any ( select nd from dept where ville=’CHICAGO’ ); INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 26/36 - Bertrand LIAUDET mysql> explain select ne, nom from emp where job='MANAGER' and select nd from dept where ville='CHICAGO')\G *************************** 1. row *************************** id: 1 select_type: PRIMARY table: emp type: ref possible_keys: JOB key: JOB key_len: 2 ref: const rows: 3 Extra: Using where *************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: dept type: unique_subquery possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: func rows: 1 Extra: Using where 2 rows in set (0.00 sec) nd = any ( 2 : select_type DEPENDANT_SUBQUERY : type du select principal d’une sous-requête de type imbrication dans le where. 4 : type UNIQUE_SUBQUERY correspond à un parcours identique à EQ_REF pour une sous-requête de type « DEPENDANT_SUBQUERY ». EQ_REF correspond à un parcours indexé des tuples avec un index unique. Cela correspond à un passage de 1 vers 1, de la table maître à la table jointe. C’est le meilleur type de jointure possible. 8 : ref « FUNC » indique que l’index est comparé à une valeur d’un select imbriquant. 9 : row 3* 1 = 3 tuples passés en revue. Bilan comparé Le résultat est le même pour cet exemple. Toutefois, plus généralement, l’usage de la requête imbriquée est plus restrictive : elle interdit la projection d’attributs du select imbriqué et elle interdit de retravailler le plan d’exécution (l’arbre algébrique) en fonction des index. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 27/36 - Bertrand LIAUDET Requête équivalente à une jointure artificielle Tous les employés qui ont le même job qu’un employé du département 20. select e1.ne, e1.nom from emp e1 where e1.job=any ( select e2.job from emp e2 where e2.nd=10 ); Version myISAM avec JOB et ND indexés Remarque : on renomme les tables, bien que ce ne soit pas nécessaire, pour s’y retrouver dans l’EXPLAIN. mysql> explain Select e1.ne, e1.nom from emp e1 where e1.job=any(select e2.job from emp e2 where e2.nd=20)\G *************************** 1. row *************************** id: 1 select_type: PRIMARY table: e1 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 14 Extra: Using where *************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: e2 type: index_subquery possible_keys: JOB,ND key: JOB key_len: 2 ref: func rows: 3 Extra: Using where 2 rows in set (0.00 sec) Version myISAM avec JOB et ND indexés 2 : select_type DEPENDANT_SUBQUERY : type du select principal d’une sous-requête de type imbrication dans le where. 4 : type INDEX_SUBQUERY correspond à un parcours identique à REF pour une sous-requête de type « DEPENDANT_SUBQUERY ». REF correspond à un parcours indexé des tuples avec un index non unique. Cela correspond généralement à un passage de 1 vers N, de table jointe à la table maître. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 28/36 - Bertrand LIAUDET 8 : ref « FUNC » indique que l’index est comparé à une valeur d’un select imbriquant. 9 : row 14 * 3 = 42 tuples passés en revue. Bilan comparé Le résultat est moins bon qu’avec une jointure artificielle. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 29/36 - Bertrand LIAUDET 4. Autour de l’EXPLAIN ANALYZE TABLE nomTable Maysql >analyze table nomTable; http://dev.mysql.com/doc/refman/5.0/fr/analyze-table.html Equivalent à myisamchk --analyze ou myisamchk -a Cette opération permet mettre à jour les méta-données (dans la METABASE) : particulièrement la cardinalité des prédicats. En utilisant la commande « Analyse table », on va mettre à jour les méta-données : mysql> analyze table emp; +-------------+---------+----------+----------+ | Table | Op | Msg_type | Msg_text | +-------------+---------+----------+----------+ | empdept.emp | analyze | status | OK | +-------------+---------+----------+----------+ 1 row in set (0.01 sec) L’opération peut être exécutée manuellement ou régulièrment et automatiquement. Script de création des commandes d’analyse pour toutes les tables : Select concat(‘ANALYZE TABLE ’, table_schema, ‘.’, table_name, ‘ ;’) from information_schema.tables ; SHOW INDEX Syntaxe Show index from nomTable ; Permet de lister les index d’une table. http://dev.mysql.com/doc/refman/5.0/fr/show-index.html Attribut CARDINALITY L’attribut « CARDINALITY » dans le « SHOW INDEX » donne une approximation du nombre de valeurs possibles pour un attribut indexé. Dans l’idéal, la valeur de CARDINALITY vaut exactement le nombre de valeurs possibles pour l’attribut considéré. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 30/36 - Bertrand LIAUDET S’il y a trop peu de tuples dans la table, la valeur de CARDINALITY est souvent diminuée. S’il y a des valeurs à NULL (NULL à yes), la valeur de CARDINALITY est souvent augmentée. Dans le cas du moteur InnoDB, la valeur de CARDINALITY est souvent augmentée. Exemple mysql> show index from dept\G *************************** 1. row *************************** Table: dept -- nom de la table Non_unique: 0 -- index unique : CP (0 = faux) Key_name: PRIMARY -- nom de l’index Seq_in_index: 1 -- n° de la colonne dans l'index, début à 1. Column_name: ND -- colonne de l’index Collation: A -- Façon dont la col. est triée. A:asc.NULL:non trié. Cardinality: 16 -- nombre de valeurs différentes Sub_part: NULL -- nb cara indexés. NULL si col. totalement indexée. Packed: NULL -- façon dont la clé est compactée. NULL si pas. Null: -- possibilité d’une valeur NULL. Non si rien. Index_type: BTREE -- technique d’indexation Comment: -- commentaires *************************** 2. row *************************** Table: dept Non_unique: 1 Key_name: NOM Seq_in_index: 1 Column_name: NOM Collation: A Cardinality: 4 Sub_part: NULL Packed: NULL Null: YES Index_type: BTREE Comment: 2 rows in set (0.01 sec) RAPPELS de la syntaxe de création des index Syntaxe Ajouter un index : ALTER TABLE NomTable ADD INDEX (nomColIndex); Supprimer un index : ALTER TABLE NomTable DROP INDEX nomIndex; A noter que le nom de l’index n’est pas forcément le nom de la colonne de l’index. A la création de la table : CREATE TABLE NE NOM JOB DATEMB SAL COMM ND EMP ( integer primary key, varchar(10) not NULL, enum ('PRESIDENT','MANAGER', 'SALESMAN', 'CLERK', 'ANALYST'), date, float(7,2), key(SAL), float(7,2), integer not null, foreign key(ND) references DEPT(ND), INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 31/36 - Bertrand LIAUDET NEchef integer references EMP, foreign key(NEchef) references EMP(NE) ) TYPE MyISAM; create index idx_JOB ON EMP(JOB); Le bilan est la création de 5 index : NE, SAL, ND, NEchef, JOB restreinte. Ca empire la situation. STRAIGHT_JOIN STRAIGHT_JOIN permet de forcer l’ordre des jointures. L’ordre sera celui de la requête. La syntaxe est celle d’un JOIN qu’on remplace par STRAIGHT_JOIN. http://dev.mysql.com/doc/refman/5.0/fr/join.html Forcer l’ordre des jointures permet de forcer l’optimiseur à utiliser certains index. C’est une pratique similaire au fait de forcer un index : FORCE INDEX FORCE INDEX et IGNORE INDEX FORCE_INDEX permet de forcer le fait d’utiliser un index. IGNORE INDEX permet d’ignorer un index. La syntaxe est celle d’un JOIN. On précise à la déclaration de la table l’attribut indexé dont on veut forcer l’usage ou dont on veut éviter l’usage. Forcer un index peut conduire à revoir l’ordre des jointures. C’est une pratique similaire au fait de forcer l’ordre des jointures : STRAIGHT_JOIN Exemple mysql> explain select * from emp e force index(nd) join dept d on(e.nd=d.nd) where d.nom = 'SALES'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: d type: ref possible_keys: PRIMARY,NOM key: NOM key_len: 17 ref: const rows: 4 Extra: Using where *************************** 2. row *************************** id: 1 select_type: SIMPLE table: e type: ref possible_keys: ND key: ND key_len: 4 ref: empdept.d.ND rows: 1 Extra: 2 rows in set (0.01 sec) INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 32/36 - Bertrand LIAUDET Ici le FORCE INDEX peut se justifier pour pouvoir exploiter l’attribut NOM de DEPT qui est indexé. FORCER LE TRI Shell > Myisamchk --sort-records=1 DATADIR/nomDatabase/nomTable Permet de trier la table “en dur” selon l’index n°1 (numéro de la ligne de l’index récupéré avec Show index). Ce tri permettra d’accélérer ensuite les requêtes qui utilise cet index. Il faut faire un flush pour que la modification soit prise en compte par le client. Mysql> flush table nomTable Mysql> select * from nomTable : les tuples apparaissent triés selon l’index. OPTIMIZE TABLE nomTable Maysql >optimize table nomTable; http://dev.mysql.com/doc/refman/5.0/fr/optimize-table.html OPTIMIZE TABLE permet de réorganiser les tables et particulièrement les emplacements vides. Choix du type des données Mieux vaut choisir types compacts. Mieux vaut choisir des types à taille fixe. A éviter Eviter les requêtes imbriquées. Eviter les DISTINCT et les ORDER BY. Consultation des statistiques de lecture en cache et sur disques en InnoDB C:> mysqladmin -uroot -p extended-status Enter password: ******** +-----------------------------------+-----------+ | Variable_name | Value | +-----------------------------------+-----------+ ... | Innodb_buffer_pool_read_requests | 12958918 | | Innodb_buffer_pool_reads | 8875 | ... Le paramètre pool_read_requests donne le nombre de lecture logique. Le paramètre pool_reads donne le nombre de lecture physique. Les chiffres donnent le nombre de pages, sachant qu’une page INNODB a une taille de 16Ko. Comment éviter les analyses de tables INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 33/36 - Bertrand LIAUDET http://dev.mysql.com/doc/refman/5.0/fr/how-to-avoid-table-scan.html SHOW TABLE STATUS FROM nomBD Permet de connaître l’état de toutes les tables d’une BD. BENCHMARK Permet de connaître les capacités de calcul SQL sur la machine qu’on utilise. Select benchmark(1 000 000, 1+1) Donne le temps d’exécution de 1 000 000 d’additions simples par MySQL INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 34/36 - Bertrand LIAUDET TP Utilisation de l’EXPLAIN Première partie 1. Expliquer le résultat de l’explain pour la requête suivante : afficher la date du jour. 2. Utiliser la BD BuveursMyISAM.txt. Vérifier le code effectivement pris en compte par le serveur pour chaque table. 3. Expliquer le résultat de l’EXPLAIN pour la requête : quels sont tous les buveurs ? 4. Expliquer le résultat de l’EXPLAIN pour la requête : quels sont tous les producteurs bordelais ? 5. Comment optimiser la requête précédente ? Faites l’optimisation et analyser le résultat de l’EXPLAIN après optimisation. 6. Vérifier que les résultats de l’EXPLAIN sont cohérents avec les données effectivement dans la BD. 7. Comment mettre à jour à cohérence ? Exécuter la commande et vérifier les conséquences sur l’EXPLAIN. 8. Expliquer le résultat de l’EXPLAIN pour la requête : quels sont tous les numéros de vins ayant conduit à des abus 9. Comment optimiser la requête précédente ? Faites l’optimisation et analyser le résultat de l’EXPLAIN après optimisation. 10. Expliquer le résultat de l’EXPLAIN pour la requête : quel est le nombre d’abus par numéro de buveurs ? 11. Peut-on optimiser cette requête ? Deuxième partie : Faire l’arbre algébrique avec coût de tous les EXPLAIN 12. Utiliser la BD EmployesMyISAM.txt. Traiter la question : tous les employés avec leurs départements, leurs chefs et le département de leurs chefs et la liste des employés qui travaillent dans un département de même nom. On affichera CP et CS de chaque table en jeu. Trier les résultats par nom d’employé. Faire le graphe de la question. Quelle est la clé primaire de la question. Expliquer le résultat de l’EXPLAIN. Quelle amélioration pourrait-on faire ? Faites-la. Relancer l’EXPLAIN. Troisième partie : Faire l’arbre algébrique avec coût de tous les EXPLAIN 13. Relancer la BD BuveursMyISAM.txt pour repartir d’une BD sans index. 14. Expliquer le résultat de l’EXPLAIN pour la requête : quels sont tous les millésimes 2007 des producteurs bordelais. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 35/36 - Bertrand LIAUDET 15. Faites l’arbre algébrique simplifié correspondant à l’EXPLAIN. Mettez-y les formules de calcul de coût. 16. Expliquer le résultat de l’EXPLAIN pour la requête : quels sont tous buveurs ayant abusé en 2007 ? 17. Faites l’arbre algébrique simplifié correspondant à l’EXPLAIN. Mettez-y les formules de calcul de coût. 18. Expliquer le résultat de l’EXPLAIN pour la requête : quels sont tous les millésimes 2007 des producteurs bordelais. 19. Faites l’arbre algébrique simplifié correspondant à l’EXPLAIN. Mettez-y les formules de calcul de coût. 20. Optimiser la requête précédente. Relancer l’EXPLAIN. Que constatez-vous ? Quatrième partie : Faire l’arbre algébrique avec coût de tous les EXPLAIN 21. Relancer la BD BuveursMyISAM.txt pour repartir d’une BD sans index. 22. Expliquer le résultat de l’EXPLAIN pour la requête : quels sont tous les buveurs ayant bu un bordeaux de degré égal à 11 degré. On donnera deux versions : une version avec jointures et une version avec select imbriqués. Que constatez-vous ? 23. Comment optimiser la requête précédente (avec jointures) ? Faites l’optimisation et analyser le résultat de l’EXPLAIN après optimisation. 24. Faites l’arbre algébrique de l’EXPLAIN précédent. Mettez-y les formules de calcul de coût. 25. Ajouter toutes les clés étrangères. Relancer l’EXPLAIN. Que constatez-vous ? 26. Modifier le script de création de la BD de la façon suivante : passer le moteur en InnoDB, ajouter les clés étrangères et les index repérés dans l’analyse. Relancer l’EXPLAIN pour la dernière requêtes. Comparer les résultats avec la version MyISAM. INSIA - BASES DE DONNÉES – SIGL 3 – Optimisation – Index et Explain - page 36/36 - Bertrand LIAUDET