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 :

Optimisation SQL, plusieurs WHERE, ordre de tri


Sujet :

Requêtes MySQL

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut Optimisation SQL, plusieurs WHERE, ordre de tri
    Bonjour,
    j'ai un site avec une table qui compte 200 000 entrées, j'utilise un cron job, qui, toutes les 5 minutes, controlent ces entrées, j'aimerai savoir comment les requetes SQL procedent quand il y a plusieurs WHERE pour pouvoir optimiser mes requetes.

    Je recupère des infos depuis plusieurs centaines de flux RSS, je recupère les infos de ces news, si elles sont déjà présentes dans ma base de donnée, je ne les recupere pas, et je stocke les news pas présentes dans ma base..

    Pour chaque news de chaque flux rss je la compare donc pour voir si elle est présente dans ma base, un gros travail vu qu'il y a plus de 200 000 entrées.

    J'utilise l'adresse url du lien vers la news ou la date pour comparer et vérifier l'existence d'une news, j'execute donc une requete pour chaque news de chaque flux, c'est cette requete que je souhaite optimiser...

    id_feed correspond à l'id unique d'un flux rss, comme ça la requete ne chercherait l'url du lien parmi uniquement les news ayant le bon id de flux..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Si je met dans ma requête SELECT * WHERE url_news="le_lien_vers_lanews.php" AND id_feed=5"
    Est ce que MySQL va filtrer les champs qui ont id_feed=5 et chercher uniquement parmi eux si url_news est bien égal à "le_lien_vers_lanews.php", ou alors est ce qu'il va chercher parmi les 200 000 champs la valeur texte de url_news PUIS l'id_feed ???

    J'aimerai bien comprendre comment dire dans une requete de trier d'abord avec id_feed et ensuite verifier l'url_news et pas l'inverse

    Merci beaucoup

  2. #2
    Invité
    Invité(e)
    Par défaut
    l'ordre des critères dans la clause where est important


    présentement l'engin fera un scan pour 'le_lien....' et ensuite utiliser ton indexes pour le id_feed=5 (si tu as un indexes)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * WHERE url_news="le_lien_vers_lanews.php" AND id_feed=5"

    tu dois les inverser

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * WHERE id_feed=5 and url_news="le_lien_vers_lanews.php"

    si tu as MYSQL5 tu peux aussi partionner une table.

    En gros cela te permet de faire une grosse table virtuelle mais en dessous c'est plusieurs tables plus petites qui sont créés

    http://dev.mysql.com/doc/refman/5.1/...ing-range.html

    tu peux peux regrouper les feeds les plus gros dans des partitions isolées. À part la définition de la table, le 'partitionning' ne change en rien la manière que tu te sers pour accéder les données.

    Un bonne préparation améliorera les performances.

    Si tu veux que cela soit plus rapide, tu pourrais insérer une colonne HASH dans ta table de feed qui correspond au CRC32 ou SHA5 de l'url. Tu mets l'indexe sur cette colonne au lieu d'indexer l'url (qui peut contenir plus de 200 caractères).


    De cette facon, quand tu lis un feed, tu calcules la valeur du hash dans php, ensuite tu demandes a mysql si tu as deja une news avec le meme hash. Le hash ayant un maximum d'environ 40 caracteres, sera surement plus rapide que de rechercher un URL.

    Tu ne déclares pas le hash comme un varchar mais plutot un CHAR32 ou char40..

    c'est possible d'optimiser plus encore, je te laisse réfléchir sur ce que tu veux ou a besoin d'abord.
    Dernière modification par Alain Defrance ; 16/09/2008 à 16h07. Motif: ajout de balise code

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut
    Citation Envoyé par Luc Raymond Voir le message
    l'ordre des critères dans la clause where est important
    Merci pour l'info
    Très important, j'avais encore lu ça nul part sur le net ^^ Ca m'avance déjà pas mal

    La partition de table ca m'a l'air interessant pour la suite Une partition par langue par exemple histoire d'optimiser

    tu me conseilles crc32 ou sha pour encrypter les url ??

    En fait je vais utiliser plusieurs techniques pour identifier les flux, soit l'url, soit la date, soit un id récupéré dans l'url..

    "Indexes" c'est l'option Index pour les champs dans phpMyAdmin ? c'est grave si quasi tous mes champs dans ma table news sont des index ? ( des id vers d'autres tables ) , la date et le lien_url(ou plutot le hash) je dois les mettre en index aussi ?

    Et encore merci pour ta réponse

  4. #4
    Invité
    Invité(e)
    Par défaut
    La partition de table ca m'a l'air interessant pour la suite Une partition par langue par exemple histoire d'optimiser
    Effectivement, si tu sa genre 2 langues, ca t'assures de démêler physiquement tes news. C'est effectivement inutile de chercher une news francaise dans une liste de news anglaise. La beauté du partitionning c'est que les requêtes ne changent pas. Seulement la définition initiale de la table.

    On appelle ça une repartition verticale de tes données, pour améliorer d'avantages, tu peux faire une partition horizontale de tes données. Puis-je breveter le terme partition diagonale?


    tu me conseilles crc32 ou sha pour encrypter les url ??
    md5=32bits, sha1=40bits, j'irais donc avec sha1 pour minimiser le nombre de collisions possibles (2 chaines avec une valeur de HASHing identique)


    En fait je vais utiliser plusieurs techniques pour identifier les flux, soit l'url, soit la date, soit un id récupéré dans l'url..
    bien tu peux utiliser le nombre de critère que tu le désires, tu exécutes ensuite la fonction de hashing sur l'ensemble de ces données..

    donc cela ne te fait qu'un seul champ à chercher! :-)

    petite suggestion
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
     //je lis mes feeds ici
     
     //ici on met une boucle pour traiter chaque flux
     $info=array();
     $info['id_feed']=5;
     $info['url']='http://www.lucraymond.net';
     $info['langue']='fr'
     $hash= sha1(serialize($info));
     
     //ici on valide si hash existe dans la BD
     //ici on insère si hash existe pas
    Citation Envoyé par dynexd Voir le message
    "Indexes" c'est l'option Index pour les champs dans phpMyAdmin ? c'est grave si quasi tous mes champs dans ma table news sont des index ? ( des id vers d'autres tables ) , la date et le lien_url(ou plutot le hash) je dois les mettre en index aussi ?
    Et encore merci pour ta réponse
    tu dois mettre un index sur seulement les champs dont tu désires faires des recherches. Si tu ne recherche jamais par date, tu n'en met pas.

    n'oublie pas que lorsque tu insere des nouvelles données dans la table, il y a une étape d'insertion des données et ensuite c'est la mise à jour des indexes. Donc si tu as 10 indexes, en insérant un nouvel enregistrement tu te retrouves à provoquer 11 actions à ton engin de base de données.

    Sans compter l'espace disque perdu pour maintenir les indexes.

    meme si tu as des indexes, cela ne veut pas dire que mysql les utilisent

    si tu met un indexe sur la colonne URL et que tu cherches:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ... where URL like '%luc%';   // n'utilisera pas l'index
    ... where URL like '%luc';   // n'utilisera pas l'index, mais une solution existe
    ... where URL like 'luc%';   // utilisera l'index

  5. #5
    Invité
    Invité(e)
    Par défaut
    si tu veux améliorer genre (100x et +) ton processus, je te conseille d'améliorer ta technique! :-)

    quand tu lis tes feeds, tu vas calculer tes hash pour ensuite voir un par un si ils existent dejà dans ta base de données?

    ce que tu peux faire (tout dépendant de ton volume de données) c'est de mettre en mémoire tes dernières nouvelles que tu as ajoutées dans ta table

    pseudocode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
     
      $feeds=AllonsChercherlesNewsSurLeWeb(...);  //retourne un tableau de FEEDS
     
      $hashes=CalculeHash($feeds); retourne un tableau de hash correspondant a nos nouvelles
     
      $dernierhashes= Mysql_query('select hash from mes_news order by DATEdeLaNews desc limit 0,1000');
     
     // valide si chaque les HASH dans HASHES 
     // si oui, on ajoute pas...
     // si non, tu peux valider dans la base de donner avec un SELECT pour etre sur qu'il nest pas présent, ensuite tu ajoutes..
    tu peux changer 1000 pour 10000..

    si tu indexes les news assez régulièrement (genre 30 minutes), en le mettant a 5000, si tu lis 3000 news par 30 minutes, tu te retrouveras a faire une requete de base + 1 pour chaque nouvelle news au lieu de faire 2 requêtes pour chaques news que tu lis.


    si tu lit aux 30 minutes : 100 feeds avec 2000 news news et que seulement 40 sont nouvelles. Tu fais 2000 requetes de validation d'existences et 40 insertions..

    avec ma technique:
    41 requetes de validation (1+40) d'existences + 40 insertions.

    tu m'en reparleras! j'ai utilisé plusieurs fois.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut
    n'oublie pas que lorsque tu insere des nouvelles données dans la table, il y a une étape d'insertion des données et ensuite c'est la mise à jour des indexes. Donc si tu as 10 indexes, en insérant un nouvel enregistrement tu te retrouves à provoquer 11 actions à ton engin de base de données.
    Oui donc je dois mettre mon champs HASH en index alors !

    Mais est ce que je dois mettre en index les champs ? ( j'en ai 4 ou 5 ) correspond à des id pointant vers d'autres tables ( qui correspondent à des categories, chaque flux est associé à 4 ou 5 tables de categories ) qui me permettent d'organiser ces news.. je ne comprends pas comment je peux vérifier l'existence de 1000 news avec seulement 40 requete d'existence

    Sinon concernant ton deuxième post je suis un peu dans le flou Pour info je lance un cronjob qui index toutes les 5 minutes..

    De plus le LIMIT 1000 ou 10 000, je ne suis pas sur que ce soit adapté, parmi les flux que j'index certains sont beaucoup moins à jours que d'autres, et peuvent avoir des news qui ont plusieurs mois, je peux avoir indexé bien plus de 10 000 news plus récentes, et ce flux avoir toujours un vielle news de stockée.....

    Merci encore pour tes précisions qui me sont très utiles !!


    Une question que je me pose aussi (j'avoue profiter de tes connaissances très poussées j'en profite tant que je peux ) : j'aimerai créer des laisons supplémentaires entre les news et catégories présentes sur le site, par exemple le feed "Travauxfacile.com" est rangé dans la categorie "Travaux" donc les news prises sur ce feed seront dans la categorie Travaux

    1. Concernant ma table News qui stocke toutes les news, est ce qu'il vaut mieux créer un champs Categorie avec l'id vers la table Catégories ou est ce que le simple champs id_feed correspond à la table Feeds suffit, ou je ferait alors un JOIN feeds ( categorie ) ON feeds.id = news.id_feed ???

    2. Si je souhaite créer des liaisons supplémentaires, par exemple associer des mots à des categories que je définirai dans ma base, de manière a ce que si une news paru sur travauxfacile.com comprends le mot "Sarkozy" si ce mot est stocké dans ma base et indique que la news doit aussi apparaitre dans la categorie politique, comment puis je créer ces liaisons ? Est ce mieux de rajouter un champs 'Liaisons' dans ma table 'news' ou alors est ce que je crée carrément une table 'liaison" : id, id_categorie, id_news ?

  7. #7
    Invité
    Invité(e)
    Par défaut
    Oui donc je dois mettre mon champs HASH en index alors !
    oui..



    Mais est ce que je dois mettre en index les champs ? ( j'en ai 4 ou 5 ) correspond à des id pointant vers d'autres tables ( qui correspondent à des categories, chaque flux est associé à 4 ou 5 tables de categories ) qui me permettent d'organiser ces news..
    par contre, si tu m'indiquais ta liste de champs, il serait plus facile pour moi d'apporter mon opinion globale

    le premier raisonnement que tu dois avoir est de dire:
    ais-je besoin de ce champs pour faire une recherche?

    si tu fais une recherche genre:

    select * from mes_news where id_Category=5 and hash = 'soleil'

    il est clair que si tu n'indexes pas le champ ID_Category ou si tu n'indexes pas HASH, ta requête sera lente car il devra parcourir tous les élements.

    quelle sont les types de requêtes que tu lances pour ta table?

    supposons que tu aies 2 tables

    categories
    id_categorie (int)
    nom_categorie (varchar)

    news
    id_news
    titre_news
    hash
    id_category

    dans cet exemple , ID_NEWS et ID_CATEGORIE doivent être des clés primaires (donc elles sont considérées comme un index automatiquement)

    si tu dois faire une recherche genre
    select id_news,titre_news where hash='test' and id_category=5

    id_category devra être un index et hash devra être un index aussi.

    si tu fais une jointure entre la table news et categories, tu n'auras pas besoin d'ajouter un index car id_categorie est deja une clé primaire (autre forme d'index).

    je ne comprends pas comment je peux vérifier l'existence de 1000 news avec seulement 40 requete d'existence
    pas facile a expliquer

    disons que tu as 1000 news

    présentement tu fais
    code actuel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $news=array( ... ici tu lis tes news et tu les met dans $NEWS..)
    for ($k=0;$k<count(news);$k++)
    {
         //ici tu va présentement voir si chaque news existe manuellement
        // donc tu fais 1000 requetes d'existences (ouf c'est slow)
        $sql="select count(*) from news where hash='{$news['hash']}' ";
        $result=mysql_query($sql);
        //si le résultat est 0, tu l'insères..
    }
    code améioré
    Code : 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
    20
    21
    22
    23
    24
     
    $news=array( ... ici tu lis tes news et tu les met dans $NEWS..)
     
    //ici on fait UN SEUL query, qui nous sort les dernieres news 
    //ajoutées dans le systeme
     
    $sql="select hash from news order by news_date desc limit 0,1000 ' ";
    $hash_news=mysql_query($sql);
     
    for ($k=0;$k<count(news);$k++)
    {
       // au lieu d'aller voir dans la table si la news existe, 
     // on peut maintenant allez vérifier le tout en mémoire, sans faire
    //de requetes.
     
        if (news['hash'] existe dans $hash_news) 
             continue;
     
    //dans le cas ou le hash serait pas en mémoire, on va voir un petit
    //coup d'oeil dans la bd, comme avant.
        $sql="select count(*) from news where hash='{$news['hash']}' ";
        $result=mysql_query($sql);
        //si le résultat est 0, tu l'insères..
    }
    j'espère que c'est plus clair.



    De plus le LIMIT 1000 ou 10 000, je ne suis pas sur que ce soit adapté, parmi les flux que j'index certains sont beaucoup moins à jours que d'autres, et peuvent avoir des news qui ont plusieurs mois, je peux avoir indexé bien plus de 10 000 news plus récentes, et ce flux avoir toujours un vielle news de stockée.....
    pour avoir fait le même programme il y a 12 ans, je comprends ce que tu veux dire... mais il existe une solution facile. J'ai dit de conserver en mémoire les derniers 10000 hash de news de ton systeme. Pour éviter le problème que tu m'entionnes, tu n'as qu'a lire les 1000 derniers hashs de chaque catégories ou de chaque feed..

    je dis 1000, cela peut être 200, 100, 10.

    le but est de minimiser les requetes SQL.

    si tu indexes 200 newsfeeds rien t'empeches de faire:

    Code : 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
    20
    21
    22
    23
     
    for ($k_site=0;$k_site<200;$k_site++)
    {
     
    $sql="select hash from news where ID_SITE= $k_SITE order by news_date desc limit 0,400 ' ";
    $hash_news=mysql_query($sql);
     
    for ($k=0;$k<count(news);$k++)
    {
       // au lieu d'aller voir dans la table si la news existe, 
     // on peut maintenant allez vérifier le tout en mémoire, sans faire
    //de requetes.
     
        if (news['hash'] existe dans $hash_news) 
             continue;
     
    //dans le cas ou le hash serait pas en mémoire, on va voir un petit
    //coup d'oeil dans la bd, comme avant.
        $sql="select count(*) from news where hash='{$news['hash']}' ";
        $result=mysql_query($sql);
        //si le résultat est 0, tu l'insères..
    }
    }
    de cette facon, tu met en mémoire les derniers hash pour chacun des SITES avant de faire la validation, tu n'auras presque jamais besoin d'aller retourner faire des requetes dans la table (sauf pour les news qui n'existent pas encore dans tes tables)

    donc si tu as 200 sites, et qu'au 5 minutes tu lis 5000 news donc 1% sont nouvelles, tu auras 200 requetes (pour le caching des hash) + 50 requetes (validation d'existence du 1% de nouvelle news) + 50 requetes d'insertion de ces news..

    tu viens quand même de passer de 5000 requêtes aux 5 min, à 300 requêtes




    Une question que je me pose aussi (j'avoue profiter de tes connaissances très poussées j'en profite tant que je peux ) : j'aimerai créer des laisons supplémentaires entre les news et catégories présentes sur le site, par exemple le feed "Travauxfacile.com" est rangé dans la categorie "Travaux" donc les news prises sur ce feed seront dans la categorie Travaux

    1. Concernant ma table News qui stocke toutes les news, est ce qu'il vaut mieux créer un champs Categorie avec l'id vers la table Catégories ou est ce que le simple champs id_feed correspond à la table Feeds suffit, ou je ferait alors un JOIN feeds ( categorie ) ON feeds.id = news.id_feed ???
    la question fondamentale, penses tu que les news d'un site ne peuvent pas appartenir a plus d'une catégorie?

    si tu as un site avec des news sur PHP, ne voudrais tu pas pouvoir associer ce feed à la catégorie programmation et à p-etre éventuellement à une catégorie PHP du même coup?

    si oui,

    tu crées une table catégorie:
    id_cat (int)
    nom_categorie (varchar)
    description_categorie (text)

    ensuite une table de liaison

    liens_categories
    id_category
    id_newsfeed


    si pour continuer mon exemple tu avais les catégories suivantes:
    1: programmation
    2: php


    si tu indexes un site comme DEVELOPPEZ.com, et que l'ID d'un flux de nouvelles est 5, tu aurais dans LIENS_CATEGORIES, tu aurais:

    1, 5 (assigne 5 dans catégorie programmation)
    2, 5 ( assigne également 5 a php)

    si tu désires avoir une hierarchie de catégories, tu n'as qu'a ajouter un champ ID_CAT_PARENT dans ta table catégorie pour stocker l'id de la catégorie parent

    donc tu aurais dans ta table catégories:

    1: programmation : 0
    2: php : 1

    la catégorie programmation n'a pas de parent, donc 0.
    la catégorie php est sous programmation, donc on met 1 comme parent


    ohoh je crois que j'ai débordé !! désolé

  8. #8
    Invité
    Invité(e)
    Par défaut
    2. Si je souhaite créer des liaisons supplémentaires, par exemple associer des mots à des categories que je définirai dans ma base, de manière a ce que si une news paru sur travauxfacile.com comprends le mot "Sarkozy" si ce mot est stocké dans ma base et indique que la news doit aussi apparaitre dans la categorie politique, comment puis je créer ces liaisons ? Est ce mieux de rajouter un champs 'Liaisons' dans ma table 'news' ou alors est ce que je crée carrément une table 'liaison" : id, id_categorie, id_news ?
    ouais.. bonne question, plusieurs réponses possibles.

    répartition horizontale des données

    présentement si je résume tu dois avoir qqchose de similaire à:

    news
    id_news
    id_feed
    hash
    date_de_la_news
    titre_news
    contenu_news

    avec cette table, j'en ferais 2.

    news_info (table format INNODB ou myisam)
    id_news (clé primaire)
    id_feed (int, avec index)
    hash (char avec index)
    date_de_news (int ou smalldate avec index)

    news_content (table format MYISAM)
    id_news (clé primaire)
    titre_news ( index plein-texte)
    contenu_news (index plein-texte)

    l'index plein texte est une particularité du moteur MYISAM et est non-displible avec les bases INNODB.

    recherche 'FULLTEXT search' sur mysql ou google pour plus d'infos..

    tu pourrais ensuites te faire une table de mot-clés pour chaque catégories, genre:

    category_keywords

    id_cat (int)
    keyword (varchar(30))


    ensuite dans ton code, tu pourrais extraire la liste des mot-clés de chaques catégories et lancer un fULLTEXT search avec les commandes appropriées de mysql. Il va rechercher rapidement chaque titre ou contenu de news et te fournir les résultats. Tu pourrais rajouter cela dans ton CRON, pour raffraichair le résultat aux 5 minutes...


    ca serait super efficace comme méthode... tu peux ajouter/enlever des mot-clés en modifiant la table category_keywords..

    tu aurais pu ne pas diviser les tables en 2, mais bon, c'est plus rapide mais ca me tentait pas de l'expliquer dans mon message qui est déjà long..



    quand tu auras comprit mes suggestions et qu'il ne restera que cela, je t'expliquerai

    a+ amigo

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut
    Un énorme merci pour ta réponse

    Vraiment, c'est trop sympa l'aide que tu m'apportes

    Je viens d'utiliser ta technique pour faire moins de requete (tu es fort tu as deviné ma technique pour vérifier j'ai amélioré en suivant tes recommandations effectivement ca va plus vite meme si le compteur que j'ai mis mets maintenant 25 secondes c'est lié au temps pour aller lire les 220 flux rss sur 220 serveurs différents, j'etait plus aux alentours des 100 à 200 secondes avant )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $maquery="SELECT hash FROM news";
    $hashmem = mysql_query($maquery);
    while ($row = mysql_fetch_array($hashmem)){
    $data[] = $row[hash];
    }
    J'ai pas trouvé plus simple pour mettre mes hash dans un tableau Apres j'utilise un in_array pour vérifier si c'est présent dedans

    Il me reste encore à optimiser, et comparer uniquement les news présente dans ma base avec leur flux, pour le moment dans mon tableau je recupere toutes les news de tous les flux, donc je compare chaque news avec toutes les news de tous les flux.. Mais ça je devrait y arriver


    Pour le partitioning mon serveur n'a pas mysql5 donc c'est réglé
    Mais je compte prendre un petit dédié ensuite, donc je mettrai mysql5, et je ferai un partitioning par id_lang


    Pour ton deuxième post je ne me suis pas encore sérieusement penché dessus Par contre à premiere vue, une question se pose : pourquoi mettre les champs en FULL TEXT et donc rechercher mes MOTS liées aux categories avec des requetes mysql, alors que je peux le faire directement en PHP pendant que je recupere les news ( ce serait moins lourd non ? )

    PAr contre je viens d'apprendre l'existence du fulltext, et si je veux développer mon propre moteur de recherche, il me faudrait donc mettre en full text tous mes 'titre' et 'contenu' de news pour ameliorer la recherche ?


    Et encore un énorme merci pour le temps que tu me dédies

  10. #10
    Invité
    Invité(e)
    Par défaut
    Un énorme merci pour ta réponse
    Vraiment, c'est trop sympa l'aide que tu m'apportes
    ...
    que j'ai mis mets maintenant 25 secondes c'est lié au temps pour aller lire les 220 flux rss sur 220 serveurs différents, j'etait plus aux alentours des 100 à 200 secondes avant )
    ...
    pas mal non... tout s'optimise.. je suis content que tu aies de bons résultats

    Il me reste encore à optimiser, et comparer uniquement les news présente dans ma base avec leur flux, pour le moment dans mon tableau je recupere toutes les news de tous les flux, donc je compare chaque news avec toutes les news de tous les flux.. Mais ça je devrait y arriver
    oui tu peux rafiner avec le temps, mais c'est bien parti..

    Pour le partitioning mon serveur n'a pas mysql5 donc c'est réglé
    Mais je compte prendre un petit dédié ensuite, donc je mettrai mysql5, et je ferai un partitioning par id_lang
    si c'est trop long tu peux le faire manuellement...

    genre tu met des préfixes à tes tables et tu traite tes FEEDS en lots (francais avec francais, anglais avec anglais)
    fr_news
    en_news

    dans ton code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    $lng='fr';
     
    $sql = "select hash from {$lng}_news ";
    ...


    Pour ton deuxième post je ne me suis pas encore sérieusement penché dessus Par contre à premiere vue, une question se pose : pourquoi mettre les champs en FULL TEXT et donc rechercher mes MOTS liées aux categories avec des requetes mysql, alors que je peux le faire directement en PHP pendant que je recupere les news ( ce serait moins lourd non ? )
    Tu peux le gérer dans PHP si tu veux. Mais utilises le FULLTExt pour la recherche c'est vraiment rapide.. si tu fais ton propre moteur de recherche avec des indexes standards, les indexes 'standards' ne sont pas appropriés pour des recherches de texte aléatoire comme un usager peut le faire.

    PAr contre je viens d'apprendre l'existence du fulltext, et si je veux développer mon propre moteur de recherche, il me faudrait donc mettre en full text tous mes 'titre' et 'contenu' de news pour ameliorer la recherche ?
    je te suggère d'utiliser l'option Fulltext versus faire ton propre engin de recherche, cela sera surement plus rapide. Si par la suite tu désires t'y pencher, tu pourras toujours faire ta propre méthodologie de recherche

    Et encore un énorme merci pour le temps que tu me dédies
    pas de problèmes mon cher, de plus cela peut éclairer d'autres collègues.

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    category_keywords
     
    id_cat (int)
    keyword (varchar(30))
    Ma question portait plutot sur une table liaison ! C'est à dire les liens entre les News et les catégories !
    Effectivement j'ai besoin de cette table keywords, mais ensuite je souhaite ( lors de la récuperation des flux) créer mes liaisons entre mes news et les categories, est ce que c'est rapide de créer une table :
    LIAISON(id_news, id_categorie) avec une ligne pour chaque keyword de ma table category_keywords trouvé dans le titre ou le contenu d'une news
    c'est bien comme méthode ?

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par dynexd Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    category_keywords
     
    id_cat (int)
    keyword (varchar(30))
    Ma question portait plutot sur une table liaison ! C'est à dire les liens entre les News et les catégories !
    Effectivement j'ai besoin de cette table keywords, mais ensuite je souhaite ( lors de la récuperation des flux) créer mes liaisons entre mes news et les categories, est ce que c'est rapide de créer une table :
    LIAISON(id_news, id_categorie) avec une ligne pour chaque keyword de ma table category_keywords trouvé dans le titre ou le contenu d'une news
    c'est bien comme méthode ?
    tu peux utiliser cette methode sauf que tu auras beaucoup d'entrees dans cette table. Si tu as 500000 nouvelles tu auras minimum 500000 entrees. Par contre tu pourrais epurer cette table de temps a autres car cela ne donne pas grand chose d'avoir des liaisons pour des nouvelles plus vieilles que 45 jours.

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut
    ensuite dans ton code, tu pourrais extraire la liste des mot-clés de chaques catégories et lancer un fULLTEXT search avec les commandes appropriées de mysql.
    Tu me conseillerais plutot de ne pas créer de tables liaisons et de rechercher parmi les mots clés en permanence quand un visiteur est sur le site ?

    Car si la categorie "PHP" est lié à la categorie "Programmation", le truc c'est que dans la plupart des cas, l'interet de ces mots clés, c'est d'associer une news à une categorie qui n'a rien à voir : Si le mot "Sarkozy" est trouvé dans une news appartenant à la categorie "Programamtion" alors moi je souhaite qu'il y ai une liaison avec la categorie "Politique"
    Effectivement dans ma table Liaisons il y aurait plusieurs entrées pour chacune des news, mais je me demande si c'est pas plus efficace que faire une recherche FULLTEXT de mes mots clés à chaque fois qu'un visiteur se rends sur le site ?

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par dynexd Voir le message
    Tu me conseillerais plutot de ne pas créer de tables liaisons et de rechercher parmi les mots clés en permanence quand un visiteur est sur le site ?
    non, je disais 2 choses. Une chose est que tu peux utiliser le FULLText pour lorsque l'utilisateur clique sur SEARCH et qu'il entre un mot clé.


    Et la deuxieme chose, c'est que les liaisons entre certaines news et des catégories peuvent êtres effectuées avec des recherches FULLTEXT mais au lieu de le faire en temps réel, tu le fais dans ta job CRON aux 5 minutes.

    Genre si tu as une table qui dit, on assigne les news Apple à la catégorie Apple, le FULLtext aurait été capable de faire cela.

    Si tu veux le faire dans PHP en même temps que tu lis tes news , c'est correct aussi.


    Fait ta table liaison comme tu le mentionnais hier..



    Effectivement dans ma table Liaisons il y aurait plusieurs entrées pour chacune des news, mais je me demande si c'est pas plus efficace que faire une recherche FULLTEXT de mes mots clés à chaque fois qu'un visiteur se rends sur le site ?
    l'intéret du fulltext vient à sa grande puissance. Présentement tu parles de liaisons de certains mots à des catégories, mais éventuellement tu voudras sans doute permettre à un utilisateur de chercher des news en utilisant n'importe quel mots, et ce même si il n'Apparait pas dans ta table liaison.

    L'index FULLTEXT te permettra de rechercher rapidement ce que tu veux, comparativement à l'index traditionnel.


    Je te suggère de faire les deux. Fait ta table liaison et lie tes news aux catégories en PHP comme tu pensais le faire. Mais si jamais tu veux faire un 'search box' sur ta page de nouvelle. Tu devrais utiliser l'index FULLTEXT au lieu de recherche une nouvelle avec qqchose de similaire à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    where titre like '%mon mot clé%'
    car ce bout de code, n'utilisera jamais l'index, même si tu en as un de définit.

  15. #15
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut
    Merci encore pour toutes ces précisions ( ou ce cours particulier ) , j'ai appris beaucoup déjà !

    Pour revenir au système de catégorie que tu m'as conseillé, j'ai créé une table
    Cat : id, nom , id_parent

    id_parent = 0 correspondand à la racine !

    Mais pour ce qui est de la requete SQL c'est un vrai casse tête

    Je ne comprends pas commment faire pour utiliser ce système, étant donné que pour chaque categorie, on ne sait pas combien de sous categories à l'intérieur.........

    C'st possible avec une seule requete ou faut faire des requetes à l'intérieur des boucles de requêtes ???



    Code : 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
    20
    21
    22
    23
    24
    25
    26
    27
    $query = "SELECT cat.id_parent AS id_p, cat.id AS id , cat.nom as nom 
    FROM cat WHERE id_parent=0";
    $sql = mysql_query($query);
    while ($row = mysql_fetch_array($sql))
    {
    	echo "<p>";
    	echo $row['nom']. "<br/>";
    	$query2 = "SELECT  cat.id_parent AS id_p, cat.id AS id  , cat.nom as nom 
    	FROM cat WHERE id_parent=".$row['id'];
    	$sql2 = mysql_query($query2);
     
    	while ($row2 = mysql_fetch_array($sql2))
    	{	
     
    		echo $row['nom']. " >> " . $row2['nom'] . "<br/>"; 
     
    			$query3 = "SELECT  cat.id_parent AS id_p, cat.id AS id  , cat.nom as nom 
    			FROM cat WHERE id_parent=".$row2['id'];
    			$sql3 = mysql_query($query3);
    			$i=0;
    			while ($row3 = mysql_fetch_array($sql3))
    			{	
    				echo $row['nom']. " >> " . $row2['nom']. " >> " . $row3['nom'] . "<br/>"; 
    			}
    	}
    	echo "</p>";
    }
    Pour afficher ma hiérarchie, par exemple, j'utilise 1 sous requete pour chaque niveau supplémentaire.... Ca devient vite lourd...

  16. #16
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par dynexd Voir le message
    }[/CODE]Pour afficher ma hiérarchie, par exemple, j'utilise 1 sous requete pour chaque niveau supplémentaire.... Ca devient vite lourd...
    d'accord.. mais ce n'est pas si sorcier. J'imagine que tu n'As pas 3000 catégories, je te propose donc de les mettres en mémoire.

    Voit ça un peu comme un contrôle 'treeview'. Tu dois charger tes catégories en mémoire.

    ex:
    select id, nom, id_parent

    tu mets ton résultat dans un tableau
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $cat=array();
    $cat[$id_parent][]=$id;
    pour les données suivantes:

    1,Programmation,0
    2,Musique,0
    3,Cinema,0
    4,PHP,1
    5,ASP,1

    tu devrais donc avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $cat[0][0]=1; //programmation
    $cat[0][1]=2; //musique
    $cat[0][2]=3; //cinema
    $cat[1][0]=4;  //php
    $cat[1][1]=5; //asp
    ou encore tu aurais pu faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $cat=array();
    $cat[$id_parent][$id]=$nom_categorie;
     
    //donc
    $cat[1][4]=='php';
    en mettant les données dans un tableau tu évites d'avoir à faire des sous requetes a chaque fois. Tu lis la table une fois ensuite tu parcours le tableau. En stockant les élements dans un tableau par l'id du parent, ca te permet facilement d'énumérer les sous-catégories.

    De plus, ton tableau de catégorie, tu pourrais le mettre en cache avec un systeme comme APC cache ou memcache. De cette facon tu pourrais aller lire tes catégories une fois l'heure (ou selon la période désirée).

    mais déjà on vient de passer de 'pleins de requêtes' à une seule.


  17. #17
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut
    Ok merci beaucoup

    Effectivement, avoir le réflexe d' archiver les résultats des requetes SQL ca peut permettre pas mal de choses sympas

    Sur le site http://www.sitepoint.com/article/hie...ta-database/3/ ils parlaient de cette méthode ( et aussi de celle des nested trees) mais utilisaient de multiples requetes et sous requetes par exemple....

    Code : 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
    20
    21
    22
    echo "<p>";
     
    	foreach ($cat[0] as $valeur => $valeur2) {
    		echo  $valeur . " - " . $valeur2 . "<br/>";
     
    			if (count($cat[$valeur]) >0 ) 
    			{
    				foreach ($cat[$valeur] as $valeur3 => $valeur4) {
    					echo $valeur2 . " >> " . $valeur4 . " <br/>";
     
    					if (count($cat[$valeur3]) >0 ) {
    						foreach ($cat[$valeur3] as $valeur5 => $valeur6) {
    							echo $valeur2 . " >> " . $valeur4 . " >> " . $valeur6 . " <br/>";
    						}
    					}
     
    				}
    			}
     
    	}
     
    echo "</p>";
    Voila mon code pour afficher le listing des categorie
    ( ça me servira dans mon administration pour choisir mes catégories avec un menu déroulant )

    Encore un énorme merci

  18. #18
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par dynexd Voir le message
    Ok merci beaucoup

    Code : 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
    20
    21
    22
    echo "<p>";
     
    	foreach ($cat[0] as $valeur => $valeur2) {
    		echo  $valeur . " - " . $valeur2 . "<br/>";
     
    			if (count($cat[$valeur]) >0 ) 
    			{
    				foreach ($cat[$valeur] as $valeur3 => $valeur4) {
    					echo $valeur2 . " >> " . $valeur4 . " <br/>";
     
    					if (count($cat[$valeur3]) >0 ) {
    						foreach ($cat[$valeur3] as $valeur5 => $valeur6) {
    							echo $valeur2 . " >> " . $valeur4 . " >> " . $valeur6 . " <br/>";
    						}
    					}
     
    				}
    			}
     
    	}
     
    echo "</p>";
    Voila mon code pour afficher le listing des categorie
    ( ça me servira dans mon administration pour choisir mes catégories avec un menu déroulant )

    Encore un énorme merci
    pas de problèmes! par contre le code ci-haut c'est pas trop élégant.
    Tu peux faire plus en moins de lignes de code..


    voici du code non testé (j'écris de mémoire)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    function AfficheCat($cat,$niveau=0)
    {
       echo "<ul class='niveau{$niveau}'>";
       foreach ($cat as $k => $v)
       {
          if (is_array($v))
               AfficheCat($cat,$niveau+1);
          else
               echo "<li>{$v}</li>";
       }
       echo "</ul>";
    }
    AfficheCat($cat);   //en ne spécifiant pas le $niveau, son contenu sera 0
    si tu veux couper dans le gras, tu peux enlever la génération de tag UL et LI.. mais en gros cette fonction te permet de générer des listes HTML et chaque liste aura un tag CLASS différent, donc en CSS tu peux controler
    a 100% ton affichage des catégories sans modifier ton code.
    Donc tu peux mettre des caractères plus gros pour le niveau0, et plus petit pour niveau1..

    etc....

    supporte un nombre illimité de sous-catégories....

    tu pourrais aussi ajouter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if ($niveau>2)
       echo "<ul class='niveau2'>";
    else
       echo "<ul class='niveau{$niveau}'>";
    comme cela, les 3 premiers niveaux 0,1,2 sont uniques en apparence et les autres sont identiques au niveau #2.

    je sais pas si je suis clair mais bon!
    :-)

  19. #19
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 45
    Points : 28
    Points
    28
    Par défaut
    Nickel ta fonction merci

    Je maitrise les CSS donc ça coule tout seul pour une fois ce que tu m'explique

    En l'occurence c'est une liste deroulante pour un formulaire donc j'en ai pas besoin, mais j'y penserai pour l'affichage des categories sur le site

  20. #20
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par dynexd Voir le message
    Nickel ta fonction merci

    Je maitrise les CSS donc ça coule tout seul pour une fois ce que tu m'explique

    En l'occurence c'est une liste deroulante pour un formulaire donc j'en ai pas besoin, mais j'y penserai pour l'affichage des categories sur le site
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function AfficheCat($cat,$niveau=0)
    {
       echo "<ul class='niveau{$niveau}'>";
       foreach ($cat AS $k => $v)
       {
          if (is_array($v))
               AfficheCat($v,$niveau+1);
          else
               echo "<li>{$v}</li>";
       }
       echo "</ul>";
    }
    AfficheCat($cat);   //en ne spécifiant pas le $niveau, son contenu sera 0
    j'ai toujours pas testé mais en me relisant, j'Ai vu un bug. AfficheCat($v,$niveau+1) au lieu de AfficheCat($cat,$niveau+1);

    il peut y en avoir d'autres! :-)

Discussions similaires

  1. [Requête SQL] Optimisation de plusieurs UPDATE SET FROM
    Par dens19 dans le forum Développement
    Réponses: 6
    Dernier message: 13/03/2009, 16h51
  2. Optimisation requete SQL ,plusieurs jointure ?
    Par mamiberkof dans le forum Langage SQL
    Réponses: 1
    Dernier message: 22/02/2008, 16h39
  3. [SQL] Requete avec ordre correspondant à la clause WHERE
    Par yobogs dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 10/06/2007, 14h32
  4. Réponses: 1
    Dernier message: 29/03/2006, 11h33
  5. Optimisation du code des ordres SQL
    Par Titouf dans le forum Langage SQL
    Réponses: 1
    Dernier message: 14/08/2005, 22h08

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