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

PHP & Base de données Discussion :

Solution à une jointure qui consomme du temps et de la mémoire


Sujet :

PHP & Base de données

  1. #1
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 220
    Par défaut Solution à une jointure qui consomme du temps et de la mémoire
    Bonjour,

    Voici le code:
    Code php : 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
    // Execute our SQL statement and return the result
    $sql = "
        SELECT entreprises.id, entreprises.Nom, DateDebutActivites, SIRET
        FROM entreprises
        LEFT JOIN dirigeants
        ON (entreprises.id = dirigeants.IdEntreprise)
        WHERE 0=0
            AND (
                (entreprises.Nom LIKE '%" . $terms . "%')
                OR (DenominationSociale LIKE '%" . $terms . "%')
                OR (NomCommercial LIKE '%" . $terms . "%')
                OR (Enseigne LIKE '%" . $terms . "%')
                OR (Sigle LIKE '%" . $terms . "%')
                OR (SIRET LIKE '%" . $terms . "%')
                OR (dirigeants.Nom LIKE '%" . $terms . "%')
            ) 
        GROUP BY entreprises.id
        $limitClause";
    $query = $this->db->query($sql);
    Avec les 2 tables de 1000 lignes au total, ça marche mais avec la base de données complète (les 2 tables à 70000 lignes), le script ne se finit pas même au bout de 3 mn et fait planter la machine.
    En fait c'est la dernière condition OR (dirigeants.Nom LIKE LIKE '%" . $terms . "%') qui est problématique.
    Comme vous pouvez le voir, ce bout de code est utilisé pour une recherche donc une recherche qui ne donne pas de résultat au bout de 15 secondes maximum n'est pas intéressant.

    Je me demande si un SELECT UNION pourrait bien être la solution.
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  2. #2
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    quel est le type de table utilisé pour le stockage ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    OR (dirigeants.Nom LIKE LIKE '%" . $terms . "%')
    Y a un LIKE en trop.

  3. #3
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 220
    Par défaut
    Ne tenez pas compte du LIKE en trop, erreur de saisie!

    Les tables sont en InnoDB!
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  4. #4
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    il n'y a pas 36 moyens d'optimiser des LIKE '%..%' avec des méta-carctères en début et fin. Dans ce cas de figure, indexer ne sert à rien à l'inverse d'un LIKE '..%' par exemple.

    Après l'index optimisé pour ce genre de traitement : le FTS (full text search) n'est présent pour InnoDB qu'à partir de MySQL 5.6.4
    Donc tu sembles coincé.

    Si c'est vraiment central, il faudrait envisager la sous-traitance de ces requêtes en les passant à des moteurs du genre Lucene ou Sphinx.

    En tout cas, le problème en l'état n'a pas de solution simple.

  5. #5
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Pour la recherche full text en innodb on peut contourner le problème quand on à pas une version de mysql toute récente :

    http://blog.oroger.fr/2009/11/03/mys...-table-innodb/
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 220
    Par défaut
    De plus, rares sont ceux qui utilisent déjà MySql 5.6.

    J'ai transformé pour le test mes tables en MyIsam et j'utilise maintenant des index Fulltext!
    Mais ça rame encore comme avec '%...%' pour fulltext. Voici ma requête:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT 
      entreprises.Nom,
      dirigeants.Nom,
      MATCH(entreprises.Nom, dirigeants.Nom) AGAINST ('THU THON' IN BOOLEAN MODE) AS cpt 
    FROM
      entreprises 
      LEFT JOIN
      dirigeants 
    ON entreprises.id = dirigeants.IdEntreprise
    WHERE MATCH(entreprises.Nom, dirigeants.Nom)
    ORDER BY cpt

    Rem: le contenu du WHERE est le même que le MATCH d'en haut mais le post ne marche pas quand je mets tout (bug de developpez.net)

    Mon souci avec MyIsam c'est que c'est trop réputé comme moins performant qu'InnoDB, surtout pour une large base de données comme l'on utilise. C'est vrai on n'a pas besoin d'utiliser des clés étrangères réelles mais MyIsam est toujours lent par rapport à InnoDB non?

    Voici un lien qui me fait hésiter: ici car selon ce lien si l'on ne veut donc pas utiliser des clés étrangères avec les intégrités référentielles, le seul avantage d'InnoDB c'est le système de récupération automatique en cas de crash puisqu'il est plus lent que d'autres et gourmand en ressources mémoires et en espace disque.

    Mais bon le système ACID supporté par InnoDB est trop rassurant!
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  7. #7
    Membre éprouvé Avatar de redoran
    Homme Profil pro
    Développeur-Amateur
    Inscrit en
    Juin 2010
    Messages
    1 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur-Amateur
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 346
    Par défaut
    salut ; et si tu passe par une table temporaire ensuite tu déclenche ta requête de recherche sur la table memory , sûr tu passe de 3 mn a 0.03 secondes

  8. #8
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    Je te l'ai dit optimiser des LIKE '%...%' sur MySQL relève d'une gegeure. Ce SGBD n'a rien d'exceptionnel et dès que tu montes un peu dans les tours, tu en touches très vite les limites. La preuve : une simple recherche texte suffit à le mettre sur les rotules.
    Bref, pas de soluce miracle. Sans tomber dans des rustines bien crades, je pense que tu essaies de percer un trou avec une petite cuillère. A force tu devrais y arriver mais à quel prix...

  9. #9
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 220
    Par défaut
    Citation Envoyé par redoran Voir le message
    salut ; et si tu passe par une table temporaire ensuite tu déclenche ta requête de recherche sur la table memory , sûr tu passe de 3 mn a 0.03 secondes
    Je ne comprends pas le principe? Que mettre dans la table temporaire, comment penses-tu envoyer les données vers cette table, par trigger?

    rawsrc > Oui j'ai retenu que l'optimisation d'un "LIKE '%...%'" n'est presque pas possible. Mais l'utilisation de FTS (Full Text Search) n'est pas à priori bénéfique non plus selon le test que j'ai fait. Je suis confus également sur le choix d'utiliser soit InnoBD plus sécurisé à défaut d'avoir l'indexation FullText, soit MyIsam plus rapide mais avec risque!*

    Question: est-ce que le FULLTEXT peut s'utiliser sur des champs de type INT, FLOAT ou DATE?
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  10. #10
    Membre éprouvé Avatar de redoran
    Homme Profil pro
    Développeur-Amateur
    Inscrit en
    Juin 2010
    Messages
    1 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur-Amateur
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 346
    Par défaut
    En fait c'est la dernière condition OR (dirigeants.Nom LIKE '%" . $terms . "%') qui est problématique.
    si tu supprime cette condition , qu'elle est le temps de réponse?

    Je ne comprends pas le principe? Que mettre dans la table temporaire, comment penses-tu envoyer les données vers cette table, par trigger?
    réponse:
    La table temporaire est une construction volatile, stockée dans la mémoire du serveur Mysql, on utilisent ce type de création lors de requêtes complexes ( union, jointure........) qui sera automatiquement détruite à la fin de l’exécution du script
    http://dev.mysql.com/doc/refman/5.0/...tml?ff=nopfpls
    sinon vous pouvez rester sur innodb et enregistré sous une table MYISAM le résultat de la requête concernée par la recherche, cette dernière sera mise a jourr avec les triggers.
    voila voilou ( c'est juste une proposition)

    un lien intéressanthttp://dev.mysql.com/doc/refman/5.0/...xt-search.html

  11. #11
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 220
    Par défaut
    Citation Envoyé par redoran Voir le message
    si tu supprime cette condition , qu'elle est le temps de réponse?
    Ben le temps de réponse devient 2 secondes max mais là il n'y a plus de jointure si on l'enlève!

    Citation Envoyé par redoran
    sinon vous pouvez rester sur innodb et enregistré sous une table MYISAM le résultat de la requête concernée par la recherche, cette dernière sera mise a jourr avec les triggers
    En fait, si je veux utiliser fulltext, ne dois-je pas mettre les tables où effectuer les recherches en MyIsam mais pas seulement les résultats de la requête? Ou est-ce qu'une table temporaire supporte fulltext?
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  12. #12
    Membre éprouvé Avatar de redoran
    Homme Profil pro
    Développeur-Amateur
    Inscrit en
    Juin 2010
    Messages
    1 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur-Amateur
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 346
    Par défaut
    salut ; sans façon essaye une relecture de ce tuto http://sqlpro.developpez.com/cours/sqlaz/jointures/
    essaye d'utilisé des alias pour les noms de table.
    et cette condition sert a quoi ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ......WHERE 0=0....AND... (...OR...).
    on a ici une logique booléenne...
    http://python.developpez.com/cours/D...ion/and_or.php
    je crois qu'il faut écrire la condition de la requête autrement ( par exemple utilisation de case...) .

  13. #13
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 814
    Billets dans le blog
    14
    Par défaut
    On peut avoir la description complète des deux tables ?
    Poste ici le résultat complet de SHOW CREATE TABLE nom_de_la_table
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  14. #14
    Membre Expert
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Par défaut
    je crois qu'il faut faire autrement. par exemple si tu fais une table "de hachage" avec tous les tripplets de ta colonne. genre une vue matérialisée.. Ensuite tu cherches dans cette base tous les tripplets tappés par ton user (avec les index, ça va vite) et tu retournes l'intersections/l'union de tous les résultats qui retourne un nombre de réponses interessant (via du script).

Discussions similaires

  1. Créer une Gadget qui consomme un web service
    Par azstar dans le forum C#
    Réponses: 3
    Dernier message: 05/09/2012, 14h10
  2. temps qui croit beacoup a cause d'une jointure
    Par skouza dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 13/07/2011, 17h40
  3. [AJAX] Une ligne qui plante de temps en temps
    Par Lilouse dans le forum AJAX
    Réponses: 3
    Dernier message: 21/04/2010, 11h13
  4. Réponses: 2
    Dernier message: 05/05/2009, 10h39
  5. une instruction qui prendra un temps remarquable.
    Par tsdia2 dans le forum Windows Forms
    Réponses: 4
    Dernier message: 08/05/2008, 11h58

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