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

 MySQL Discussion :

Optimisation requête lourde


Sujet :

MySQL

  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 62
    Par défaut Optimisation requête lourde
    Bonjour,

    Je suis assez embêté par le temps de chargement beaucoup trop de long de mes pages. En effet, via PHP je dois générer un tableau dynamique et afficher des informations pour chaque article dans le tableau.
    Pour se faire j'ai créé une abomination que voici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    (SELECT r.article_id, a.titre, a.texte, r.ss_titre, r.lieu_id, d.date1, d.date2
    FROM ARTICLES a
    INNER JOIN RENSEIGNEMENTS r ON a.id = r.article_id
    INNER JOIN DATES d ON r.date_id = d.id
    WHERE a.edition IN ('NANCY', 'NANCY-METZ', 'NANCY-METZ-STRASB', 'NANCY-METZ-STR-DIJON', 'TTES EDITIONS')
    AND a.rubrique = 'EXPOS'
    AND d.date1 = ( SELECT MIN( d1.date1 ) 
                           FROM ARTICLES a1
                           INNER JOIN RENSEIGNEMENTS r1 ON a1.id = r1.article_id
                           INNER JOIN DATES d1 ON r1.date_id = d1.id
                           WHERE a1.titre = a.titre )
    GROUP BY a.titre)
    UNION ALL
    (SELECT id, titre, texte, null, null, 9999, null 
    FROM ARTICLES a 
    WHERE id NOT IN (SELECT a.id FROM ARTICLES a, RENSEIGNEMENTS r WHERE a.id=r.article_id) 
    AND a.edition IN ('NANCY', 'NANCY-METZ', 'NANCY-METZ-STRASB', 'NANCY-METZ-STR-DIJON', 'TTES EDITIONS') 
    AND a.rubrique = 'EXPOS') 
    ORDER BY date1
    En fait certains articles n'ont pas certaines informations, du coup cela rend la requête beaucoup plus compliquée. La première partie récupère les articles classiques et les trie par date (en prenant la date minimum disponible pour l'article, car un article peut avoir plusieurs dates) et la deuxième partie récupère ceux à part, qui n'ont pas de date.

    Du coup comme je n'ai pas trouvé comme faire les deux requêtes en même temps, j'ai utilisé un UNION ALL

    Si quelqu'un a une idée pour rendre plus simple le bouzin je suis preneur.

    Merci

  2. #2
    Membre Expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Par défaut
    Saluton,
    Il me semble qu'il te suffit de remplacer les INNER JOIN de la première requête par des LEFT JOIN et tu n'auras plus besoin de faire la deuxième requête donc l'UNION
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  3. #3
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 059
    Par défaut
    Attention quand même à la condition dans le WHERE qui porte sur la date. Elle casse à elle seule l'effet des LEFT JOIN.
    Il faudra peut-être la passer en condition de jointure, ou alors l'améliorer par un OR...
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  4. #4
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 62
    Par défaut
    Oui c'est ce que je me disais... Qu'entends tu par conditions de jointure ou amélioration par un OR ? Tu pourrais développer ?

  5. #5
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 059
    Par défaut
    Pour que la jointure externe fonctionne, il faut passer la condition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    AND d.date1 = ( SELECT MIN( d1.date1 ) 
                           FROM ARTICLES a1
                           INNER JOIN RENSEIGNEMENTS r1 ON a1.id = r1.article_id
                           INNER JOIN DATES d1 ON r1.date_id = d1.id
                           WHERE a1.titre = a.titre )
    dans la jointure sur la table DATES.
    Ou alors, il faut modifier la condition par quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    AND (
        d.date1 = ( SELECT MIN( d1.date1 ) 
                           FROM ARTICLES a1
                           INNER JOIN RENSEIGNEMENTS r1 ON a1.id = r1.article_id
                           INNER JOIN DATES d1 ON r1.date_id = d1.id
                           WHERE a1.titre = a.titre )
        OR d.date1 IS NULL
    )
    A tester...
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  6. #6
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 62
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SELECT r.article_id, a.titre, a.texte, r.ss_titre, r.lieu_id, d.date1, d.date2
    FROM ARTICLES a
    LEFT JOIN RENSEIGNEMENTS r ON a.id = r.article_id
    LEFT JOIN DATES d ON r.date_id = d.id
    WHERE a.edition IN ('NANCY', 'NANCY-METZ', 'NANCY-METZ-STRASB', 'NANCY-METZ-STR-DIJON', 'TTES EDITIONS')
    AND a.rubrique = 'EXPOS'
    AND (
        d.date1 = ( SELECT MIN( d1.date1 ) 
                           FROM ARTICLES a1
                           LEFT JOIN RENSEIGNEMENTS r1 ON a1.id = r1.article_id
                           LEFT JOIN DATES d1 ON r1.date_id = d1.id
                           WHERE a1.titre = a.titre )
        OR r.article_id IS NULL
    )
    GROUP BY a.titre
    ORDER BY date1
    A partir de ça j'ai effectivement ce que je veux, le soucis c'est que les articles sans date sont au début (à cause de l'order by normal) Pour le coup je vois pas comment faire à part mettre une valeur de base dans date1 pour les articles sans date

    EDIT : Merci !

  7. #7
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 059
    Par défaut
    Tu peux utiliser la fonction COALESCE dans le ORDER BY, en mettant une date dans le futur. Ça placera les dates à NULL en fin de liste.
    COALESCE prend les arguments qui lui sont passés dans l'ordre et renvoie le premier non null. Ainsi, en mettant une date dans le futur, si la date est à NULL, c'est la date future qui est renvoyée dans le ORDER BY, et les NULL se retrouvent à la fin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT...
    FROM...
    WHERE...
    ORDER BY COALESCE(d.date1, '2050-12-31')
    Bien sûr, il faudra penser à mettre à jour ta requête en 2050
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  8. #8
    Membre Expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Par défaut
    Citation Envoyé par ced Voir le message
    Bien sûr, il faudra penser à mettre à jour ta requête en 2050
    Pas de problème, Ced, si Alzheimer ou tout autre épée de Damoclès ne m'a pas dégommé d'ici là, je le lui rappellerai.
    Après tout, je n'aurai qu'à peine 99 ans !
    L'espoir fait vivre.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Optimiser une requête lourde
    Par Sango64 dans le forum Langage SQL
    Réponses: 20
    Dernier message: 21/06/2013, 15h46
  2. Optimiser requête lourde (Copying to tmp table ?)
    Par JerryOne3 dans le forum Requêtes
    Réponses: 2
    Dernier message: 20/09/2011, 10h13
  3. Comment optimiser une lourde requête avec des index
    Par Romalafrite dans le forum Requêtes
    Réponses: 10
    Dernier message: 01/12/2006, 19h18
  4. optimisation requête
    Par alex2205 dans le forum Décisions SGBD
    Réponses: 5
    Dernier message: 09/02/2005, 14h15
  5. optimisation requête SQL!!! help!!
    Par anathem62 dans le forum Requêtes
    Réponses: 2
    Dernier message: 24/05/2004, 16h26

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