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 :

requete avec un "WHERE .. . IN" trop lourd


Sujet :

Requêtes MySQL

  1. #1
    Membre confirmé Avatar de Phiss
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2005
    Messages
    676
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 676
    Points : 616
    Points
    616
    Par défaut requete avec un "WHERE .. . IN" trop lourd
    Bonjour à tout le monde.

    Je me permets de lancer ce sujet sur mon problème.

    J'ai une requète qui est de la forme suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT mes_champs FROM ma_table WHERE mon_champ IN (val1, val2, etc.)
    Le problème que je rencontre vient du nombre de valeurs contenues dans le IN.
    Je tourne des fois à plus de 100 000 valeurs qui font planté ma requête faute de mémoire.

    D'où ma question :
    A-t-on le moyen de passer par une autre requête que le IN afin d'avoir le même résultat?

    Merci d'avance.
    " L'absence diminue les médiocres passions et augmente les grandes, comme le vent éteint les bougies et allume le feu. "
    La Rochefoucauld

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 127
    Points : 208
    Points
    208
    Par défaut
    Bonjour,

    Ce qu'il faudrait savoir, c'est comment sont choisies les valeurs que tu mets dans le IN.

    Ou bien ce sont des valeurs totalement arbitraires, et dans ce cas je ne vois que 2 solutions :
    ou tu découpe le IN en morceaux, genre paquets de 1000 (voir limites bdd) et tu fait un UNION
    ou tu insère les valeurs concernées (et/ou la primary key) dans une table temporaire et tu fais une jointure avec ta table.

    Par contre, si tu as des critères du genre mon_champ LIKE '%celuila%' ou un lien possible avec d'autres tables, ou une date de sélection, n'utilise pas le IN bien sûr.

    C'est tout ce que je peux te proposer, sans en savoir plus en tout cas

    Cordialement

  3. #3
    Membre confirmé Avatar de Phiss
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2005
    Messages
    676
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 676
    Points : 616
    Points
    616
    Par défaut
    Alors dans mon IN il y a des valeurs arbitraires.
    Ce sont des identifiants récupérés par une fonctions php.

    Du coup si je découpe par paquet de 1000, cela veut dire faire X requête ou n'en laisser qu'une mais faire ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Where nom_champ IN (val1, val2, val3) OR nom_champ IN (val4, val5, val6) etc.
    .

    Pour ce qui est de la table temporaire, je vais voir ce qui est possible.
    " L'absence diminue les médiocres passions et augmente les grandes, comme le vent éteint les bougies et allume le feu. "
    La Rochefoucauld

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 127
    Points : 208
    Points
    208
    Par défaut
    Re-bonjour Phiss,

    Tu peux effectivement faire comme tu dis, c'est peut-être plus performant, à tester, par contre, si tu veux que ta requête ne rame pas trop, tu as intérêt à te pencher sur les index.

    J'aurais tendance à penser que si la requête doit faire un scan complet, ta méthode serait plus efficace alors qu'avec un index et un groupement des sélect par ordre alphabétique, le multiple SELECT serait peut-être plus rapide, mais c'est purement intuitif.

    Aspect technique mis à part, je serais curieux de savoir ce qui t'amène à faire une recherche avec des critères aussi larges, peut_être une recherche de mots clés dans un document ? Bon ça ne me regarde peut-être pas, c'est juste par curiosité !
    Cordialement

  5. #5
    Membre confirmé Avatar de Phiss
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2005
    Messages
    676
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 676
    Points : 616
    Points
    616
    Par défaut
    Bonjour semaphore1984,

    J'ai testé avec la table temporaire et à priori c'est pas mieux. :-(
    Je vais faire le test comme je disais mais sans être trop convaincu quand même.

    Pour le besoin, c'est une recherche dans une table conséquente (plus de 200 000 enregistrements) en passant par les identifiants qui sont clés primaire.
    " L'absence diminue les médiocres passions et augmente les grandes, comme le vent éteint les bougies et allume le feu. "
    La Rochefoucauld

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Comment sont déterminés les identifiants qui se retrouvent dans le IN ?

    La détermination de ces identifiants par PHP ne peut-elle être faite en SQL ?

    Bref, décris plus en détail ton processus qui amène à la construction de la requête.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  7. #7
    Membre confirmé Avatar de Phiss
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2005
    Messages
    676
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 676
    Points : 616
    Points
    616
    Par défaut
    Bonjour CinePhil,

    Alors je vais essayer d'éclaircir tout ça.

    Cette requête est situé dans une fonction appelée en plusieurs endroits.
    Selon la provenance de l'appel, la liste des identifiants est renseignée de différentes manières. Cette liste est donc passée en paramètre de la fonction dans un tableau.

    On ne peut donc pas savoir lors de l’exécution de la requête quels sont les identifiants se trouvant dedans.

    La requête me permet de récupérer les infos sur d'autres champs de la table afin de les afficher. La liste des champs est elle même évolutive dans la fonction.

    En gros, actuellement j'ai une requête ressemblant à cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "SELECT " . $liste_champ . " FROM " . $ma_table . " WHERE " . $mon_champ . " IN (" . implode(", ", $tableau_id) . ")"
    Est ce que cela est plus clair?
    " L'absence diminue les médiocres passions et augmente les grandes, comme le vent éteint les bougies et allume le feu. "
    La Rochefoucauld

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 127
    Points : 208
    Points
    208
    Par défaut
    Bonjour Phiss,

    C'est toujours difficile de proposer rapidement une solution quand on a pas toutes les données du problème, mais ce qui m'étonne, c'est que pour un affichage, tu ais besoin de récupérer tant de données à la fois.

    Je m'explique :
    Si ce sont des id qui existent, ça veut dire que si tu as 20000 id dans ton tableau, tu va afficher 20 000 lignes dans un seul écran ? comment une personne, même si c'est paginé, va trouver l'information qu'elle cherche avec une telle quantité de lignes dans le résultat ?

    Je te l'accorde, je fais des suppositions qui ne sont peut être pas vraies, mais es tu bien sûr de ne pas pouvoir restreindre la fourchette d'id de recherche, et par conséquent le résultat obtenu ?

    Ce n'est pas un jugement de valeur, c'est seulement des réflexions qui me viennent à l'esprit, ok ?

    Cordialement

  9. #9
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Que fait cette mystérieuse fonction ?

    À lire la requête, on a l'impression que c'est une fonction fourre tout juste destinée à construire une requête sur n'importe quelle table, ce qui est pour le moins étrange !

    Quand je demandais de décrire le processus, je voulais dire : depuis la sélection des id qui alimente actuellement le IN.
    Que fait l'utilisateur pour que le programme génère une liste aussi longue d'id à sélectionner ?

    L'action de l'utilisateur a, en principe, une sémantique, telle que "Je veux sélectionner tous les clients de Toulouse". On satisfait ce genre de besoin en faisant une certaine requête qui sera différente de celle répondant au besoin "Je veux sélectionner tous les clients qui ont des factures en retard de paiement".

    C'est cette logique de l'application que j'aimerais comprendre pour donner une réponse appropriée. En attendant, tout ce que je peux dire, c'est que mettre des milliers d'identifiants dans un IN d'une requête construite de la sorte, c'est sûrement ce qu'il ne faut pas faire ! Tu en subis d'ailleurs les conséquences en terme de mauvaises performances de ton appli.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  10. #10
    Membre confirmé Avatar de Phiss
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2005
    Messages
    676
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 676
    Points : 616
    Points
    616
    Par défaut
    Excusez moi de ne pas être revenu plus tôt.

    Tout commence avec des objets qui sont remplis par des données de plusieurs tables.
    Ces tables peuvent être sur des bases différentes. (une table principale qui a des liens vers des tables externes)

    Quand je fais une recherche je dois donc aller chercher tous les identifiants de la table principale afin justement de récupérer ces identifiants externes.

    Pour que vous voyez bien la chose.
    J'effectue une recherche d'un mot sur la base de mes objets.
    Le mot rechercher doit être recherché sur tous les champs de l'objet.
    Donc cela inclut les champs des tables externes.
    Je veux donc créer soit un tableau d'objets soit une table temporaire contenant tous les champs de tous les objets.

    Et lorsque je remplis mon tableau, je ne vois pas d'autre solution que le IN.

    Est ce que cela est plus clair?

    PS : cela veut dire que j'ai des requêtes sur plusieurs tables avec de gros IN.
    " L'absence diminue les médiocres passions et augmente les grandes, comme le vent éteint les bougies et allume le feu. "
    La Rochefoucauld

  11. #11
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Non, c'est trop vague !

    Citation Envoyé par Phiss
    Tout commence avec des objets qui sont remplis par des données de plusieurs tables.
    Je suppose qu'il s'agit ici d'objet au sens informatique, c'est à dire instances de classes ?
    Mais quelle sémantique se cache derrière ces mystérieux objets ?

    Dans le monde réel, un objet c'est quelque chose de solide, que je peux tenir dans la main s'il est petit (un crayon, une paire de lunettes, un smartphone...) ou pas s'il est grand (une voiture, un ordinateur, une télévision, une armoire...)

    Citation Envoyé par CinéPhil
    L'action de l'utilisateur a, en principe, une sémantique, telle que "Je veux sélectionner tous les clients de Toulouse".
    Ça, c'était concret !
    Nul doute qu'il y aura probablement une classe "client" dans le programme informatique et que son instanciation créera des objets représentant chacun un client.

    Quand je fais une recherche je dois donc aller chercher tous les identifiants de la table principale afin justement de récupérer ces identifiants externes.
    Que contient plus précisément cette table ? Des données sur des vélos ? des villes ? des personnes ? des produits ? des chiens ? des acteurs ?

    J'effectue une recherche d'un mot sur la base de mes objets.
    Dans le contexte informatique qui est celui de ce forum, cette phrase est ambigüe, donc imprécise.
    Base : S'agit-il d'une base de données relationnelle contenant des données sur des objets physiques ?
    Objet : S'agit-il de l'objet informatique dans un programme (instance de classe) ou d'objets physiques ?

    Donc cette phrase veut-elle dire ?
    - Je cherche un mot parmi les données enregistrées sur des objets physiques.
    - Je cherche un mot parmi les valeurs des propriétés des objets instanciés dans mon programme.

    Bref, je ne comprends toujours pas de quoi il s'agit.

    Tant que vous n'expliquerez pas mieux votre cas concret, je ne pourrai pas vous aider efficacement.

    Lisez la phrase en bleu de ma signature et appliquez son principe.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  12. #12
    Membre confirmé Avatar de Phiss
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2005
    Messages
    676
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 676
    Points : 616
    Points
    616
    Par défaut
    Re bonjour.

    Je vais à nouveau essayer d'être plus clair.

    J'ai plusieurs bases de données en mysql sur lesquelles j’accède grâce à PHP.
    Dans ces bases, j'en ai une principale qui me sert de base mère.
    Les autres sont des bases clientes.

    Dans ma base mère j'ai des tables contenant une partie des informations de mes objets (individus, produits, etc.). Il est possible que certaines informations de ces objets soient sur une base clientes.

    Donc lorsque je crée un objet sous php, je l'instancie pour qu'il récupère la totalité des informations le concernant sur toutes les tables (base mère et clientes). Le lien entre la base mère et les bases clientes sont des identifiants stockés sur la table de la base mère que l'on retrouve sur la table de la base cliente.
    exemple pour un produit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    table mère : produit
    produit_id, produit_nom, produit_actif, produit_base_1_id, produit_base_2_id
     
    table base 1 : produit1
    produit1_id, produit1_prix
     
    table base 2: produit2
    produit2_id, produit2_image
    J'ai implémenté un formulaire de recherche sur le site qui laisse la possibilité de mettre ce que l'on veut comme recherche. On ne se limite pas sur un champ.
    Le seul impératif c'est que le produit soit actif (produit_actif à 1).
    Donc je vais chercher tout les produit_base_1_id et produit_base_2_id dans la table mère pour les enregistrements actif.
    De la je récupère une liste d'identifiants que je passe à mes deux tables clientes.
    C'est ces deux listes que je mets dans le IN de ma requête.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT produit2_nom FROM produit2 WHERE produit2_id IN ( liste des id récupérés) AND produit2_nom LIKE "%ma_recherche%"

    Donc pour simplifier cela pourrait être du style :
    Je veux récupérer tous les produits qui contiennent "toto".

    Où pour vous citer
    - Je cherche un mot parmi les valeurs des propriétés des objets instanciés dans mon programme.
    Merci en tout cas de m'aider. Même si je ne suis pas très clair dans mes propos.
    " L'absence diminue les médiocres passions et augmente les grandes, comme le vent éteint les bougies et allume le feu. "
    La Rochefoucauld

  13. #13
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    J'ose espérer que ce qui justifie l'existence de 3 BDD ainsi conçues est qu'elles figurent sur des serveurs différents ?

    Il existe cependant des outils de réplication qui permettent de rapatrier dans une BDD mère des données éparpillées dans des BDD filles.

    Si les trois BDD sont sur le même serveur, on peut faire des requêtes interrogeant des tables provenant de plusieurs BDD. Il est ainsi possible de faire cette requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT p.produit_id, p.produit_nom,
    	p1.produit1_prix,
    	p2.produit2_image
    FROM base_mere.produit p
    LEFT OUTER JOIN base_1.produit1 p1 ON p1.produit1_id = p.produit_base_1_id
    LEFT OUTER JOIN base_2.produit2 p2 ON p2.produit2_id = p.produit_base_2_id
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 confirmé Avatar de Phiss
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2005
    Messages
    676
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 676
    Points : 616
    Points
    616
    Par défaut
    En effet les bases sont sur des serveurs différents.

    Je vais essayer de voir du coté de la réplication si ce n'est pas trop lourd à mettre en place et surtout possible sur nos serveurs.

    Encore merci.
    " L'absence diminue les médiocres passions et augmente les grandes, comme le vent éteint les bougies et allume le feu. "
    La Rochefoucauld

  15. #15
    Membre confirmé
    Avatar de tse_jc
    Homme Profil pro
    Data Solutions
    Inscrit en
    Août 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Data Solutions
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2010
    Messages : 287
    Points : 597
    Points
    597
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    Désolé d'être aussi critique, mais ce cas de figure illustre bien le fait que les CMS et l'utilisation abusive des bases de données comme simple lieu de stockage pour persister des classes objets, font plus de dégâts que de bien. La modélisation de vos bases de données est aussi catastrophique que la modélisation conceptuelle de votre application. C'est du gros n'importe quoi. Quand votre site/application va atteindre ses limites au niveau de sa capacité à gérer la charge (si vous n'y êtes pas déjà), vous serez bon pour tout redévelopper à zéro pour être en mesure de résoudre vos problèmes, et si vous serez en mesure de pouvoir migrer vos données vers un modèle de données normalisé au sens de l'algèbre relationnelle, vous pourrez considérer que vous aurez une chance incroyable.

    La prochaine fois, j'espère que vous penserez à calculer ce que peut vous coûter un investissement low cost avec un CMS, et que ce choix représente un choix pertinent et pérenne sur le long terme.

    Je vous souhaite une bonne continuation.

    Cordialement.

Discussions similaires

  1. [MySQL] requete avec 4 clause where
    Par monlou dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 01/10/2014, 20h20
  2. [HQL] aide requete avec from T where t.a in ?
    Par Sniper37 dans le forum Hibernate
    Réponses: 2
    Dernier message: 12/02/2008, 14h08
  3. Réponses: 4
    Dernier message: 15/05/2007, 10h10

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