Partage
  • Partager sur Facebook
  • Partager sur Twitter

Optimisation requête leftJoin

    21 septembre 2017 à 16:09:39

    Bonjour,

    Je suis sur une base MySQL, et j'effectue cette requête

    SELECT *
    FROM 
      GMO_CMDB_Composant g0_ 
      LEFT JOIN GMO_SAVE_Sauvegarde g1_ ON g0_.id_COMPOSANT = g1_.composant_SAUVEGARDE 
      AND (g1_.date_SAUVEGARDE = ?) 
      LEFT JOIN GMO_CMDB_Correspondance_Systeme_applicatif_composant_client g7_ ON g0_.id_COMPOSANT = g7_.composant_CORRESPONDANCE 
      LEFT JOIN GMO_SAVE_Replication g2_ ON g1_.id_SAUVEGARDE = g2_.sauvegarde_REPLICATION 
      LEFT JOIN GMO_SAVE_Commentaire g3_ ON g1_.id_SAUVEGARDE = g3_.sauvegarde_COMMENTAIRE 
      LEFT JOIN GMO_SAVE_Master g4_ ON g1_.master_SAUVEGARDE = g4_.id_MASTER 
      LEFT JOIN GMO_SAVE_Code_retour g5_ ON g1_.code_retour_SAUVEGARDE = g5_.id_CODE_RETOUR 
      LEFT JOIN GMO_SAVE_Etat g6_ ON g5_.etat_CODE_RETOUR = g6_.id_ETAT 
      INNER JOIN GMO_CMDB_Environnement g8_ ON g7_.environnement_CORRESPONDANCE = g8_.id_ENVIRONNEMENT 
      LEFT JOIN GMO_CMDB_Role_composant g9_ ON g7_.role_CORRESPONDANCE = g9_.id_ROLE_COMPOSANT 
      LEFT JOIN GMO_CMDB_Systeme_applicatif g10_ ON g7_.systeme_applicatif_CORRESPONDANCE = g10_.id_SYSTEME_APPLICATIF 
    WHERE 
      (
        g6_.libelle_ETAT <> ? 
        OR g1_.code_retour_SAUVEGARDE IS NULL
      ) 
      AND g8_.id_ENVIRONNEMENT = ? 
      AND (
        g0_.whitelist_COMPOSANT = ? 
        OR (
          (
            g9_.blacklist_ROLE_COMPOSANT = ? 
            OR g9_.blacklist_ROLE_COMPOSANT IS NULL
          ) 
          AND (g0_.blacklist_COMPOSANT = ?) 
          AND (
            g10_.blacklist_SYSTEME_APPLICATIF = ? 
            OR g10_.blacklist_SYSTEME_APPLICATIF IS NULL
          )
        )
      )

    Celle-ci prend 5000ms à s'effectuer, ce qui est trop long.

    Quand je modifie cette partie de la requête :

    INNER JOIN GMO_SAVE_Sauvegarde g1_ ON g0_.id_COMPOSANT = g1_.composant_SAUVEGARDE 
      AND (g1_.date_SAUVEGARDE = ?) 

    Elle passe à 60ms, ce qui est plus acceptable.

    J'ai changé le LEFT JOIN EN INNER JOIN, mais en faisant ça, je suis susceptible de perdre certaines données.

    Ma table Composant contient 10000 lignes et ma table Sauvegarde 500 000 pour le moment, mais devra pouvoir monter jusqu'à 5 000 000 environ.

     J'aurai aimé savoir pourquoi il y a une telle différence entre les performances des 2 requêtes et comment je pourrais améliorer les performances de la première version (celle avec le LEFT JOIN).

    Merci.

    • Partager sur Facebook
    • Partager sur Twitter
      23 septembre 2017 à 17:57:54

      Salut,

      Le INNER JOIN étant une jointure stricte, il est plus rapide à exécuter car il n'a pas besoin d'étendre les résultats avec des valeurs nulles, et retourne moins de lignes que les LEFT ou RIGHT JOIN (forcément puisque ces dernières gèrent les nulles). Si tu remplaces ta jointure par INNER JOIN, les composants sans sauvegarde ne seront plus traités par ta requête.

      Pour essayer d'améliorer les performances, tu peux déjà commencer par éviter de faire un SELECT * si ce n'est pas nécessaire de sélectionner tous les champs de toutes les tables, car plus tu ramènes de champs, plus ta requête mettra du temps à s'exécuter. C'est même assez catastrophique sur des requêtes avec beaucoup de tables et de données.

      Ensuite vérifie que tes champs soient correctement indexés, notamment ceux qui se trouvent dans les jointures et le where.

      • Partager sur Facebook
      • Partager sur Twitter
        25 septembre 2017 à 11:15:12

        J'ai mis des indexes sur les champs où j'effectue un WHERE, et aussi pour les JOIN.

        Mon problème, c'est que dans mon application, je passe par un ORM (Doctrine2), et je crois bien que je sois obligé de récupérer toutes ces informations, d'où mon SELECT *.

        • Partager sur Facebook
        • Partager sur Twitter

        Optimisation requête leftJoin

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown