Cours BD 5.
authorKim Nguyễn <kn@lri.fr>
Wed, 8 Apr 2015 19:43:37 +0000 (21:43 +0200)
committerKim Nguyễn <kn@lri.fr>
Wed, 8 Apr 2015 19:43:37 +0000 (21:43 +0200)
bd/bd05.xhtml

index 7b0692e..5c5c6f0 100644 (file)
@@ -42,7 +42,7 @@
     </script>
   </head>
   <body>
-    <a href="bd03.xhtml" class="sws-previous"/>
+    <a href="bd04.xhtml" class="sws-previous"/>
     <div class="sws-slide sws-cover sws-option-nofooter">
       <h1>Bases de données</h1>
       <h3>Polytech Paris-Sud</h3>
@@ -90,7 +90,7 @@
   pages</li>
   <li><em>Reserves</em>: 40 octets/enr., 100 enr/page, 1000
   pages</li>
-  <li><em>Boats</em>: non utilisé dans la suite</li>
+  <li><em>Boats</em>: 20 octets/enr., 200 enr/page, 200 pages</li>
 </ul>
     </div>
     <div class="sws-slide">
@@ -277,8 +277,8 @@ Une projection commute avec une selection qui utilise uniquement
 <h1>Modèle de calcul</h1>
 <p>
   Les SGBD modernes utilisent un modèle de
-  calcul <em><i>pull</i></em>. L'opérateur le plus « haut » (racine)
-  dans l'arbre de requête « tire » (<i>pull</i>) le résultat de ses
+  calcul <em><i>pull</i></em>. L'opérateur le plus «&nbsp;haut&nbsp;» (racine)
+  dans l'arbre de requête «&nbsp;tire&nbsp;» (<i>pull</i>) le résultat de ses
   sous-arbres (similaire à l'appel de <i>next</i> sur les iterateurs
   de la bibliothèque standard Java). Cela permet
   de <em><i>pipeliner</i></em> les opérateurs. Certains opérateurs «
@@ -355,7 +355,7 @@ Une projection commute avec une selection qui utilise uniquement
 </ul>
 <p><img src="left_deep.svg" style="width:80%;margin-left:10%;" /></p>
 <p style="background:white">Ce ne sont que des <em>heuristiques</em> pour réduire l'espace de
-  recherche, on n'est pas sur d'avoir la solution optimale!</p>
+  recherche, on n'est pas sûr d'avoir la solution optimale!</p>
 </div>
 <div class="sws-slide">
 <h1>Énumération des plans gauches en profondeur 1/2</h1>
@@ -375,24 +375,226 @@ Une projection commute avec une selection qui utilise uniquement
   deux à deux les résultats de la passe (n-1)
 </li>
 </ol>
-<p>Comment sélectionner les « meilleurs » jointures
-  <span class="sws-pause" style="background:white" >On garde pour chaque <em>ordre</em> de
-  résultat intermédiaire celle de moindre coût
+<p>Comment sélectionner les « meilleures » jointures ?
+  <span class="sws-pause" style="background:white" >On garde pour chaque <em>ordre</em> de
+    résultat intermédiaire celle de moindre coût
 </span></p>
 </div>
 <div class="sws-slide">
 <h1>Énumération des plans gauches en profondeur 2/2</h1>
-<p>Exemple: si on a la possibilité de faire une jointure itérative de
-  cout 1000, une jointure par hash de coût 500 et une jointure
-  sort-merge de coût 1500, on garde les version hash
-  et <s>sort-merge</s> (car il est possible que le fait d'avoir les
-  résultats déjà trié rendent le coût moindre à l'étape suivante)
+<p>Points à prendre en compte pour le calcul du coût d'un plan</p>
+<ol>
+  <li><em>Éviter les plans qui génèrent des produits cartésiens</em>, sauf si
+  c'est indispensable</li>
+  <li>Les projections, sélections, et jointures itératives par index
+    peuvent êtres faites en <em><i>pipeline</i> (ou <i>streaming</i></em> sans
+    itération/matérialisation des résultats intermédiaires
+  </li>
+  <li>Celà peut valoir le coup d'utiliser un <i>merge-sort</i> join
+    (possiblement coûteux) si on demande les résultats dans un <em>certain
+    ordre</em> (<tt>ORDER BY</tt> compatible avec celui de la jointure). Cela évite de faire
+    une jointure suivie d'un tri.
+  </li>
+  <li>Pousser les sélections/projections <em>plus bas</em> dans le plan
+  permet de faire diminuer la taille des résultats
+  intermédiaires. Attention cependant, appliquer une sélection ou une
+  projection à une table T munie d'un index crée une table T' plus
+  petite mais <em><i>sans
+  index</i></em>.
+  </li>
+</ol>
+</div>
+<div class="sws-slide">
+<h1>Exemple</h1>
+<p>Considérons la requête : </p>
+<code>
+  SELECT sname, bname FROM Boats B, Sailors S, Reserves R WHERE
+  B.bid = R.bid AND S.sid = R.sid AND S.rating > 8
+</code>
+<p>Deux jointures (<tt>B &join; R</tt> et <tt>R &join; S</tt>) et une
+sélection sur S. On suppose un hash-index sur S.sid et un
+hash-index sur B.bid, les valeurs de notes vont de 1 à 10,
+uniformément réparties. Tous les sid et tous les bid sont présents
+  dans R.
+  Les hash-index sont non-groupants et de coût
+  d'accès 2.
+  Quels sont les plans possibles ?</p>
+<p class="sws-pause"><img src="example_plan.svg" style="width:80%;margin-left:10%;" /></p>
+</div>
+
+<div class="sws-slide">
+<h1>Exemple (Calculs préliminaires)</h1>
+
+<ul>
+<li>Taille d'une page : 4000 octets</li>
+<li>Taille de S : 500 pages, 40 000 enr.</li>
+<li>Taille de R : 1000 pages, 100 000 enr.</li>
+<li>Taille de B : 200 pages, 40 000 enr.</li>
+<li>Taux de sélectivité de <tt>rating &gt; 8 : 20%</tt> </li>
+<li><tt>&sigma;<sub>rating&gt;8</sub>(S)</tt> : 8000 enr. ou 100 pages</li>
+</ul>
+
+</div>
+
+
+<div class="sws-slide">
+<h1>Exemple (Plan 1)</h1>
+<p>
+<span style='display:inline-block;
+            margin-right:1em;
+            vertical-align: top;
+            background-image: url("example_plan.svg");
+            background-repeat: no-repeat;
+            background-position: -5%;
+            border: 1px solid black;
+            width:5cm;
+            height:4cm;
+            float:left;'>
+ </span>
+
+On choisi de faire d'abord une jointure entre R et S (i.e. un produit
+cartésien car il n'y a pas de condition de jointure entre ces deux
+tables). Puis la jointure de la table résultante avec B sur les
+attributs (bid,sid).
+</p>
+<p> Manière la plus efficace de calculer S : <em>appliquer la sélection
+  directement sur S, puis la jointure <tt>B &join;
+  (&sigma;(S))</tt></em>. Pas d'utilisation d'index possible, jointure page
+  à page (car on génère tout le produit cartésien) : <tt>100 ×
+  (100 + 200) = 300 000</tt> E/S (pages) ou 192 000 000 enr.
+</p>
+<p>Puis jointure <em>itérative page à page</em> avec R (<em>pas d'index sur R</em>, pas d'index
+  sur le résultat précédant qu'on vient de créer en mémoire):
+  <tt>1 000 × (300 000 + 1000) = 301 000 000 E/S.</tt>
+</p>
+<p>Coût total: <tt>301 300 000 E/S</tt> (les projections sont faites
+  en pipline à la fin)</p>
+<p style="background:white">Plan complètement inefficace. On ignorera les plans contenant un
+  produit cartésien, sauf si c'est le seul moyen de calculer la
+  requête (<tt>SELECT * FROM A, B</tt>).
+</p>
+</div>
+
+<div class="sws-slide">
+<h1>Exemple (Plan 2 v1)</h1>
+<p>
+<span style='display:inline-block;
+            margin-right:1em;
+            vertical-align: top;
+            background-image: url("example_plan.svg");
+            background-repeat: no-repeat;
+            background-position: 53%;
+            border: 1px solid black;
+            width:5cm;
+            height:4cm;
+            float:left;'>
+ </span>
+
+On choisi de faire d'abord une jointure entre R et B, sur
+l'attribut <tt>bid</tt> puis jointure du résultat intermédiaire
+sur <tt>sid</tt>.</p>
+
+<p>On dispose <em>d'un index</em> sur <tt>B.bid</tt>. On effectue une
+  <em>jointure itérative par index</em> : <tt> 1000 + 100 000 × 3 :
+  301 000 E/S</tt> (2 pour le hash-index et 1 pour la lecture des
+  données depuis l'index).
+</p>
+<p>La deuxième jointure peut être faite à la volée (jointure itérative
+  par index sur <tt>S.sid</tt>) et la condition de sélection testée à
+  la volée. Coût total 100 000 × 3 (pour chacun des enregistrement
+  précédants, on paye un accès d'index + un accès à la ligne
+  correspondante dans S).
+</p>
+<p>Coût total: <tt>601 000 E/S</tt> (les projections sont faites en pipline à la fin)</p>
+</div>
+
+<div class="sws-slide">
+<h1>Exemple (Plan 2 v2)</h1>
+<p>
+<span style='display:inline-block;
+            margin-right:1em;
+            vertical-align: top;
+            background-image: url("example_plan.svg");
+            background-repeat: no-repeat;
+            background-position: 53%;
+            border: 1px solid black;
+            width:5cm;
+            height:4cm;
+            float:left;'>
+ </span>
+
+On choisi de faire d'abord une jointure entre R et B, sur
+l'attribut <tt>bid</tt> puis jointure du résultat intermédiaire
+sur <tt>sid</tt>.</p>
+
+<p>On n'utilise <em>pas l'index</em> sur <tt>B.bid</tt>. On effectue une
+  <em>jointure itérative page à page</em> : <tt> 200 + 200 × 1000 :
+  200 200 E/S</tt> . On a 100 000 résultats (car tous les B.bid
+  sont présents dans la table R). Un enregistrement du
+  résultat fait environ 40+20 = 60 octets donc 66 enregistrements par
+  pages de 4000 octets donc 1515 pages de résultats.
+</p>
+<p>On applique la sélection sur S par un scan linéaire: <tt>500
+  E/S</tt> et <tt>100 pages</tt> de résultats</p>
+<p> On fait une jointure page à page des deux résultats
+ précédents : <tt>100 + 100 × 1515 = 100 615 E/S</tt>.
+</p>
+<p>Coût total: <tt>102 630 E/S</tt> (les projections sont faites en pipline à la fin)</p>
+</div>
+
+
+
+<div class="sws-slide">
+<h1>Exemple (Plan 3)</h1>
+<p>
+<span style='display:inline-block;
+            margin-right:1em;
+            vertical-align: top;
+            background-image: url("example_plan.svg");
+            background-repeat: no-repeat;
+            background-position: 103%;
+            border: 1px solid black;
+            width:5cm;
+            height:4cm;
+            float:left;'>
+ </span>
+
+On choisi de faire d'abord une jointure entre R et S, sur
+l'attribut <tt>sid</tt> puis jointure du résultat intermédiaire
+sur <tt>bid</tt>.</p>
+<p>On applique la sélection sur S par un scan linéaire: <tt>500
+  E/S</tt> et <tt>100 pages</tt> de résultats</p>
+
+<p> On effectue une <em>jointure itérative page à page</em> : <tt> 100 + 100 × 1000 :
+  100 100 E/S</tt> . On a 100 000 résultats (car tous les S.sid
+  sont présents dans la table R, <s>même après sélection</s> car
+  distribution uniforme). Un enregistrement du
+  résultat fait environ 40+50 = 90 octets donc 44 enregistrements par
+  pages de 4000 octets donc 2272 pages de résultats.
+</p>
+<p> On fait une jointure page à page des du résultat
+ précédent avec B : <tt>200 + 200 × 2272 = 454 600 E/S</tt>.
 </p>
-<p>On garde les <tt>ORDER BY</tt>, <tt>GROUP BY</tt>, aggrégats, …
-  pour la fin, en profitant si possible des ordres des résultats faits
-  par les jointures précédentes</p>
-<p>On évite tant que possible de faire des produits cartésiens (en
-  poussant les selections par exemple)</p>
+<p>Coût total : 555 200 E/S</p>
+</div>
+<div class="sws-slide">
+<h1>Exemple (conclusion)</h1>
+
+<ul>
+  <li>Utiliser l'index n'est pas toujours payant, surtout s'il est
+    non-groupant et qu'il car on ajoute un facteur qui est le nombre de
+    résultats, pas le nombre de pages</li>
+  <li>On a fait certaines approximations « à la louche » (taille des
+    enregistrements résultants d'une jointure, nombre des
+    enregistrements résultants)</li>
+  <li>On n'a pas considéré le fait que pousser les projections plus
+    bas pour ne garder que les colonnes strictement nécessaires pouvait
+    faire baisser la taille des tables intermédiaires
+  </li>
+</ul>
+
+
+
 </div>
 <div class="sws-slide">
 <h1>Requêtes imbriquées</h1>