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 :

Comment optimiser une lourde requête avec des index


Sujet :

Requêtes MySQL

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 270
    Points : 163
    Points
    163
    Par défaut Comment optimiser une lourde requête avec des index
    Bonjour à tous.

    Grosso modo j'ai une grosse requête qui fait ceci :

    SELECT les commandes ORDER BY date DESC LIMITE AUX 20 premiers

    sauf que comme il y a des milliers de résultats, il prend l'ensemble des résultats, les retourne puis ensuite filtre les 20 premiers, ce qui a pour conséquence de faire une requête extrêmement longue (7 secondes).

    Comment optimiser ça et où placer mes index (on m'a parlé d' "index composé" ?)

    Vous pourrez voir le début de notre conversation à cette adresse :

    http://www.webrankinfo.com/forums/vi...c.php?p=610321

    Mais il est vrai que WRI est plus une communauté de référenceurs que de férus de MySQL.

    Merci de votre aide, donc.

  2. #2
    Membre habitué Avatar de avogadro
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 412
    Points : 188
    Points
    188
    Par défaut
    et si tu fais une view avec les 20 premieres résultats, la view est créé une seul fois, et apres tu n'a plus qu'a l'afficher, et des que tu modifies des infos sur la table auquel elle fait référence elle se met toute seul a jour (je crois)

    Pour créer une vue vous devez utiliser CREATE VIEW


    CREATE [OR REPLACE] VIEW
    [FORCE|NOFORCE] viewname
    [(alias)]
    AS subquery
    [WITH CHECK OPTION [CONSTRAINT constraint]
    [WITH READ ONLY [CONSTRAINT constraint];

    OR REPLACE: Recrée la vue si elle existe.

    FORCE: Crée une vue même si la table n’existe pas.

    NOFORCE: Crée une vue seulement si la table existe.

    Viewname: Nom de la vue.

    Alias: Spécifie des noms pour les expressions sélectionnées

    Subquery: La requête SELECT complète.

    WITH CHECK OPTION: Spécifie que seul des lignes accessibles par la vue peuvent être mis à
    jour ou inserés.

    Constraint: Est le nom donné à la contrainte CHECK OPTIONS.

    WITH READ ONLY: Assure qu’aucune opération DML ne peut pas être effectuée.


    Exemple:

    SQL> CREATE OR REPLACE VIEW empvu
    2 AS
    3 SELECT empno, ename,sal
    4 FROM emp
    5 WHERE deptno=30;

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 270
    Points : 163
    Points
    163
    Par défaut
    Citation Envoyé par avogadro
    et si tu fais une view avec les 20 premieres résultats, la view est créé une seul fois, et apres tu n'a plus qu'a l'afficher, et des que tu modifies des infos sur la table auquel elle fait référence elle se met toute seul a jour (je crois)
    D'après ce que tu me dis, c'est l'idéal, vraiment génial.

    Où est-ce que je place cette requête ? lors d'une modif de la base ou juste je la crée une fois ?

  4. #4
    Membre habitué Avatar de avogadro
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 412
    Points : 188
    Points
    188
    Par défaut
    Citation Envoyé par Romalafrite
    D'après ce que tu me dis, c'est l'idéal, vraiment génial.

    Où est-ce que je place cette requête ? lors d'une modif de la base ou juste je la crée une fois ?
    normalement tu la crées une seule fois la view parce que c'est fait pour les infos souvent demandés, donc je pense que si tu fais des modifications sur la table auquelle la vue fait référence, la vue se met a jour toute seul comme les données sont liées directement a la table de référence. C'est a tester, sinon je ne vois pas trop l'intéret d'une view ^^

    Puis apres si tu utilises un site en php avec phpmyadmin tu lance ta requette pour créer la view directement dans phpmyadmin et sur le site tu fais les requettes pour afficher la vue !

    C'est un début d'idée, a approfondir...

  5. #5
    Membre expérimenté

    Profil pro
    Inscrit en
    Août 2002
    Messages
    1 060
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 1 060
    Points : 1 357
    Points
    1 357
    Par défaut
    Bonjour,

    Extrait du manuel de référence mysql :
    Si vous utilisez LIMIT # avec la clause ORDER BY, MySQL va arrêter de trier dès qu'il a trouvé la première # au lieu de trier toute la table.
    http://dev.mysql.com/doc/refman/5.0/...imization.html

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 270
    Points : 163
    Points
    163
    Par défaut
    Citation Envoyé par jeca
    Bonjour,

    Extrait du manuel de référence mysql :


    http://dev.mysql.com/doc/refman/5.0/...imization.html

    Rien compris, en fait, j'ai trouvé une solution convenable en limitant la recherche aux X dernières commandes (WHERE id_commande > (max_id_commande - X))

  7. #7
    Membre éclairé Avatar de cadoudal56
    Profil pro
    Inscrit en
    Février 2005
    Messages
    694
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2005
    Messages : 694
    Points : 779
    Points
    779
    Par défaut
    Oui ou alors il existe une autre possibilité....
    Si tu connais ta fréquence de commande (genre x commande tous les jours ou tous les mois, tu utilise un BETWEEN
    WHERE date BETWEEN xxx TO xxx

    Et tu limites toujours sur les 20 premiers...

    @+
    cadou

  8. #8
    Membre éprouvé
    Avatar de Sivrît
    Profil pro
    Inscrit en
    Février 2006
    Messages
    953
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 953
    Points : 1 249
    Points
    1 249
    Par défaut
    Pour l'utilisation d'une vue j'ai peur que lorsqu'on l'appelle la requête qui la définie soit exécutée, ce qui nous ramènerait au point de départ... cela dit je connais mal le fonctionnement des vues.


    Je pense qu'un indexe sur le champ 'date' devrait régler l'affaire. Comme ça le tri est déjà fait et le limit devient trivial. Un truc comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE INDEX MonIndexSurLesDates ON MaTable(date);

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 270
    Points : 163
    Points
    163
    Par défaut
    Citation Envoyé par Sivrît
    Pour l'utilisation d'une vue j'ai peur que lorsqu'on l'appelle la requête qui la définie soit exécutée, ce qui nous ramènerait au point de départ... cela dit je connais mal le fonctionnement des vues.


    Je pense qu'un indexe sur le champ 'date' devrait régler l'affaire. Comme ça le tri est déjà fait et le limit devient trivial. Un truc comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE INDEX MonIndexSurLesDates ON MaTable(date);
    je l'ai déjà ça mais ça n'a pas fait grand chose malheureusement..

  10. #10
    Membre éprouvé
    Avatar de Sivrît
    Profil pro
    Inscrit en
    Février 2006
    Messages
    953
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 953
    Points : 1 249
    Points
    1 249
    Par défaut
    Il aurait peut-être mieux vallu copier la requête de l'autre forum, parce que tel que c'est dit dans le message initial ça semble assez trivial.

    J'ai peur que le 'etat<>-1' ne pose problème. Le mieux serait de commencer avec une requête qui ne contient que la première table et de jouer avec 'EXPLAIN' pour s'assurer que l'on utilise bien un index, quitte à indexer (etat, date) et (date, etat) (le deuxième me semble plus susceptible de fonctionner). Il y a dans la doc de mysql un mot clef pour forcer l'utilisation d'un index; ce serait peut-être à tester en désepoir de cause. Il est possible que la version de MysqL influence l'optimisation des LIMIT/ORDER BY.

    Si ça passe il sera temps de rajouter les jointures une par une en veillant à ce que chaque étape lie bien via un indexe (ce devrait être assez facile car les liaisons sont simples). Si possible les 'LEFT JOIN' seraient à éviter car bien plus lents que de simples 'JOIN'.


    Le lien pour les vues devait être pour moi Mais tel que je vois leur fonctionnement elles ne vont pas résoudre le problème de vitesse, à moins peut être que les tables concernées ne soient que rarement mises à jour.

  11. #11
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 270
    Points : 163
    Points
    163
    Par défaut
    Citation Envoyé par Sivrît
    Il aurait peut-être mieux vallu copier la requête de l'autre forum, parce que tel que c'est dit dans le message initial ça semble assez trivial.

    J'ai peur que le 'etat<>-1' ne pose problème. Le mieux serait de commencer avec une requête qui ne contient que la première table et de jouer avec 'EXPLAIN' pour s'assurer que l'on utilise bien un index, quitte à indexer (etat, date) et (date, etat) (le deuxième me semble plus susceptible de fonctionner). Il y a dans la doc de mysql un mot clef pour forcer l'utilisation d'un index; ce serait peut-être à tester en désepoir de cause. Il est possible que la version de MysqL influence l'optimisation des LIMIT/ORDER BY.

    Si ça passe il sera temps de rajouter les jointures une par une en veillant à ce que chaque étape lie bien via un indexe (ce devrait être assez facile car les liaisons sont simples). Si possible les 'LEFT JOIN' seraient à éviter car bien plus lents que de simples 'JOIN'.


    Le lien pour les vues devait être pour moi Mais tel que je vois leur fonctionnement elles ne vont pas résoudre le problème de vitesse, à moins peut être que les tables concernées ne soient que rarement mises à jour.
    Merci.

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

Discussions similaires

  1. [OpenOffice][Tableur] Comment réaliser une liste déroulante avec des images
    Par flexi2202 dans le forum OpenOffice & LibreOffice
    Réponses: 0
    Dernier message: 30/04/2015, 10h34
  2. Réponses: 5
    Dernier message: 02/07/2012, 09h12
  3. Comment appeler une page PHP avec des paramètres ?
    Par petitclem dans le forum Débuter
    Réponses: 9
    Dernier message: 07/03/2012, 19h45
  4. [MySQL] Optimiser une requête avec des tableaux PHP ?
    Par Khleo dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 14/11/2011, 15h49
  5. Réponses: 4
    Dernier message: 24/05/2010, 13h15

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