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 :

Question performance et "taille" d'une requête


Sujet :

Requêtes MySQL

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    260
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 260
    Points : 131
    Points
    131
    Par défaut Question performance et "taille" d'une requête
    Bonjour,

    Je viens parler d'un problème que je ne maitrise pas du tout, en fait c'est pas vraiment un problème c'est surtout des questions, si quelqu'un pouvait me donner des idées ou des liens, vu que je n'ai rien trouvé sur le net jusqu'à présent... :

    - La première chose que j'aimerais savoir, c'est à partir de quel moment on peut considérer qu'une requête est "trop lourde" à executer, c'est à dire, mes requêtes s'executent plutôt pas mal en local avec une 100aine de lignes, mais qu'est ce qui me dit qu'en serveur distant et avec 200 000 lignes voire plus...

    Exemple : une requête du type :

    union (pour faire une requête du type "FULL OUTER JOIN") de :
    - jointure externe droite (RIGHT OUTER JOIN) d'une table avec une union de deux autres tables dont un prédicat avec requête imbriquée + une autre jointure (aie aie aie c'est pas clair)...
    - jointure externe gauche (LEFT OUTER JOIN) de la même chose

    Pour essayer de faire comprendre ce que je dit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT ... FROM 
    (SELECT ... FROM ... UNION SELECT ... FROM WHERE C=(SELECT C FROM ...)) T
    JOIN ... ON ...
    LEFT JOIN ... ON ...
    UNION
    SELECT ... FROM 
    (SELECT ... FROM ... UNION SELECT ... FROM WHERE C=(SELECT C FROM ...)) T
    JOIN ... ON ...
    RIGHT JOIN ... ON ...
    Désolé pour le peu de clarté mais je vois pas comment vous l'expliquer autrement...

    - deuxième question, lors d'une union, est-ce qu'il vaut mieux faire les filtre avant l'union dans chaque select, ou les faire sur le résultat de l'union si c'est possible :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ... FROM ...  WHERE C=1
    UNION 
    SELECT ... FROM ... WHERE C=1
    ou plutôt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT ... FROM (SELECT ... FROM ... 
    UNION 
    SELECT ... FROM ... ) T
    WHERE C = 1
    Bon déjà ces deux questions, si jamais j'ai des réponses peut être que je demanderais des petits compléments...

    Merci d'avance à ceux qui auront lu au moins lol

  2. #2
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    Citation Envoyé par RR instinct
    Bonjour,

    Je viens parler d'un problème que je ne maitrise pas du tout, en fait c'est pas vraiment un problème c'est surtout des questions, si quelqu'un pouvait me donner des idées ou des liens, vu que je n'ai rien trouvé sur le net jusqu'à présent... :

    - La première chose que j'aimerais savoir, c'est à partir de quel moment on peut considérer qu'une requête est "trop lourde" à executer,
    à partir du moment où l'utilisateur en a marre d'attendre
    Citation Envoyé par RR instinct
    c'est à dire, mes requêtes s'executent plutôt pas mal en local avec une 100aine de lignes, mais qu'est ce qui me dit qu'en serveur distant et avec 200 000 lignes voire plus...
    Impossible à savoir à moins de tester en vrai. Cela dépend du serveur, de son utilisation (dédié ou partagé), du nombre d'utilisateurs concurrents, etc.
    Citation Envoyé par RR instinct
    Exemple : une requête du type :

    union (pour faire une requête du type "FULL OUTER JOIN") de :
    - jointure externe droite (RIGHT OUTER JOIN) d'une table avec une union de deux autres tables dont un prédicat avec requête imbriquée + une autre jointure (aie aie aie c'est pas clair)...
    - jointure externe gauche (LEFT OUTER JOIN) de la même chose
    (...)
    Désolé pour le peu de clarté mais je vois pas comment vous l'expliquer autrement...
    en gros, le premier piège est que l'UNION est DISTINCT par défaut ; or le DISTINCT est une opération très lourde. Tu as donc intérêt à utiliser un UNION ALL :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT...
    FROM T1 LEFT OUTER JOIN T2...
    UNION ALL
    SELECT...
    FROM T1 RIGHT OUTER JOIN T2...
    WHERE T1.ID IS NULL
    Pour ce qui est de ta sous-requête, a priori l'optimisation faite par MySQL n'est pas terrible, et peut même être catastrophique si la sous-requête est corrélée... si tu peux, tu as intérêt à réécrire tes requêtes autrement, au moins à titre de test.

    Citation Envoyé par RR instinct
    - deuxième question, lors d'une union, est-ce qu'il vaut mieux faire les filtre avant l'union dans chaque select, ou les faire sur le résultat de l'union si c'est possible :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ... FROM ...  WHERE C=1
    UNION 
    SELECT ... FROM ... WHERE C=1
    ou plutôt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT ... FROM (SELECT ... FROM ... 
    UNION 
    SELECT ... FROM ... ) T
    WHERE C = 1
    A priori, il est préférable de faire le WHERE sur chaque table, afin d'utiliser les index et de minimiser le boulot de l'UNION. Enfin, là encore, tu as plutôt intérêt à utiliser UNION ALL, sauf si tu as vraiment des doublons à éliminer.
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    260
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 260
    Points : 131
    Points
    131
    Par défaut
    Hey merci pour la réponse aussi complète

    Je ne savais pas pour l'UNION, il s'avère que le distinct ne doit pas me servir (je pensais que si pour le jointure externe mais le squelette que tu m'as donné doit être encore plus performant

    Une petite précision, qu'appelle tu une requête correllée ? Je crains qu'elle le soit mais au risque de dire une grosse bêtise je vais plutôt attend que tu m'eclaircisse de ta lanterne

    Mais dans ce cas j'ai pas d'autres solutions... tant pis...

    Merci beaucoup.

  4. #4
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    Citation Envoyé par RR instinct
    Une petite précision, qu'appelle tu une requête correllée ?
    Une requête corrélée, ça ne veut rien dire. Une SOUS-requête corrélée, c'est une sous-requête avec une condition qui fait référence à une valeur de la requête principale.

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -- sous-req sans corrélation :
    SELECT Article, Prix
    FROM Articles
    WHERE Prix > (SELECT AVG(Prix) FROM Articles)
    
    -- sous-req corrélée :
    
    SELECT Categ, Article, Prix
    FROM Articles A
    WHERE Prix > (SELECT AVG(Prix) FROM Articles A2 WHERE A2.Categ = A.Categ)
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    260
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 260
    Points : 131
    Points
    131
    Par défaut
    Aie c'est bien ce qui me semblait... je vais essaye de trouver une solution mais c'est pas gagné... tant pis sinon...

    Merci pour toutes ces précieuses infos

  6. #6
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 281
    Points : 11 737
    Points
    11 737
    Par défaut
    Par exemple, ma sous-requête corrélée ci-dessus peut être remplacée par un alias de table :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT A.Categ, A.Article, A.Prix
    FROM Articles A
      INNER JOIN Articles A2 ON A2.Categ = A.Categ
    GROUP BY A.Categ, A.Article, A.Prix
    HAVING A.Prix > AVG(A2.Prix)
    ou encore par une table virtuelle (sous-requête dans le FROM) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT A.Categ, A.Article, A.Prix
    FROM Articles A
      INNER JOIN (
        SELECT Categ, AVG(Prix) AS PxMoy
        FROM Articles 
        GROUP BY Categ
        ) A2 ON A2.Categ = A.Categ
    WHERE A.Prix > A2.PxMoy
    Mais ce n'est qu'un exemple, il y a des cas où on ne peut pas trop faire autrement.
    Antoun
    Expert Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    260
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 260
    Points : 131
    Points
    131
    Par défaut
    Je remet le sujet en "non résolu" pour une petite précision, il me semble que le group by nuit aussi fortement aux performances car j'en avais dans ma requête et sur une grosse quantité de données, celle ci prenait enormément de temps (1 dixième pour une 50 aine de lignes, 5 secondes pour environ 1000 lignes, et j'ai pas laissé finir pour 25 000 lignes parce que ca a tourné pendant 30 minutes).

    Peut être que ma requête était mal structurée (certainement même) mais en ajoutant un sum() et donc un group by, la requête met beaucoup plus de temps pour s'executer...

    Donc je me demande si une sous-requête correllée n'est pas préfèrable ? (après je sais pas du tout c'est juste une constation qui peut s'avérée fausse)...

    Dès que j'ai le temps j'essaie de changer la sous requête et j'en dirais plus sur "l'expérience"

    En tout cas merci encore pour les précisions

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

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