Évaluation des requêtes relationnelles SQL QUOI Évaluateur de requêtes du SGBD COMMENT en fonction du schéma interne
Dans la suite, on va considérer les tables Exemple courant Dans la suite, on va considérer les tables Livre(ISBN, titre, année, éditeur, #code) Catégorie(code, description, #code_parent)
Requête interne SELECT titre, descripteur FROM livre, categorie WHERE ISBN=1-1111 AND livre.code=categorie.code
Plan d ’exécution 1
Plan d ’exécution 2
Plan d ’exécution 3
Estimation du coût des opérations physiques TempsES : temps d’accès à la mémoire secondaire (MS) TempsUCT souvent négligeable TailleMC : espace mémoire centrale TailleMS : espace mémoire secondaire
Statistiques TempsPosDébut Temps qu’il faut pour se positionner au début du premier octet à transférer (ex: 10ms) TempsTrans Temps qu’il faut pour transférer un bloc (ex: 1ms) TempsESBloc (ex: 11ms) TailleBloc (ex: 2KO) NT Nombre de lignes de la table T TailleLigneT Taille d’une ligne de la table T FBT Facteur de blocage moyen de T (#lignes/bloc) FBMT Facteur de blocage Max de T BT Nombre de blocs de T
Coût des opérations de base Hypothèses Néglige effet de l ’antémémoire (cache) Néglige écriture du résultat TailleLigne < TailleBloc Sans interruption
Balayage (BAL) TempsES (BAL) = BT * TempsTrans + NombrePos * TempsPosDébut
Exemple : TempsES (BALEditeur) Allocation sérielle sans fragmentation interne BEditeur = NEditeur / FBEditeur = 50/ 60 = 1 bloc TempsES (BALEditeur) = 11 ms
Exemple : TempsES (BALCatégorie) Allocation sérielle sans fragmentation interne BCatégorie = 4 000/ 40 = 100 blocs Meilleur cas : 100 * 1 ms + 1 * 10 ms = 110 ms Pire cas : 100 *1 ms+100* 10 ms = 1 100 ms
Exemple : TempsES (BALLivre) Allocation sérielle sans fragmentation interne BLivre = 1 000 000/ 20 = 50 000 blocs Meilleur cas : TempsES (BALLivre) = 50,01 secs Pire cas : TempsES (BALLivre) = 9,16 minutes
Exemple : TempsES (BALLivre) Arbre-B+ primaire sur la clé primaire ISBN FBLivre = 2/3 FBMLivre = 13 BLivre = NLivre/ FBLivre = 1 000 000/ 13 = 76 924 blocs Pire cas (consécutivité des feuilles non assurée) ! = 76 924* 1ms + 76 924 * 10ms = 848 164 ms = 14,1 mn
Sélection par égalité dans un index arbre-B+ primaire (S=IP) TempsES (S=IP) = Parcours des niveaux d ’index (HauteurI -1) * TempsESBloc + Parcours des feuilles SelT (CléIndex = Valeur)/ FBT* TempsESBloc
Suite Cas d ’une clé candidate TempsES (S=IP )= HauteurI * TempsESBloc Estimation de HauteurI 1 + log OrdreMoyenI (CardT (CléIndex) / FBT) OrdreMoyenI = 2/3 OrdreI FBT = 2/3 FBMT
Index primaire code de la table Catégorie (clé) OrdreMoyenI = 2/3 OrdreI = 66 FBCatégorie = 2/3 FBMCatégorie = 26 HauteurI = 1 + log OrdreMoyenI (CardCatégorie (code) / FBCatégorie) = 1+ log 66 (4 000 / 26) = 3 TempsES (S=IP) = HauteurI *TempsESBloc = 33 ms
Index primaire sur #code de la table Livre (clé étrangère) OrdreMoyenI = 2/3 OrdreI = 66 FBLivre = 2/3 FBMLivre = 13 HauteurI = 1 + log OrdreMoyenI (CardLivre (code) / FBLivre) = 3 FacteurSélectivitéLivre (code) = 1/ CardLivre (code) = 1/4 000 SelLivre (code = Valeur ) = 1 000 000/4000 = 250 lignes TempsES (S=IP) = (HauteurI -1) * TempsESBloc + SelLivre (code = Valeur)/ FBLivre)* TempsESBloc = 2* 11 ms + ( 250/ 13) * 11 ms = 22 ms +20 * 11 ms = 242 ms
Index primaire sur ISBN de Livre OrdreMoyenI = 2/3 OrdreI = 66 FBLivre = 2/3 FBMLivre = 13 HauteurI = 1 + log OrdreMoyenI (CardLivre (ISBN) / FBLivre) = 4 TempsES (S=IP) = HauteurI *TempsESBloc = 44 ms
Sélection par égalité dans un index arbre-B+ secondaire (S=IS)
Estimation de TempsES (S=IS) Niveaux d ’index (HauteurI -1) * TempsESBloc Feuilles de l ’index SelT (CléIndex = Valeur)/ OrdreMoyenI *TempsESBloc Blocs de l ’organisation primaire SelT (CléIndex = Valeur)*TempsESBloc TempsES (S=IS sur clé candidate) (HauteurI +1)*TempsESBloc
Estimation de HauteurI pour index secondaire Hypothèses clés répétées FB = OrdreMoyen HauteurI = logOrdreMoyenI (NT)
Index secondaire code de Livre (clé étrangère) HauteurI = log66(1 000 000) = 4 SelLivre (code = Valeur )= 250 lignes TempsES (S=IS) = 2 827ms TempsES (S=ISa) = 2 827ms TempsES (S=IP) = 242ms
Index secondaire sur code de Livre (clé étrangère) HauteurI = log66(1 000 000) = 4 SelLivre (code = Valeur) = 50 000 lignes TempsES (S=IS) = 558 371ms TempsES (S=ISa) = 361 207ms Pire que TempsES (BALLivre) = 50,01 secs !
Index secondaire sur ISBN de Livre (clé primaire) HauteurI = log66(1 000 000) = 4 TempsES(S=IS sur clé candidate)= (HauteurI +1)*TempsESBloc = 55 ms ~TempsES (S=IP) = HauteurI *TempsESBloc = 44 ms
Sélection par intervalle dans un index arbre-B+ primaire (S>IP) ~ clé non unique CléIndex [Valeur1..Valeur2] TempsES (S>IP) = (HauteurI -1) * TempsESBloc + SelT (CléIndex [Valeur1..Valeur2])/ FBT* TempsESBloc
Index primaire sur code de la table Livre (clé étrangère) OrdreMoyenI = 2/3 OrdreI = 66 FBLivre = 2/3 FBMLivre = 13 HauteurI = 3 TempsES (S>IP) = 4 257 ms
Tri externe si M est petit TRI D'UNE TABLE (TRI) Utilité jointure par tri-fusion élimination des doubles (DISTINCT) opérations d ’agrégation (GROUP BY) résultats triés (ORDER BY) Tri externe si M est petit tri-fusion
Étape tri Tri fusion externe nombre de groupes = BT /M = 12 /3 = 4 Coût = 2 * ( BT /M * TempsPosDébut + BT * TempsTrans) = 104 ms
Étape fusion Coût des passes de fusion = BT*(2*log M-1 (BT /M)-1) * TempsESBloc = 12*(2*log 2 (12 /3)-1) *11ms = 396 ms
Coût total du tri-fusion externe TempsES (TRI) = 2*(BT /M* TempsPosDébut + BT*TempsTrans) + BT*(2*log M-1 (BT /M)- 1) * TempsESBloc = 104 ms + 396 ms = 500 ms
Tri de Livre Allocation sérielle sans fragmentation interne M = 50 TempsES (TRI) = 29,5 mins
OPÉRATIONS DE JOINTURE Cas de deux tables R|X|S Extension directe à d ’autres cas union, intersection, jointure externe, ...
Jointure par boucles imbriquées Boucles imbriquées par lignes (BI) TempsES (BI) = BR * TempsESBloc+NR*(BS * TempsTrans+ TempsPosDébut) Meilleur cas (Tampon assez grand) : TempsES (BI) = TempsES (BALR) + TempsES (BALS) = (BR + BS) * TempsTrans + 2*TempsPosDébut
BI : Livre |X| Catégorie R=Livre et S=Catégorie TempsES (BI) = 30,57 hrs R = Catégorie et S = Livre TempsES (BI) = 56,57 hrs Meilleur cas (sans relecture) TempsES (BI) = 50 120 ms
Boucles imbriquées par blocs (BIB) TempsES (BIB) = BR * TempsESBloc + BR * (BS * TempsTrans + TempsPosDébut)
BIB: Livre |X| Catégorie R=Livre et S=Catégorie TempsES (BIB) = 100,83 mins R = Catégorie et S = Livre TempsES (BIB) = 83,37 mins Meilleur cas (sans relecture) TempsES (BIB) = 50 120 ms
Boucles imbriquées multi-blocs (BIM) TempsES (BIM) = BR * TempsTrans + BR/(M-2) * TempsPosDébut + BR/(M- 2) * (BS * TempsTrans + TempsPosDébut)
BIM: Livre |X| Catégorie R=Livre et S=Catégorie TempsES (BIM) = 175,04secs R = Catégorie et S = Livre TempsES (BIM) = 150,16secs
Jointure par boucles imbriquées avec index sur la table interne (BII) TempsES (BII) = BR * TempsESBloc + NR * TempsES (Sélection par index)
BII: Livre |X| Catégorie Cas des index primaires R=Livre et S=Catégorie TempsES (BII) = 9,32 hrs R = Catégorie et S = Livre TempsES (BII) = 16,15 mins
Jointure par tri-fusion (JTF) TempsES (JTF) = TempsES (TRIR) + TempsES (TRIS) + 2*(BR + Bs) * TempsESBloc
JTF: Livre |X| Catégorie M = 50 TempsES (JTF) = TempsES (TRILivre) + TempsES (TRICatégorie) + 2*(BLivre + BCatégorie) * TempsESBloc = 2 873 540 ms >>TempsES (BIM) = 150 160 ms (R = Catégorie)
Si 100 fois plus de Catégories M = 50 TempsES (JTF) = 3 444 000 ms < TempsES (BIM) = 10 464 180 ms M = 10 TempsES (JTF) = 6 180 000 ms << TempsES (BIM) = 62 535 000 ms
Optimisation Chercher le meilleur plan d ’exécution? coût excessif Solution approchée à un coût raisonnable Générer les alternatives heuristiques Choisir la meilleure estimation approximative du coût
Plans d'exécutions équivalents Plusieurs arbres algébriques équivalents etc.
Règles d ’équivalences de l ’algèbre relationnelle Eclatement d'une sélection conjonctive (SE) e1 ET e2 (T) = e1 ( e2 (T)) Commutativité de la sélection (SC) e1 ( e2 (T)) = e2 ( e1 (T)) Elimination des projections en cascades (PE) liste1 ( liste2 (T)) = liste1 (T) Commutativité de la jointure (JC) T1 |X| T2 = T2 |X| T1 Associativité de la jointure (JA) T1 |X| (T2 |X| T3) = (T1 |X| T2) |X| T3 Etc …
Plusieurs plans d ’exécution pour un arbre algébrique Pour chaque opération logique plusieurs choix d ’opérations physiques etc.
Mise en œuvre du plan d'exécution Matérialisation des tables intermédiaires Pipeline
MISE EN ŒUVRE PAR MATÉRIALISATION
MISE EN ŒUVRE PAR PIPELINE
Heuristiques d'optimisation Élaguer l ’espace des solutions solutions non applicables Exemples d ’heuristiques sélections le plus tôt possible projections le plus tôt possible arbres biaisés à gauche seulement les jointures les plus restrictives en premier jointures supportées par index en premier
Heuristique : arbres biaisés à gauche seulement Jointure de n tables (2*(n-1))!/(n-1)! ordres différents pour n tables n! biaisés à gauche
Minimiser le coût Stratégies Optimisation par coût programmation dynamique amélioration itérative recuit simulé algorithme génétique
ESTIMATION DU COÛT D'UN PLAN D'EXÉCUTION TempsES(Plan avec pipeline) = TempsES (JTFLivre|X|Catégorie) = 2 873 540 ms
Autre exemple TempsES(Plan avec pipeline) = TempsES(S=IS pour index sur ISBN) + N s ISBN=1(Livre) * TempsES(S=IS sur code de Catégorie) = 55 ms + 33 ms = 88 ms
ESTIMATION DE LA TAILLE DU RÉSULTAT D'UNE OPÉRATION Taille d'une sélection SelT (Expression de sélection)/ FBMT blocs Taille d'une projection N C1,C2,…,Cn(T) = (1- colonnes Ci de la projection (1- FacteurSélectivitéT (Ci)))*NT Taille d'une jointure naturelle NR |X| S = NR * NS / maximum(CardR(cléJointure), CardS(cléJointure))
Contrôle du processus d'optimisation Cas Oracle outils EXPLAIN PLAN SQL Trace SQL Analyse (Enterprise Manager Tuning Pack) Oracle EXPERT
Indices (hints)
Paramètre OPTIMIZER_MODE COST (statistique): minimise le coût estimé besoin de statistiques (ANALYSE) mieux mais plus cher ALL_ROWS minimise le temps total (plutôt MERGE JOIN) FIRST_ROWS minimise temps réponse (plutôt NESTED LOOPS) RULE (heuristique) appelé à disparaître ? (Il semble que oui)
Changement du mode pour une session ALTER SESSION SET OPTIMIZER_GOAL = RULE | ALL_ROWS | FIRST_ROWS | CHOOSE
Exemple d ’utilisation de EXPLAIN PLAN SQL> start utlxplan.sql Pour créer la table plan_table Table created. ... SQL> run 1 explain plan 2 set statement_id = 'com' 3 for select * from commandes, lignes_de_commande 4* where no_commande = commande_no_commande Explained.
Suite SQL> run 1 SELECT LPAD(' ',2*(LEVEL-1))||operation||' '||options 2 ||' '||object_name 3 ||' '||DECODE(id, 0, 'Cost = '||position) "Query Plan" 4 FROM plan_table 5 START WITH id = 0 AND statement_id = 'com' 6* CONNECT BY PRIOR id = parent_id AND statement_id ='com' Query Plan --------------------------------------------- SELECT STATEMENT Cost = NESTED LOOPS TABLE ACCESS FULL LIGNES_DE_COMMANDE TABLE ACCESS BY ROWID COMMANDES INDEX UNIQUE SCAN COMMANDE_PK