Évaluation des requêtes relationnelles
Concepts de base
Requête interne
Optimisation statique ou dynamique à chaque exécution EXECUTE IMMEDIATE de SQL Statique compilation PREPARE de SQL plusieurs exécutions EXECUTE réoptimisation automatique suite à modification de schéma interne?
Décomposition 1) Analyse syntaxique 2) Analyse sémantique 3) Résolution des vues 4) Simplification syntaxique 5) Simplification sémantique
Estimation du coût des opérations physiques TempsES : temps d’accès à mémoire secondaire (MS) TempsUCT souvent négligeable TailleMC : espace mémoire centrale TailleMS : espace mémoire secondaire
Modèle du coût d'une entrée-sortie en mémoire secondaire TempsESBloc = TempsESDisque(TailleBloc) = TempsPosDébut + TempsTrans (TailleBloc) TempsTrans (TailleBloc) = TailleBloc / TauxTransVrac
Statistiques au sujet des tables
Statistiques (suite)
Statistiques (suite)
Maintien des statistiques par le SGBD Coût inversement relié à la précision Mise à jour incrémentale à chaque mise à jour Mise à jour en différé périodes de faible activité déclenchement contrôlé par ABD Estimation par échantillonnage tables très volumineuses Commande ANALYSE (Oracle) contrôle du déclenchement paramètres d ’échantillonnage
Coût des opérations de base Algèbre physique Hypothèses Néglige effet de l ’antémémoire 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 FBEditeur = FBMEditeur = 60 BEditeur = NEditeur / FBEditeur = 50/ 60 = 1 bloc TempsES (BALEditeur) = BEditeur * TempsTrans + NombrePos * TempsPosDébut TempsES (BALEditeur) = 11 ms
Exemple : TempsES (BALCatégorie) Allocation sérielle sans fragmentation interne FBCatégorie= FBMCatégorie= 40 BCatégorie = NCatégorie / FBCatégorie = 4 000/ 40 = 100 blocs Meilleur cas : TempsES (BALCatégorie) = BCatégorie* TempsTrans + NombrePos * TempsPosDébut = 100 * 1 ms + 1 * 10 ms = 110 ms Pire cas : TempsES (BALCatégorie) = 100 * 1 ms + 100 * 10 ms = 1 100 ms
Exemple : TempsES (BALLivre) Allocation sérielle sans fragmentation interne FBLivre= FBMLivre= 20 BLivre = NLivre/ FBLivre = 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) ! TempsES (BALLivre) = BLivre* TempsTrans + NombrePos * TempsPosDébut = 76 924* 1ms + 76 924 * 10ms = 848 164 ms = 14,1 minutes
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 Estimation de HauteurI Cas d’une clé candidate TempsES (S=IP sur clé candidate)=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é primaire ) 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 (clé primaire) 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
Taille de l'index primaire TailleMS(IP) = TailleIndexInterne + Blivre FBT = 2/3 FBMT BT = NT/ FBT TailleIndexInterne CardT(CléIndex)/ OrdreMoyenI
Index primaire sur code de Livre FBLivre = 2/3*FBMLivre = 13 BLivre = NLivre/ FBLivre = 1 000 000/ 13 = 76 924 blocs TailleIndexInterne CardLivre (code)/ OrdreMoyenI = 61 blocs TailleMS(IP) = TailleIndexInterne + BLivre 76 985 blocs 50 000 blocs pour allocation sérielle
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 sans relecture de blocs Éviter de relire les blocs de données de l ’organisation primaire Nombre moyen de blocs à lire : (1- (1- FacteurSélectivitéT (CléIndex))FB )* BT
Estimation de HauteurI pour index secondaire Hypothèses clés répétées OrdreMoyen = FB 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
Taille de l'index secondaire Index secondaire code de Livre (clé étrangère) TailleMS(IS) = NLivre / OrdreMoyenI = 15 152 blocs ~ 1/3 taille de la table ! TailleMS(IS) (15 152) + BLivre (50 000)< TailleMS(IP) (76 985)
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
Sélection par intervalle dans un index arbre-B+ secondaire (S>IS) ~ clé non unique
Sélection par égalité avec hachage (S=H) Hachage statique + chaînage TempsES (S=H) = NT/( THT* FBT) * TempsESBloc
Hachage sur ISBN de Livre (clé primaire) Hypothèse ~ idéale TR = 80% FBLivre = 0,8* FBMLivre = 16 THLivre = NLivre/ FBLivre = 62 500 blocs pas de débordements TempsES (S=H) = 1 000 000/( 62 500* 16) * 11ms =11 ms TempsES (S=IP) = HauteurI *TempsESBloc = 44 ms
Hachage sur code de Livre (clé étrangère) Hypothèse ~ idéale THLivre = CardLivre(code) = 4 000 FBLivre = FBMLivre = 20 TempsES (S=H) = 1 000 000/( 4 000 * 20) * 11ms = 143 ms TempsES (S=IP) = 242 ms
Taille de l'organisation par hachage TailleMS(S=H) = NT/FBT Hachage sur ISBN de Livre (clé primaire) Hypothèse ~ idéale TailleMS(S=H) = THLivre = NLivre/ FBLivre = 62 500 blocs
Sélection par clé composée Hypothèse de distribution indépendante FacteurSélectivitéT(C1 = V1 et C2 = V2 et… et Cn = Vn) = FacteurSélectivitéT (C1)* FacteurSélectivitéT (C2) * …* FacteurSélectivitéT (Cn)
Index secondaire sur clé composée {code, annéeParution} de Livre HauteurI = log33(1 000 000) = 4 FacteurSélectivitéLivre(code = V1 et annéeParution = V2) = FacteurSélectivitéLivre (code)* FacteurSélectivitéLivre (annéeParution) = 1/CardLivre (code) * 1/CardLivre (annéeParution) = 1/200 000 SelLivre (code = V1 et annéeParution = V2)= NLivre/ 200 000 = 5 lignes TempsES (S=IS) = (HauteurI - 1) * TempsESBloc + SelLivre (code = V1 et annéeParution = V2)/ OrdreMoyenI *TempsESBloc + SelLivre (code = V1 et annéeParution = V2) * TempsESBloc TempsES (S=IS) = 3 * 11 ms + 5/ 33 *11 ms + 5 * 11 ms = 99 ms
Index secondaire sur clé composée {code, annéeParution} de Livre HauteurI = log33(1 000 000) = 4 TempsES (S=IS) = (HauteurI - 1) * TempsESBloc + SelLivre ({code, annéeParution} [{unCode, min} .. {unCode, max}])/ OrdreMoyenI *TempsESBloc + SelLivre ({code, annéeParution} [{unCode, min} .. {unCode, max}]) * TempsESBloc FacteurSélectivitéLivre({code, annéeParution} [{unCode, min} .. {unCode, max}]) ~ FacteurSélectivitéLivre(code) = 1/4 000 TempsES (S=IS) = 2 827ms (idem index sur code seul)
Index secondaire sur clé composée {code, titre} de Livre HauteurI = log6(1 000 000) = 8 TempsES (S=IS) = 3 289 ms
ORGANISATIONS HÉTÉROGÈNES Adapter les formules facteur de blocage doit tenir compte de la présence de plusieurs tables
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
Tri fusion externe Étape tri 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
SÉLECTION CONJONCTIVE PAR INTERSECTION (SÇ) Index I1 sur code Index I2 sur annéeParution TempsES(S) = TempsES(Extraction de la liste des références de I1) + TempsES(Extraction de la liste des références de I2) + TempsES(Lecture des blocs de données)
Suite > TempsES (S=IS pour index I1) = 2 827 ms TempsES(Extraction de la liste des références de I1) = (HauteurI1 - 1) * TempsESBloc + SelLivre (code = Valeur)/ OrdreMoyenI *TempsESBloc = 77 ms TempsES(Extraction de la liste des références de I2) = (HauteurI2 - 1) * TempsESBloc + SelLivre (annéeParution = Valeur)/ OrdreMoyenI *TempsESBloc = 3 377 ms TempsES(Lecture des blocs de données) = SelLivre (code = V1 et annéeParution = V2)*TempsESBloc = 55 ms TempsES(S) = 3 509 ms > TempsES (S=IS pour index I1) = 2 827 ms
Si CardLivre (annéeParution) = 100 TempsES(S) = 1809,5 ms < TempsES (S=IS pour index I1) = 2 827 ms
SÉLECTION DISJONCTIVE PAR UNION (SÈ) FacteurSélectivitéT(C1 = V1 ou C2 = V2 ou… ou Cn = Vn) = 1-((1-FacteurSélectivitéT (C1))* (1-FacteurSélectivitéT (C2)) * …* (1-FacteurSélectivitéT (Cn)))
OPÉRATIONS DE JOINTURE Cas de deux tables RS 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 (antémémoire suffisamment grande) : TempsES (BI) = TempsES (BALR) + TempsES (BALS) = (BR + BS) * TempsTrans + 2*TempsPosDébut
BI : Livre 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 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 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: LivreCatégorie Cas des index primaires R=Livre et S=Catégorie TempsES (BII) = BLivre * TempsESBloc + N Livre * TempsES(S=IPCatégorie pour l'index primaire sur code) = 9,32 hrs R = Catégorie et S = Livre TempsES (BII) = B Catégorie * TempsESBloc + N Catégorie * TempsES(S=IPLivre pour l'index primaire sur code) = 16,15 mins
Contexte avantageux pour BII Jointure sélective Peu de mémoire vive
TempsES (BIH) = BR * TempsESBloc + NR * TempsES(Sélection par hachage) Jointure par boucles imbriquées avec hachage sur la table interne (BIH) TempsES (BIH) = BR * TempsESBloc + NR * TempsES(Sélection par hachage)
BIH: LivreCatégorie R=Livre et S=Catégorie TempsES (BIH) = BLivre * TempsESBloc + N Livre * TempsES(S=HCatégorie pour hachage sur code) = 3,21 hrs R = Catégorie et S = Livre TempsES (BIH) = BCatégorie * TempsESBloc + NCatégorie* TempsES(S=HLivrepour hachage sur code)= 11,75 mins
Jointure par tri-fusion (JTF) TempsES (JTF) = TempsES (TRIR) + TempsES (TRIS) + 2*(BR + Bs) * TempsESBloc
JTF: LivreCaté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
Jointure par hachage (JH) Égalité seulement 1- Partition des tables (Si h [0..n-1], M ≥ n)
Jointure par hachage (suite) Jointure par itération sur les parties TempsES (JH) = TempsES (BALR) + TempsES (BALs) + 2 * (BR + Bs) *TempsESBloc Hypothèse : taille de R < taille de S taille de Ri M blocs
Hachage récursif Si M < Ri (~ BR /M ) Si BR M hacher récursivement ~log M (BR)-1 passes ne dépend que de la plus petite table TempsES (JH) = TempsES (BALR) + TempsES (BALs) + 2 * (BR + Bs) * log M (BR)-1 *TempsESBloc Si BR M TempsES (JH) = TempsES (BALR) + TempsES (BALs)
JH: LivreCatégorie R = Catégorie (la plus petite table) M = 50 TempsES (JH) = 1 152 320 ms >TempsES (BIM) = 150 160 ms (R = Catégorie) < TempsES (JTF) = 3 444 000 ms
Si 100 fois plus de Catégories R = Catégorie (la plus petite table) M = 50 TempsES (JH) = 2 700 020 ms << TempsES (BIM) = 10 464 180 ms (R = Catégorie)
Pré-jointure par une organisation hétérogène (PJ) sériel par grappe index primaire hachage TempsES (PJ) ~ TempsES (BALR) + TempsES (BALs) meilleur cas pas de fragmentation interne...
PJ: LivreCatégorie TempsES (PJ) = 50 120 ms meilleur cas
Comparaison des méthodes de jointure BIM une des deux tables est petite JTF 2 grandes tables nombre de passes de tri dépend de la plus grande table ordre intéressant JH nombre de passes ne dépend que de la plus petite table BII ou BIH utilisation partielle d’une des deux tables PJ optimal pour jointure si peu de fragmentation interne pénalise opérations sur une table
AGRÉGATION, ÉLIMINATION DES DOUBLES, OPÉRATIONS ENSEMBLISTES Principe général appariement de lignes sur valeurs communes Adapter les algorithmes de jointure et estimation de coût
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) T1T2 = T2T1 Associativité de la jointure (JA) T1 (T2T3) = (T1T2) T3
Suite Commutativité restreinte de la sélection et de la jointure (CSJ) e (T1 T2) = e (T1) T2 si l'expression de sélection e ne contient que des colonnes de T1 Commutativité restreinte de la projection et de la sélection (CPS) listeColonnes ( e (T)) = listeColonnes ( e ( listeColonnes colonnes de e T)) Commutativité restreinte de la projection et de la jointure (CPJ) listeColonnes (T1 T2) = listeColonnes ( listeColonnes colonnes de T1(T1) listeColonnes colonnes de T2(T2)) 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
Réalisation des opérations par itérateur Interface standard Ouvrir déclenche l’opération Suivant produit la ligne suivante Fermer termine l ’opération Certaines opérations moins adaptées ex: Ouvrir pour le tri-fusion tri des deux tables…
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 plus restrictives en premier jointures supportées par index, hachage ou grappe 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
Optimisation heuristique Oracle mode RULE
Optimisation par coût Minimiser le coût Stratégies 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 (JTFLivreCatégorie) = 2 873 540 ms
Autre exemple TempsES(Plan avec pipeline) = TempsES(S=IS pour index sur ISBN) + N s ISBN=1000 Œuvre * 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 S = NR * NS / maximum(CardR(cléJointure), CardS(cléJointure))
VARIATIONS DU MODÈLE D'ESTIMATION DU COÛT Simplification nombre de blocs à transférer Jointures taille du résultat Contexte réparti seulement coût de transfert entre sites Hypothèses sur distributions Coût UCT
Contrôle du processus d'optimisation Cas Oracle outils EXPLAIN PLAN SQL Trace Oracle EXPERT HINTS pour forcer l ’utilisation d ’un chemin SELECT /*+ INDEX(EMPLOYÉ INDEX_SEXE)*/ FROM EMPLOYÉ WHERE SEXE = ‘F’
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
Paramètre OPTIMIZER_MODE COST (statistique): minimise le coût estimé besoin de statistiques (ANALYSE) plus précis plus coûteux RULE (heuristique) appelé à disparaître ?
OPTIMIZER_GOAL ALTER SESSION SET OPTIMIZER_GOAL = RULE ALL_ROWS minimise le temps total (plutôt MERGE JOIN) FIRST_ROWS minimise temps réponse (plutôt NESTED LOOPS) CHOOSE