[Resolu] [phpBB] Ajouter colonne "Nb de sujets" dans memberlist.php

Ajouter colonne "Nb de sujets" dans memberlist.php [Resolu] [phpBB] - PHP - Programmation

Marsh Posté le 13-03-2008 à 17:53:48    

Bonjour,
 
J'ai rajouté une colonne "Sujets" dans memberlist.php qui affiche le nombre de sujets de chaque membre.
J'utilise une Jointure avec "INNER JOIN" et "t.topic_poster = u.user_id"
Or tous les membres qui n'ont créé aucun topic sont ignoré en faisant comme ça.
 
Il faudrait utiliser "LEFT JOIN" pour que tout s'affiche.
 
Mais voilà mon problème, dès que je remplace "INNER JOIN" par "LEFT JOIN", la requête devient très longue. Elle passe d'environ 0,15 0.0740 seconde d'exécution à plus de 40 secondes.
 
Voici le code php de la requête avec INNER JOIN:
 

Code :
  1. $sql = "SELECT u.username, u.user_id, u.user_viewemail, u.user_posts, u.user_regdate, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_avatar, u.user_avatar_type, u.user_allowavatar, u.user_allow_viewonline, u.user_session_time, u.user_points, t.topic_poster, COUNT(t.topic_id) AS count_topic_nb
  2.    FROM " . USERS_TABLE . " u INNER JOIN " . TOPICS_TABLE . " t ON t.topic_poster = u.user_id
  3.    WHERE u.user_id <> " . ANONYMOUS . "$letter_sql
  4.    GROUP BY u.username, u.user_id, u.user_viewemail, u.user_posts, u.user_regdate, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_avatar, u.user_avatar_type, u.user_allowavatar, u.user_allow_viewonline, u.user_session_time, u.user_points, t.topic_poster
  5.    $order_by";
  6. //-- mod : flags ---------------------------------------------------------------
  7. //-- add
  8.    $sql = str_replace('SELECT ', 'SELECT u.user_flag, ', $sql);
  9.    $sql = str_replace('GROUP BY ', 'GROUP BY u.user_flag, ', $sql);
  10. //-- fin mod : flags -----------------------------------------------------------    
  11. //-- mod : rank color system ---------------------------------------------------
  12. //-- add
  13. $sql = str_replace('SELECT ', 'SELECT u.user_level, u.user_color, u.user_group_id, ', $sql);
  14. $sql = str_replace('GROUP BY ', 'GROUP BY u.user_level, u.user_color, u.user_group_id, ', $sql);
  15. //-- fin mod : rank color system -----------------------------------------------


 
 
Ce qui donne ceci :
 

Code :
  1. SELECT u.user_level, u.user_color, u.user_group_id, u.user_flag, u.username, u.user_id, u.user_viewemail, u.user_posts, u.user_regdate, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_avatar, u.user_avatar_type, u.user_allowavatar, u.user_allow_viewonline, u.user_session_time, u.user_points, t.topic_poster, COUNT(t.topic_id) AS count_topic_nb
  2. FROM table_users u
  3.  INNER JOIN table_topics t
  4.    ON t.topic_poster = u.user_id
  5. WHERE u.user_id <> -1
  6.  AND u.username LIKE '%'
  7. GROUP BY u.user_level, u.user_color, u.user_group_id, u.user_flag, u.username, u.user_id, u.user_viewemail, u.user_posts, u.user_regdate, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_avatar, u.user_avatar_type, u.user_allowavatar, u.user_allow_viewonline, u.user_session_time, u.user_points, t.topic_poster
  8. ORDER BY u.user_regdate ASC
  9. LIMIT 0, 30


 
Sauriez-vous me dire ce qui ne va pas ?
 
Merci d'avance pour votre aide.


Message édité par mkex64 le 16-03-2008 à 07:02:30

---------------
http://www.unicornis.org/
Reply

Marsh Posté le 13-03-2008 à 17:53:48   

Reply

Marsh Posté le 14-03-2008 à 14:13:13    

En combien s'affiche la requete SQL de base ? Y-a-til les GROUP BY dedans ?


---------------
Feedback : http://forum.hardware.fr/hfr/Achat [...] 2666_1.htm
Reply

Marsh Posté le 14-03-2008 à 14:37:16    

Bonjour,
 
Je n'ai pas compris se que tu me demande babasss ?


---------------
http://www.unicornis.org/
Reply

Marsh Posté le 14-03-2008 à 14:40:46    

Normal, je sais pas écrire une phrase....  :D  
 
En combien de temps s'affichait la requete SQL de base ? Y-a-til les GROUP BY dedans ?


---------------
Feedback : http://forum.hardware.fr/hfr/Achat [...] 2666_1.htm
Reply

Marsh Posté le 14-03-2008 à 14:48:12    

Tu as essayé avec une sous requete :

Code :
  1. SELECT u.user_level, u.user_color, u.user_group_id, u.user_flag, u.username, u.user_id AS USERID,
  2.  u.user_viewemail, u.user_posts, u.user_regdate, u.user_from, u.user_website, u.user_email,
  3.  u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_avatar, u.user_avatar_type,
  4.  u.user_allowavatar, u.user_allow_viewonline, u.user_session_time, u.user_points, t.topic_poster,
  5.  ( SELECT COUNT(topic_id) FROM table_topics WHERE topic_poster = USERID GROUP BY topic_poster ) AS count_topic_nb
  6.    FROM table_users u
  7.    WHERE u.user_id <> -1
  8.     AND u.username LIKE '%'
  9.    GROUP BY u.user_level, u.user_color, u.user_group_id, u.user_flag, u.username, u.user_id, u.user_viewemail, u.user_posts,
  10.  u.user_regdate, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_avatar,
  11.  u.user_avatar_type, u.user_allowavatar, u.user_allow_viewonline, u.user_session_time, u.user_points
  12.    ORDER BY u.user_regdate ASC
  13.    LIMIT 0, 30


Message édité par babasss le 14-03-2008 à 14:48:40

---------------
Feedback : http://forum.hardware.fr/hfr/Achat [...] 2666_1.htm
Reply

Marsh Posté le 14-03-2008 à 14:53:57    

Ok donc,
 
La requête SQL de base, donc sans mes modifications, il n'y a pas les GROUP BY, la voici :
 

Code :
  1. $sql = "SELECT username, user_id, user_viewemail, user_posts, user_regdate, user_from, user_website, user_email, user_icq, user_aim, user_yim, user_msnm, user_avatar, user_avatar_type, user_allowavatar, user_allow_viewonline, user_session_time, user_points
  2.     FROM " . USERS_TABLE . "
  3.     WHERE user_id <> " . ANONYMOUS . "$letter_sql
  4.     ORDER BY $order_by";
  5. //-- mod : flags ---------------------------------------------------------------
  6. //-- add
  7.     $sql = str_replace('SELECT ', 'SELECT user_flag, ', $sql);
  8. //-- fin mod : flags -----------------------------------------------------------    
  9. //-- mod : rank color system ---------------------------------------------------
  10. //-- add
  11. $sql = str_replace('SELECT ', 'SELECT user_level, user_color, user_group_id, ', $sql);
  12. //-- fin mod : rank color system -----------------------------------------------


 
 
Et pour le temps d'exécution il est entre : 0,15s et 0,20s 0,0287s
Donc autant qu'après ma modifications et avec "INNER JOIN"
 
Merci.
 
 
EDIT : Je me trompe, c'est plutôt 0,0287s et 0.0740s pour mon code modifié avec INNER JOIN
 

Code :
  1. SELECT user_level, user_color, user_group_id, user_flag, username, user_id, user_viewemail, user_posts, user_regdate, user_from, user_website, user_email, user_icq, user_aim, user_yim, user_msnm, user_avatar, user_avatar_type, user_allowavatar, user_allow_viewonline, user_session_time, user_points
  2. FROM table_users
  3. WHERE user_id <> -1
  4. AND username LIKE '%'
  5. ORDER BY user_regdate ASC LIMIT 0, 30


 
 
Je viens de tester ceci :

Code :
  1. SELECT user_level, user_color, user_group_id, user_flag, username, user_id AS USERID,
  2.     user_viewemail, user_posts, user_regdate, user_from, user_website, user_email,
  3.     user_icq, user_aim, user_yim, user_msnm, user_avatar, user_avatar_type,
  4.     user_allowavatar, user_allow_viewonline, user_session_time, user_points,
  5.     ( SELECT COUNT(topic_id) FROM table_topics WHERE topic_poster = USERID GROUP BY topic_poster ) AS count_topic_nb
  6.       FROM table_users
  7.       WHERE user_id <> -1
  8.        AND username LIKE '%'
  9.       ORDER BY user_regdate ASC
  10.       LIMIT 0, 30


 
 
Ca a l'air de fonctionner, temps d'exécution 0,29s mais plus lourd quand même


Message édité par mkex64 le 14-03-2008 à 15:24:17

---------------
http://www.unicornis.org/
Reply

Marsh Posté le 14-03-2008 à 15:26:17    

Entre 0.29s et 40s, il y a de l'amélioration....
Il va forcément y avoir une charge supplémentaires en utilisant un système simple. Si tu as vraiment un problème de temps de réponse, tu peux faire une table agrégé qui te calcule tous les heures (via un CRON) le nb de post par id et tu fais une jointure avec cette table. Mais ce système est vraiment plus lourd...


Message édité par babasss le 14-03-2008 à 15:26:50

---------------
Feedback : http://forum.hardware.fr/hfr/Achat [...] 2666_1.htm
Reply

Marsh Posté le 14-03-2008 à 15:34:45    

Je récapitule pour que ce soit plus clair :
 
- Requête de base, sans la colonne NB de sujets : Tps d'écution : 0,0287s
 

Code :
  1. SELECT user_level, user_color, user_group_id, user_flag, username, user_id, user_viewemail, user_posts, user_regdate, user_from, user_website, user_email, user_icq, user_aim, user_yim, user_msnm, user_avatar, user_avatar_type, user_allowavatar, user_allow_viewonline, user_session_time, user_points
  2.    FROM table_users
  3.    WHERE user_id <> -1
  4.    AND username LIKE '%'
  5.    ORDER BY user_regdate ASC LIMIT 0, 30


 
 
- Ma modifications de la requête pour ajouter la colonne NB de sujets, qui fonctionne presque entièrement car il ignore tout les membres ayant 0 topics (ce qui est normal) : Tps d'éxécution : 0.0740s
Donc c'est presque ça...
 

Code :
  1. SELECT u.user_level, u.user_color, u.user_group_id, u.user_flag, u.username, u.user_id, u.user_viewemail, u.user_posts, u.user_regdate, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_avatar, u.user_avatar_type, u.user_allowavatar, u.user_allow_viewonline, u.user_session_time, u.user_points, t.topic_poster, COUNT(t.topic_id) AS count_topic_nb
  2.    FROM table_users u
  3.     INNER JOIN table_topics t
  4.       ON t.topic_poster = u.user_id
  5.    WHERE u.user_id <> -1
  6.     AND u.username LIKE '%'
  7.    GROUP BY u.user_level, u.user_color, u.user_group_id, u.user_flag, u.username, u.user_id, u.user_viewemail, u.user_posts, u.user_regdate, u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim, u.user_yim, u.user_msnm, u.user_avatar, u.user_avatar_type, u.user_allowavatar, u.user_allow_viewonline, u.user_session_time, u.user_points, t.topic_poster
  8.    ORDER BY u.user_regdate ASC
  9.    LIMIT 0, 30


- Même code mais avec LEFT JOIN, ça fonctionne mais le temps d'exécution passe à plus de 40 secondes.  :pt1cable:  
 
 
 
- Et la requête qui fonctionne le mieux pour le moment : mais quand même environ 10 fois plus lourde que la requêtes de base : temps d'exécution 0,29s :
 

Code :
  1. SELECT user_level, user_color, user_group_id, user_flag, username, user_id AS USERID,
  2.        user_viewemail, user_posts, user_regdate, user_from, user_website, user_email,
  3.        user_icq, user_aim, user_yim, user_msnm, user_avatar, user_avatar_type,
  4.        user_allowavatar, user_allow_viewonline, user_session_time, user_points,
  5.        ( SELECT COUNT(topic_id) FROM table_topics WHERE topic_poster = USERID GROUP BY topic_poster ) AS count_topic_nb
  6.          FROM table_users
  7.          WHERE user_id <> -1
  8.           AND username LIKE '%'
  9.          ORDER BY user_regdate ASC
  10.          LIMIT 0, 30


 
 
Merci babasss je vais garder cette derniere requête, en attendant si je trouve mieux.


Message édité par mkex64 le 14-03-2008 à 15:35:56

---------------
http://www.unicornis.org/
Reply

Marsh Posté le 14-03-2008 à 16:02:48    

Par contre je viens de voir qu'avec cette dernière requête, si je trie par nombre de sujet, le temps d'exécution passe à 33 sec :

 
Code :
  1. SELECT user_level, user_color, user_group_id, user_flag, username, user_id AS USERID,
  2. user_viewemail, user_posts, user_regdate, user_from, user_website, user_email, user_icq,
  3. user_aim, user_yim, user_msnm, user_avatar, user_avatar_type, user_allowavatar, user_allow_viewonline,
  4. user_session_time, user_points,
  5. ( SELECT COUNT(topic_id)
  6. FROM table_topics
  7. WHERE topic_poster = USERID
  8. GROUP BY topic_poster ) AS count_topic_nb
  9. FROM table_users
  10. WHERE user_id <> -1
  11. ORDER BY count_topic_nb ASC
  12. LIMIT 0,30


Message édité par mkex64 le 14-03-2008 à 16:03:55

---------------
http://www.unicornis.org/
Reply

Marsh Posté le 14-03-2008 à 16:18:04    

Essaye de le faire en deux temps :

  • Créer une table temporaire avec le topic_id et le count topic_id
  • Dans ton SQL, faire le lien avec cette table...


---------------
Feedback : http://forum.hardware.fr/hfr/Achat [...] 2666_1.htm
Reply

Marsh Posté le 14-03-2008 à 16:18:04   

Reply

Marsh Posté le 15-03-2008 à 12:01:57    

Bonjour,
 
Ok je vais essayer de faire ça.  
 
Merci.


---------------
http://www.unicornis.org/
Reply

Marsh Posté le 15-03-2008 à 16:23:03    

Bon voilà j'ai testé la table temporaire.
Les résultats sont OK mais le temps d'exécution est d'environ de 3 à  5 secondes.
 
 
J'ai fait ça comme requêtes :
 

Code :
  1. CREATE TEMPORARY TABLE tmp_count_t (
  2. count_topic_nb mediumint(8) UNSIGNED NOT NULL,
  3. topic_poster mediumint(8) DEFAULT '0' NOT NULL
  4. )


 
 

Code :
  1. INSERT INTO tmp_count_t (count_topic_nb, topic_poster)
  2. SELECT COUNT(*), topic_poster
  3. FROM table_topics
  4. GROUP BY topic_poster


 

Code :
  1. SELECT u.user_level, u.user_color, u.user_group_id, u.user_flag,
  2. u.username, u.user_id, u.user_viewemail, u.user_posts, u.user_regdate,
  3. u.user_from, u.user_website, u.user_email, u.user_icq, u.user_aim,
  4. u.user_yim, u.user_msnm, u.user_avatar, u.user_avatar_type,
  5. u.user_allowavatar, u.user_allow_viewonline, u.user_session_time,
  6. u.user_points, t.topic_poster, t.count_topic_nb
  7. FROM phpbb_users u
  8. LEFT JOIN tmp_count_t t ON t.topic_poster = u.user_id
  9. WHERE u.user_id <> -1
  10. ORDER BY u.user_regdate ASC
  11. LIMIT 0, 30


Message édité par mkex64 le 15-03-2008 à 17:17:49

---------------
http://www.unicornis.org/
Reply

Marsh Posté le 15-03-2008 à 17:45:07    

Si tu veux gagner un peu de temps, tu peux associer une date de rafraichissement pour que le calcul ne se lance que si cela fait plus de X temps que la table n'a pas été recrée...


---------------
Feedback : http://forum.hardware.fr/hfr/Achat [...] 2666_1.htm
Reply

Marsh Posté le 16-03-2008 à 07:00:59    

Merci,
 
Finalement j'ai fait plus simple...
 
J'ai rajouté une colonne dans la table_users qui liste le nombre de topics pour chaque user.
 
J'ai intégré les données dans la table via un petit script qui lance des requêtes avec une boucle et tout ça...
 
Et j'ai rajouté dans les codes le fait que ça incrémente le nombre de topics d'un user à chaque fois que cet user en créé un.
 
 
Et ça marche à la perfection.
 
 
Merci à vous.


---------------
http://www.unicornis.org/
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed