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

Langage SQL Discussion :

Requête trop lente, comment l'optimiser?


Sujet :

Langage SQL

  1. #1
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut Requête trop lente, comment l'optimiser?
    Bonjour à tous.

    J'ai une requête qui pose problème dans mon programme car elle met bien 30 secondes à s'éxecuter.Cela vient du fait qu'il y a un filtre qui permet de ne pas sélectionner des éléments qui sont dans une liste.
    Mais il y a énormément d'élément à comparer!
    Voici la requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT DISTINCT s.name, u.realname, dl.name 
    FROM software s, users u, computers c, licenses l,inst_software ins, dropdown_locations dl
    WHERE c.contact = u.name
    AND ins.cID = c.ID 
    AND ins.license = l.ID 
    AND l.sID = s.ID 
    AND dl.id = u.location 
    AND s.name 
    NOT IN('³öÆæÖÆʤ£*¸ß¿¼Ó¢Óï','#Supprimé','Acrobat Reader 4.0',
    'WinZip','Windows 2000 Support Tools','Windows 2000 Service Pack 4',
    'Windows 2000 Hotfix Special Release ...........
    le NOT IN continue sur 500 logiciels environ puis fin de la requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ,'Windows Driver Package - FTDI FTDI VCP Driver Package','Windows Driver Package - FTDI CDM Driver Package',' ')
     AND dl.completename 
    IN('Informatique')  
    ORDER BY dl.name,u.realname
    Voila j'aimerais savoir comment rendre cette requête plus rapide.

    Merci d'avance

  2. #2
    Membre expérimenté Avatar de scheu
    Inscrit en
    Juin 2007
    Messages
    1 506
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 1 506
    Points : 1 736
    Points
    1 736
    Par défaut
    sans infos sur le SGBD, les volumétries, les indexes existants, ... etc difficile de deviner

  3. #3
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut
    Citation Envoyé par scheu Voir le message
    sans infos sur le SGBD, les volumétries, les indexes existants, ... etc difficile de deviner
    Désolé
    Le SGBD c'est MySql.
    Qu'entends tu par volumétrie et indexes existants? le nombre d'occurences des tables?

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Execute la requête que tu nous as présentée précédée du mot clé "EXPLAIN" comme celà :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    EXPLAIN SELECT DISTINCT s.name, u.realname, dl.name 
    FROM software s, users u, computers c, licenses l,inst_software ins, dropdown_locations dl
    WHERE c.contact = u.name
    AND ins.cID = c.ID 
    AND ins.license = l.ID 
    AND l.sID = s.ID 
    AND dl.id = u.location 
    AND s.name 
    NOT IN('³öÆæÖÆʤ£*¸ß¿¼Ó¢Óï','#Supprimé','Acrobat Reader 4.0',
    'WinZip','Windows 2000 Support Tools','Windows 2000 Service Pack 4',
    'Windows 2000 Hotfix Special Release ...........
    Explain demande à MySQL d'executer la requête, mais au lieu de retourner le résultat de cette requête, il retourne sa manière de traiter ta requête. Ainsi tu pourras voir apparaître les manques en matière d'indexes.

    Donne le résultat de cette exécution ici.

  5. #5
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut
    Merci de ta réponse.
    Voila le résultat
    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE ins ALL cID,sID NULL NULL NULL 102363 Using temporary; Using filesort
    1 SIMPLE c eq_ref PRIMARY PRIMARY 4 glpidb.ins.cID 1
    1 SIMPLE u ref name,name_2,location name 766 glpidb.c.contact 10 Using where
    1 SIMPLE l eq_ref PRIMARY,sID PRIMARY 4 glpidb.ins.license 1
    1 SIMPLE s eq_ref PRIMARY PRIMARY 4 glpidb.l.sID 1 Using where
    1 SIMPLE dl eq_ref PRIMARY PRIMARY 4 glpidb.u.location 1 Using where
    Désolé, ce n'est pas très lisible...

  6. #6
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Si vous enlevez le distinct, y-a-t-il du mieux ? Et avez vous vraiment besoin du distinct ?

    Tout le reste de la requête (jointures et clause where) s'execute en utilisant des indexes.

  7. #7
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut
    Je gagne 0.4 secondes si j'enleve le distinct...Et je ne pense pas qu'il soit utile au final...

    Mais bon ça n'arrange rien...Une autre idée?

  8. #8
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Si c'est cette liste de valeur dans le <NOT IN> qui pose vraiment problème, il y a quelquechose à tester.

    Vous créez une table temporaire en mémoire. Je ne me rappelle plus la syntaxe exacte MySQL mais je sais que ça existe. Cette table est unique pour chaque connexion donc les utilisateurs n'auront pas de problème de concurrence.

    Cette table contient les valeurs sélectionnées pour votre filtre. Dans votre application, quand les utilisateurs ajoutent un critère, vous l'ajoutez dans cette table. A l'inverse, vous supprimez s'ils déselectionnent le critère.

    Votre requête n'aura plus de NOT IN mais une jointure vers cette table qui sert de filtre.

    Déclarez correctement cette table. Ne stockez que les identifiants sélectionnés, pas les noms, ce sera plus efficace.

  9. #9
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut
    Merci vmolines

    En fait, les filtres sont ajoutés ou retirés par l'administrateur de l'application, et ils valent pour tous les utilisateurs...
    Ces filtres sont enregistrés dans un fichier texte.
    Donc une table commune contenant les logiciels filtrés à la place de ce fichier suffirait...


    Mais ça ne m'arrange pas trop, car cela prendrait du temps pour modifier tout le code, et je dois finir cette apllication au plus vite...

    Je retiens ton idée, au cas ou je ne trouve rien d'autre.
    Une autre idée?

  10. #10
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    - Utilisez s.id au lieu de s.name pour filtrer
    - Exprimez vos jointures avec JOIN

  11. #11
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut
    Je ne peux pas utiliser s.id car le fichier texte ne comprend que l'intitulé.

    Quant à mettre les jointures en join cela m'a fait gagner quelques secondes!
    Merci!
    Par contre ne sachant pas bien manipuler les join, peux-tu me dire si je l'ai fait correctement?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT DISTINCT s.name, u.realname, dl.name
    FROM software s, computers c
    INNER JOIN users u ON c.contact = u.name
    INNER JOIN licenses l ON l.sID = s.ID
    INNER JOIN inst_software ins ON ins.cID = c.ID
    AND ins.license = l.ID
    INNER JOIN dropdown_locations dl ON dl.id = u.location

  12. #12
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    La syntaxe est bonne mais ne connaissant pas la structure de tes tables ni le résultat que tu veux obtenir, je ne peux te dire si ton arbre de jointure est bon.

    Dans les jointures, il est dommage de lier USER à COMPUTER par le nom, ce n'est pas efficace. Il faut utiliser les identifiants pour faire ses liaisons.

    Par contre, ta méthode pour filtrer à partir des noms saisis dans un fichier texte est mauvaise. C'est pas grand chose en développement de lister des identifiants plutôt que des noms.

    Pour tester le gain apporté par un filtrage sur identifiant plutôt que par nom (avant de se lancer dans un dev) :

    - Fais une requête qui ramène les identifiants à partir des noms
    - Modifie ta requête pour qu'elle utilise cette liste d'identifiants
    - Execute et vois le gain apporté.

  13. #13
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut
    oui je sais bien que ce n'est pas une bonne méthode, mais je dois modifier un programme qu'une personne a fait, et elle a choisi de faire comme ça...
    Je n'y suis pour rien!
    Ce ne sont pas les identifiants qui sont listés car le fichier texte alimente une listbox pour les admins...

    Pour la jointure entre user et computer je n'ai pas le choix, car la BDD est généré par un programme (appelé GLPI) et c'est le seul lien qu'il y a entre ces deux tables...
    Je vais essayer de faire ta méthode de récupérer les id des logiciels filtrés puis comparer les id.

    En tout cas merci beaucoup vmolines!

  14. #14
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Je n'avais pas vu la fin de la requête (mauvaise lecture)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    AND dl.completename 
    IN('Informatique')  
    ORDER BY dl.name,u.realname
    Je vous ai fait enlevé le distinct mais testez aussi en enlevant le <ORDER BY>. C'est la dessus que MySQL peine car, sans index sur les champs du order, il doit faire un parcours complet de la table (voir 1ere ligne de l'explain). Si je ne me trompe pas, ça sera bien plus rapide sans le <ORDER BY>, et là on verra comment améliorer.

    Même remarque pour le fitlre sur dl.completename, préférez un identifiant qu'un nom.

  15. #15
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Citation Envoyé par ToutPaumé Voir le message
    oui je sais bien que ce n'est pas une bonne méthode, mais je dois modifier un programme qu'une personne a fait, et elle a choisi de faire comme ça...
    Je n'y suis pour rien!
    Ce ne sont pas les identifiants qui sont listés car le fichier texte alimente une listbox pour les admins...

    ...

    Rien ne vous empèche d'afficher des noms pour les utilisateurs et de stocker/récupérer les identifiants sous jacents pour vous. C'est toujours ainsi qu'il faut procéder. Une fois la sélection de l'utilisateur validée, vous injectez tous les identifiants récupérés dans votre IN.

  16. #16
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    A chaque fois ce sont des hypothèse que je fais. Ce serait plus facile avec la description des tables présentes dans la requête et les liens entre elles. Vous devez toujours donner la structure de vos tables quand vous demandez de l'aide.

  17. #17
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut
    Ok désolé...
    J'y penserais la prochaine fois!
    Je vais essayer de récupérer l'ID a la place du completename.
    Mais c'est déjà un peu plus rapide comme ça.Merci!

  18. #18
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Il ne faut pas que ce soit "un peu plus rapide". Une requête comme celle là devrait avoir un temps d'execution ridicule. Quelques secondes, c'est déjà trop je trouve.

  19. #19
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 879
    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 879
    Points : 53 057
    Points
    53 057
    Billets dans le blog
    6
    Par défaut
    Faîtes comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TABLE application (NOM VARCHAR(256) PRIMARY KEY)
    au besoin par une table temporaire locale

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    INSERT INTO application  VALUES ('³öÆæÖÆʤ£*¸ß¿¼Ó¢Óï')
    INSERT INTO application  VALUES (','#Supprimé')
    INSERT INTO application  VALUES ('Acrobat Reader 4.0')
    INSERT INTO application  VALUES ('WinZip')
    ...
    INSERT INTO application  VALUES ('Windows Driver Package - FTDI CDM Driver Package')

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SELECT DISTINCT s.name, u.realname, dl.name 
    FROM   software s
           INNER JOIN licenses l
              ON l.sID = s.ID 
           INNER JOIN inst_software ins
              ON ins.license = l.ID 
           INNER JOIN computers c
              ON ins.cID = c.ID 
           INNER JOIN users u
              ON c.contact = u.name
           INNER JOIN dropdown_locations dl
              ON dl.id = u.location
    WHERE  s.name NOT IN (SELECT NOM 
                          FROM  application )
    -- vérifiez la présence des index suivants :
    software (id)
    licenses (sid) (id)
    inst_software (licence) (cid)
    computers (id) (contact)
    users (name) (location)
    dropdown_locations (id)


    A +

  20. #20
    Membre confirmé Avatar de getz85
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2008
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2008
    Messages : 423
    Points : 462
    Points
    462
    Par défaut
    Merci SQL Pro.

    Même sans crééer de table application (ce qui serait long et fastidieux étant donné le nombre de logiciel à filtrer), la requête s'execute beaucoup plus rapidement maintenant.
    Les indexs sont bien tous présents.

Discussions similaires

  1. Optimisation de requêtes trop lentes..
    Par Nevrosl dans le forum Requêtes
    Réponses: 5
    Dernier message: 11/03/2010, 13h38
  2. Réponses: 21
    Dernier message: 03/08/2009, 13h32
  3. requête trop lente
    Par smaildba dans le forum SQL
    Réponses: 9
    Dernier message: 20/04/2009, 12h20
  4. Requête trop lente
    Par shadeoner dans le forum SQL
    Réponses: 11
    Dernier message: 23/05/2008, 10h24
  5. auto-killer une requête trop lente
    Par Nico57 dans le forum Oracle
    Réponses: 5
    Dernier message: 05/12/2006, 18h04

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