IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Optimisation de requête


Sujet :

Requêtes MySQL

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2022
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2022
    Messages : 4
    Points : 1
    Points
    1
    Par défaut Optimisation de requête
    Bonjour - je cherche à optimiser cette requête (index, index bitmap, index de jointure, autre idée ?).
    Pouvez-vous m'aider SVP ?
    Quels index il faudrait utiliser sur des join ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT dept_emp.emp_no, employees.last_name, employees.first_name, departments.dept_name
    FROM dept_emp
    JOIN employees
    ON dept_emp.emp_no = employees.emp_no
    JOIN departments
    ON dept_emp.dept_no = departments.dept_no
    WHERE departments.dept_name = 'Sales' 
    OR departments.dept_name = 'Development';
    Source de la base : https://dev.mysql.com/doc/employee/e...structure.html

    Ou si éventuellement, sur cette bdd, si vous avec une autre requête avec des join déjà optimisée, je suis preneur pour comprendre le principe.

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721
    Points : 1 876
    Points
    1 876
    Par défaut
    Bonjour,

    Si vous avez repris cette structure pour créer les tables, alors vous verrez qu'il y a déjà des index...
    Avant de chercher à "optimiser", il serait bon d'évaluer le niveau de performance actuel pour déterminer ce qui est optimisable...
    Je vous conseille d'étudier la commande explain et aussi de vous familiariser avec le plan d'exécution. Ce sont des notions que l'on retrouve dans les autres systèmes de bases de données.
    Votre intuition est correcte: lorsqu'on fait un join entre deux tables, ça aide énormément de le faire sur des champs indexés. Le scénario que vous voulez éviter dans une requête en général est le "full table scan", autrement dit, la lecture de toute la table sans utilisation d'index.

    Mais ça dépend aussi du volume de données. Si les tables ont peu d'enregistrements, alors la présence d'un index n'apporte pas grand-chose.
    Donc il n'y a pas de réponse toute faite, ça dépend aussi de l'utilisation. Si vous faites des "lookups" ou joins sur d'autres champs, alors il peut s'avérer utile de les indexer aussi, voire même de revoir la structure des tables dans certains cas.

    Si les index accélèrent les recherches, ils ralentissent aussi les mises à jour (insert/update) puisqu'ils doivent suivre les changements dans les données. Les index doivent donc être utilisés avec parcimonie.

    Puisque vous avez un exemple concret: comptez le nombre d'enregistrements dans les tables vs le nombre d'enregistrements retournés par votre requête. Examinez le résultat de la commande explain + le temps écoulé + les index effectivement utilisés. En guise d'exercice, vous pourriez aussi répéter cette opération après avoir supprimé les index pour constater la différence de performance. Encore une fois, elle ne sera pas forcément critique si le volume de données est réduit.

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2022
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2022
    Messages : 4
    Points : 1
    Points
    1
    Par défaut EXPLAIN PLAN
    Super merci pour ce retour.

    J'avais pas précisé, mais j'ai testé effectivement différentes possibilités en regardant à chaque fois le plan d'exécution.
    Mais je n'arrive pas à l'améliorer. J'ai à chaque fois 1 ou plusieurs TABLE ACCESS \ FULL, et un COST élevé.

    Je ne sais pas comment écrire un index de jointure.

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721
    Points : 1 876
    Points
    1 876
    Par défaut
    Le mieux serait peut-être de poster le résultat de la commande explain, et éventuellement donner une idée du volume de données (nombre approximatif d'enregistrements par table) + la requête exacte.
    Dans certains cas, on peut optimiser une requête en la ré-écrivant différemment, parfois en spécifiant soit-même les index (on contourne alors le query optimizer), mais il est aussi possible qu'il n'y a pas de marge d'amélioration dans l'état actuel des choses.
    En pratique on cherche à optimiser les requêtes qui sont "lourdes", ou bien les environnements à forte charge (ex: site E-commerce), on ne se préoccupe pas trop des requêtes qui prennent quelques millisecondes à s'exécuter si le gain en ressources que l'on peut escompter est marginal.

    Un bête truc mais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    WHERE departments.dept_name = 'Sales' 
    OR departments.dept_name = 'Development';
    peut être formulé ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE departments.dept_name IN ('Sales', 'Development')
    C'est un peu plus simple/lisible/flexible, en revanche je n'attends pas de gain de performance en faisant cela, mais il faut expérimenter aussi.

    Je ne sais pas si vous lisez l'anglais technique mais la doc est incontournable: https://dev.mysql.com/doc/refman/8.0...imization.html
    En vérifiant que la doc correspond à la version que vous utilisez.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2022
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2022
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Alors pour les 2 tables 'employees' et 'dept_emp' : 300.000 enregistrements.
    Et table 'departments' : 9 enregistrements.

    Voilà en pdf le plan d'exécution.plan2.pdf

  6. #6
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    Ce sont aussi les cardinalités des employés dans chacun des départements concernés qui pourraient aider.
    Cela permettrait de voir si une UNION ALL (avec un hint de parallélisme si < 12.1, sinon cela devrait être automatique) pourrait aider.

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721
    Points : 1 876
    Points
    1 876
    Par défaut
    Le pdf est parfaitement illisible pour moi, je vois juste une image minuscule. Le mieux est de poster du texte formaté avec la balise code.

    Au fait, je ne sais pas combien d'enregistrements renvoie la requête, mais si vous récupérez disons un tiers de ces 300000 enregistrements que contient la table, alors ça fait quand même un gros volume de données qui doit être extrait, consolidé, puis voyager via une connexion réseau probablement, et cela aussi à un coût.
    On essaie en général de ne récupérer que le volume nécessaire, par exemple en filtrant sur des plages de dates ou des critères additionnels. L'utilisateur ne veut normalement pas consulter 100000 enregistrements en un coup, donc on essaie de filtrer à la source.

    Un petit lien intéressant pour aller plus loin: How to Measure MySQL Query Time: A Detailed Look

    Et pour avoir une idée à l'arrache du volume de trafic réseau engendré: https://serverfault.com/a/530540

    Même sans aller jusque-là, vous pouvez facilement évaluer la taille de vos tables: https://chartio.com/resources/tutori...able-in-mysql/
    Puis vous faire une idée approximative certes mais utile quand même. Si vous récupérez un dixième du contenu de la table, alors pour faire simple considérez que le volume de données extrait équivaut à un dixième de la taille totale de la table.

    Autrement dit, si vous pompez 25 Mb de données à chaque fois (exemple), c'est normal que ce ne soit pas instantané si on tient compte de toutes les étapes, jusqu'à l'affichage des données vers le client de destination. C'est pour cela qu'il est intéressant de faire des mesures et avoir une idée même vague des ressources consommées.

    Une requête "optimisée" mais qui renvoie un nombre délirant d'enregistrements n'est pas une requête rapide ou optimale.

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2022
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2022
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Merci encore

    Voilà l'EXPLAIN PLAN en .xls
    Fichiers attachés Fichiers attachés

  9. #9
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 056
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 056
    Points : 9 394
    Points
    9 394
    Par défaut
    Qui administre ta base de données ; A priori personne, vu qu'on parle de petits volumes.
    Je pense qu'une chose à faire, c'est ceci :
    analyze table xxxx compute statistics.
    En répétant cette commande pour chacune des tables.
    Quand on insère des données dans les tables, au fil du temps, les index peuvent devenir déséquilibrés, peu performants.
    Quand une table fait 300000 lignes, il faut exécuter cette commande de temps en temps, en gros quand il y a 10% des données qui changent (Insert ou delete ou update).

    Tu lances cette commande pour chaque table, puis tu essaies à nouveau ta requête. J'ai vu des cas où on passait de 10sec à 0.1sec, juste avec ces 'analyze table'. Les index étaient devenus tellement dégradés que le moteur Oracle ne les utilisait pas.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  10. #10
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    On est dans le forum ORACLE DB, pas MySQL : il faudrait déplacer la discussion au bon endroit si réellement vous utilisez MySQL, par contre si vous avez vraiment déployer sous ORACLE cet exemple du site MySQL,
    il faudrait aussi donnez la version de votre DB et la description complète des tables concernées.

  11. #11
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Vérifiez que vous avez bien les index suivants :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    X1 : dept_emp (dept_no)
    X2 : employees (emp_no, last_name, first_name)
    X3 : departments (dept_name, dept_no)
    Si tel n'est pas le cas, créées les.

    Il est dommage qu'oracle, toujours très en retard techniquement, n'implémente pas la clause INCLUDE auquel cas il aurait été préférables pour alléger le coût des mises à jour d'avoir les index suvants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    X1 : dept_emp (dept_no)
    X2 : employees (emp_no) INCLUDE (last_name, first_name)
    X3 : departments (dept_name) INCLUDE (dept_no)
    Comme le fait Microsoft SQL Server depuis 18 ans ou PostGreSQL depuis 2/3 ans.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

Discussions similaires

  1. [Access] Optimisation performance requête - Index
    Par fdraven dans le forum Access
    Réponses: 11
    Dernier message: 12/08/2005, 14h30
  2. Optimisation de requête avec Tkprof
    Par stingrayjo dans le forum Oracle
    Réponses: 3
    Dernier message: 04/07/2005, 09h50
  3. Optimiser une requête SQL d'un moteur de recherche
    Par kibodio dans le forum Langage SQL
    Réponses: 2
    Dernier message: 06/03/2005, 20h55
  4. optimisation des requêtes
    Par yech dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 21/09/2004, 19h03
  5. Optimisation de requête
    Par olivierN dans le forum SQL
    Réponses: 10
    Dernier message: 16/12/2003, 10h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo