Partage
  • Partager sur Facebook
  • Partager sur Twitter

Chargement d'éléments contenus dans une table volumineuse

Sujet résolu
    21 novembre 2010 à 20:22:33

    Bonsoir bonsoir :)

    Dites je me pose une question : pour éviter le parsage du contenu (contenu récupéré dans ma bdd) à chaque chargement d'une page, j'ai dédoublé plusieurs champs d'une de mes table, champs qui contiennent tout de même 10Kio en moyenne.

    La place n'est pas un problème au temps des "gigas à profusion", mais un ami informaticien m'a fait remarqué que récupérer du contenu dans une grosse table était plus "lourd" (et donc lent) que dans une table plus petite.

    Finalement je me demande s'il vaut mieux pas revenir au parsage de mon contenu "en temps réel" (à l'ouverture d'une page donc) plutôt que de stocker le contenu parsé...


    Savez-vous ce qu'il en est ?
    • Partager sur Facebook
    • Partager sur Twitter
      21 novembre 2010 à 21:10:05

      Salut,

      Il est evident que a l'heure actuelle, ce n'est plus vraiment un probleme de place mais bien de temps de traitement.
      Plus ta table est grosse et plus ca sera long. Certains boite interdise meme a leur informaticien l'utilisation de certaines jointure pour eviter des plantage, tellement leur table sont importante.

      Dans ton cas tous depend du nombre d'entrée, mais 10kio pour un seul champs c'est deja tres important.

      Sache que dans tous les cas, la redondance d'information n'est que tres rarement benefique.
      • Partager sur Facebook
      • Partager sur Twitter
        21 novembre 2010 à 21:47:38

        Donc vaut mieux parser en sachant que le parsage prends lui aussi un certain temps.

        Au fait, si tu as le temps pourrais-tu approfondir le cas présent ?

        Quel phénomène explique le fait que plus la table est grosse, et plus le chargement est long. Car d'après mes (faibles) savoirs, l'instruction est on ne peut plus précise : "va chercher ça dans telle case".

        Je ne sais pas comment ça se passe niveau informatique, mais il est vrai que si on prends l'exemple d'une bibliothèque, il est effectivement plus long de chercher le livre XY dans une bibliothèque nationale plutôt que dans une biblio communale.

        Cependant je doute que les algorithmes de MySQL fonctionnent pareil...

        Merci d'avance :)
        • Partager sur Facebook
        • Partager sur Twitter
          21 novembre 2010 à 22:09:03

          Tu as raison, mais une des premières cause de perte de temps ne vient pas de l'algo en lui même mais de la place prise en mémoire, et du temps qu'il faut pour que la table aille en mémoire. Car pour accélérer le temps de recherche, sql mais toute la table dans la mémoire avant de faire quelque chose.
          Et si une table simple est placé ca va (quoique ca dépend de la taille évidement), mais des qu'on doit mettre une jointure ou plus dans la mémoire ca prends tres vite de la place.

          Il est d'ailleurs déconseillé de faire des requêtes dépassant les 4-5 jointures de façon général.

          On souligne assez peu, mais le faire un select uniquement des champs qui nous intéresse réellement est aussi très important pour réduire les temps de mise en mémoire.

          Plus généralement, les base de données relationnel sont basé sur l'algebre relationnel découlant de la théorie des ensembles entre autre. L'etudier permet de mieux comprendre la facon de faire une requete, et de l'optimiser, ainsi que d'apprendre a penser logique avec les BDDRs

          Dans ton cas, il vaut mieux transformer ton texte en html avant de la mettre dans la base, car tu ne fera qu'un traitement la ou tu en fera des dizaines lors de l'affichage pour chaque personne qui voudra visualiser la page...
          • Partager sur Facebook
          • Partager sur Twitter
            21 novembre 2010 à 22:21:13

            Parfait, je vais rouvrir mon cours sur la théorie des ensembles alors ^^


            Merci en tout cas, et à bientôt !
            • Partager sur Facebook
            • Partager sur Twitter
              22 novembre 2010 à 23:32:18

              Je suppose qu'il s'agit de bbcode que tu parses à l'affichage ?...

              Bon, dans ce cas la solution est simple, tu stockes dans ta table posts :
              - le bbcode original
              - le bbcode parsé en html prêt à être affiché

              Tu créé l'index de recherche fulltext sur celui qui marche le mieux (plutôt le html). Si ta base de données compresse, tu as fini, sinon tu peux stocker l'autre en blob compressé avec gzip.

              Si ton forum est vraiment gros, tu peux remarquer que ton working set est essentiellement du html puisque tu as 99% d'affichage et 1% d'édition de posts, et faire un petit partitionnement vertical des familles, autrement dit tu mets le html dans la table posts (celle qui sert tout le temps) et tu stockes le bbcode dans une table à part avec juste l'id du post, qui servira donc uniquement lors des éditions de posts, et tu le cache disque qui aurait été utilisé pour stocker ça est donc libéré.
              • Partager sur Facebook
              • Partager sur Twitter
                23 novembre 2010 à 10:27:03

                Aha, ta méthode est nickel casque noir, c'est celle que j'utilisais avant. Je sais plus pourquoi ça m'énervais de gérer deux tables et j'ai fusionné les deux, d'où la problématique exposée ici (je savais pas que ça alourdissait les requêtes...).

                Je songe donc à repasser à cette ancien mode, mais une autre alternative que je suis en train de mettre au point est le stockage du contenu html uniquement, et lors de l'édition on parse ce contenu pour obtenir du bbcode :)

                Qu'en dis-tu ?
                • Partager sur Facebook
                • Partager sur Twitter
                  23 novembre 2010 à 11:04:11

                  Citation : Mr Konijn

                  (je savais pas que ça alourdissait les requêtes...).



                  Bon, imagine une requête qui affiche une page de forums, grosso modo : "WHERE topic_id = machin ORDER BY post_id LIMIT postsparpage OFFSET (page-1)*postsparpage" dans cette requête il y a deux choses :

                  1- la BDD doit sauter (page-1)*postsparpage posts, mysql peut faire ceci en parcourant uniquement l'index sur (topic_id,post_id) donc la taille de la table n'a aucune influence (uniquement le nombre de posts à sauter pour arriver à la page en question). Personnellement comme on affiche généralement que la première ou la dernière page, mon forum compte les posts à partir du début (ORDER BY post_id) ou à partir de la fin (ORDER BY post_id DESC) en tenant compte du nombre de posts dans le topic (stocké dans la table topics) ce qui accélère grandement la navigation dans les topics à flood, la dernière page est aussi rapide que la première, et la plus lente est celle du milieu.

                  2- ensuite la BDD doit choper postsparpage posts dans la table : Puisque la table est indexée correctement et que la requête est très simple, la taille de la table n'a aucune importance ... tant qu'elle tient en RAM. C'est important que ta table posts soit en cache (RAM) sinon les accès disque plombent la performance. Donc diviser la taille de la table par 2 en fourrant un des 2 TEXT dans une autre table rarement utilisée est un gros avantage ! De plus il est avantageux d'avoir une organisation de la table sur le disque par (topic_id,post_id) pour grouper ensemble les posts d'un même topic, malheureusement InnoDB ne peut pas faire ça car il organise tout sur la clé primaire. Un exemple, si ta table n'est pas en cache, mais qu'elle est organisée par (topic_id,post_id) une page nécessite 1 seek disque (~ 10 ms) qui chope tous les posts d'un coup ; si elle est organisée aléatoirement, il faut dans le pire cas, 1 seek par post, donc aïe.

                  Citation : Mr Konijn

                  Je songe donc à repasser à cette ancien mode, mais une autre alternative que je suis en train de mettre au point est le stockage du contenu html uniquement, et lors de l'édition on parse ce contenu pour obtenir du bbcode :)



                  Si tu as envie de te cogner un parser bidirectionnel bbcode <=> html ça pourrait bien être la meilleure solution.

                  PS : Si t'as un gros forum la chose qui passe pour un index FULLTEXT dans MySQL est à éviter !
                  • Partager sur Facebook
                  • Partager sur Twitter
                    23 novembre 2010 à 12:33:59

                    Merci pour ces précisions, mais en fait il s'agit juste d'articles, et non d'un forum. J'essaye d'optimiser le chargement de ce genre de page ci car leur temps de chargement est exécrable : http://www.questmachine.org/Articles/a [...] ne.php?a=2106.

                    Au fait, tu va me prendre pour un nul mais on m'a plus d'une fois parlé du gzip, donc le fait de compresser sa table. En quoi ça consiste exactement ?
                    • Partager sur Facebook
                    • Partager sur Twitter
                      23 novembre 2010 à 13:56:02

                      Sympa ton site.

                      J'ai fait un test avec wget, le temps de chargement a l'air généralement correct, mais des fois c'est énorme !

                      Questions : tu vas faire un peu de copier coller

                      - taille de ta BDD (screenshot de la liste des tables dans phpmyadmin),
                      - specs du serveur (RAM, cpu, disque, OS, versions serveur web, mysql, php, etc)
                      - log de 1 minute de "vmstat 5" sur serveur chargé
                      - log de 1 minute de "iostat 5" sur serveur chargé
                      - screenshot du top sur serveur chargé
                      - SHOW FULL PROCESSLIST (dans mysql) sur serveur chargé (vérifie si y'a pas des mots de passe dedans !)
                      - Tu devrais profiler (mesure le temps de toutes les requêtes et le temps total utilisé par php)
                      - autres ?

                      > le fait de compresser sa table

                      postgres (et autres) compressent automatiquement de façon transparente tout champ texte ou blob suffisamment gros pour que ça vaille le coup. MySQL ne le fait pas, donc tu peux utiliser gzip en php pour compresser ton texte et le stocker compressé. L'inconvénient est que le moteur de recherche FULLTEXT est alors incapable de fonctionner (mais ce n'est pas grave, puisque de toutes façons, il ne sert à rien si ta table est assez grosse pour que tu aies besoin de compression...)

                      en tout cas c'est un hack donc utile uniquement si tu as un dédié pas cher et une base trop grosse XD
                      • Partager sur Facebook
                      • Partager sur Twitter
                        23 novembre 2010 à 15:17:42

                        Héhé, hormis des screens sur la taille de la bdd, je ne sais rien te fournir :(

                        Faudrait que j'envoie un mail à l'hébergeur pour connaître la config du serveur (d'ailleurs pour le SHOW FULL PROCESSLIST, je n'ai pas la main sur le serveur) et pour les stats... je suis pas sous linux.

                        Voilà tout de même 2 screens : http://www.questmachine.org/BDD.png et http://www.questmachine.org/Structure_articles.png
                        • Partager sur Facebook
                        • Partager sur Twitter
                          23 novembre 2010 à 15:53:43

                          Ton PNG est un tiff XD

                          Tes tables ne sont pas énormes, pour 1000 articles si ils sont un peu dodus 30 Mo ça fait 30 Ko par article, donc raisonnable.

                          Si ton serveur est un mutualisé, ça peut expliquer pourquoi ça rame : il suffit qu'un neuneu ait installé un site très mal optimisé ou un tracker torrent en PHP sur le même serveur BDD que toi...

                          Sinon, que font ces tables en MyISAM ? Tout devrait être en InnoDB. Et ta structure est pas terrible : il vaut mieux utiliser une table de lien si tu as des catégories multiples (des colonnes categorie1 categorie2 categorie3 = erreur) idem pour des champs que je suspecte de contenir des listes (validateurs, articles lies...) pas très propre tout ça XDDDDD

                          Tes champs avec des listes dedans, je suppose que tu fais des recherches LIKE dessus ? Dans ce cas toute la table est parcourue à chaque fois...

                          Chronomètre tes requêtes.

                          Essaie SHOW PROCESSLIST (sans FULL), normalement tu devrais pouvoir l'obtenir, cela ne nécessite normalement pas de privilège root.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            23 novembre 2010 à 16:11:05

                            Citation : Lord casque noir

                            Ton PNG est un tiff XD


                            Aha, merde, tu l'a remarqué (remarque c'était risqué puisque pas bcp de navig savent visionner les tiff :p ).


                            Sinon c vrai que c'est pas énorme, surtout que ton petit calcul se base sur 1000 article... alors qu'il y en a 1920. Niveau optimisation, tout est +- au point (pour le niveau d'utilisation du site).

                            Je ne fais jamais de recherche LIKE dedans et les catégorie contiennent uniquement des tinyint.

                            Comme il fallait bien que je me décide à faire quelque chose, je vais retourné à l'ancienne méthode : avant je concervais uniquement le bbcode que je parsait avec un script php à l'ouverture d'une page.


                            PS : le SHOW PROCESSLIST me retourne des bêtises.

                            RE-PS : il a vraiment une sale tronche ce lord casque noir. Héhé, ça me fait penser que l'autre jour je regardais le début, et j'ai trouvé ça tellement con que j'ai zappé (et ça m'arrive pas souvent de zapper des films cultes pourtant !)
                            • Partager sur Facebook
                            • Partager sur Twitter
                              23 novembre 2010 à 16:29:05

                              Bizarre pour le processlist. Mais ça ne t'empêche pas de mettre un profiler sur tes requêtes : dans la fonction que tu utilises pour faire tes requêtes, rajoute des microtime() pour mesurer le temps d'exécution et affiche le résultat en bas de page, visible uniquement par toi.

                              A mon avis tu as soit un problème d'hébergeur, soit un problème de locks (et le fait que tu aies des tables en myisam ne peut qu'empirer la chose.

                              PS : Ce film est complètement con, mais j'adore. Il faut être bourré.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                23 novembre 2010 à 18:19:32

                                Si je me souviens bien faut une table MyIsam pour mettre un index fulltext non ?

                                Deplus, mon moteur fait ses recherches avec WHERE MATCH ... AGAINST ... et je crois que la doc m'avais également indiqué qu'il fallait des tables en myisam...
                                • Partager sur Facebook
                                • Partager sur Twitter

                                Chargement d'éléments contenus dans une table volumineuse

                                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                • Editeur
                                • Markdown