rub a écrit:
Code:
'[...]AND c.validation_date > \''.$start.'\'[...]'
Pourquoi ne pas remplacer les ' externes par des " pour éviter d'avoir à échapper les simples quotes de la requete?
Question subsidiaire:
est-il mieux (?) de faire 'xx '.$toto.' yy' ou "xx $toto yy"? BIen sûr, dans le cas où les xx et yy ne contienent pas de texte interprétable?
PS: je suis de retour de 15j de vacances :-p
rub a écrit:
VDigital a écrit:
:idea:
J'ai peut être une autre solution à vous proposer, dès que j'ai un peu de temps pour y réfléchir, je vous ferai une proposition d'une logique différente.On est impatient ;-)
L'idée ne murit pas assez vite, mais je n'oublie pas, tu ne l'auras pas pour la 1.6, j'ai même peur de mettre avancé et d'être dans une impasse.
Effectivement, je vais en tenir compte...
rub, si tu modifies les fonctions ainsi, on ne pourra plus avoir les détails qui sont au programmes de futures améliorations de la notification, comme la liste des noms des catégories mises à jour. En tout cas si tu veux modifier en ce sens, il faut renommer la fonction... en nb_new_comments.
z0rglub a écrit:
(désolé rub, ce post risque de briser quelques espoirs)
Non, non, je me doutais un peu des réponses mais j'avais envie d'en discuter...
z0rglub a écrit:
Les requêtes imbriquées, c'est du MySQL 4.1, donc c'est non. Que MySQL 4.0 devienne éventuellement le prérequis à partir de la branche 1.6 de PhpWebGallery, pourquoi pas (le code actuel ne l'impose pas il me semble, mais je ne peut plus vérifier étant moi-même passé en 4.0 depuis plus de 6 mois).
Je m'en doutais un peu... déjà que mes requêtes imbriqués dans le where ne passaient pas, je me doutais que celles imbriquées dans le from, ne le serais pas aussi...
Oui pourquoi MySQL 4.0 comme pré-requis, mais si c'est pas nécessaire, on reste bien sur à la version 3.0...
Par contre, je suis triste de ne pas pourvoir faire de réquêtes imbriquées, je trouve ca tres pratique...
z0rglub a écrit:
Remplacer la concaténation des identifiants de catégories inaccessibles stockée en cache utilisateur par une table associant {user_id,category_id}, c'est non. Car un NOT IN (...) est bien plus rapide qu'une jointure. Pour information, cette table que tu proposes existait en des temps immémoriaux (en branche 1.3) et elle a été très avantageusement remplacé par user_cache.forbidden_categories, sans conteste.
Ce qui est vrai si on fait l'interrogation pour un seul user (c'est peut-être plus rapide mais c'est plus qussi simple à écrire aussi)...
Pour n utilisateurs d'un coup, ce n'est pas le cas (mais sauf NBM, nous n'avons pas le cas)...
Par contre, je suis étonné que la jointure soit plus longue que le not in... (ca doit dépendre du nombre de forbidden, ect...)...
z0rglub a écrit:
Je rappelle que nous devons concentrer nos efforts d'amélioration des performances sur category.php/index.php et picture.php, les autres pages ne doivent pas être trop lentes, mais ce n'est pas la priorité.
Discuter sur l'optimisation d'autres pages peut aussi aider à optimiser les 2 pages principales ;-)
z0rglub a écrit:
Ne pas prendre en compte les catégories verrouillées ??? Bien sûr que si, ce serait une erreur fonctionnelle que de ne pas le faire et un bug à corriger en branche 1.6.
Ca serait une erreur fonctionnelle dans les fonctionnalités classiques mais pas pour la notification (RSS ou mail).
Par exemple, si on a:
o création d'une nouvelle catégorie C
o cette catégorie C est verrouillée
o demande de notification RSS ou mail
o la nouvelle catégorie C ne sera pas comptée dans la notification car elle est verrouillée
o dévérrouillage de la catégorie C
o demande de notification RSS ou mail
o la nouvelle catégorie C ne sera pas comptée dans la notification car la date de demande sera trop récente par rapport à la date de la catégorie
C'est pour ca que la notion de verrouillage ne devrait pas être faite pour la notification.
Pour moi, le verrouillage, c'est empêcher temporaire l'utilisateur de voir une catégorie car elle est en cours de mise à jour. Mais, on peut quand même notifier qu'elle est présente.
Pour me contredire, si la catégorie est verrouillée, c'est que les images contenues se sont pas figés (pas assez ou trop d'images) et par conséquent, il ne faut pas les notifier...
Bref, tout ca pour dire, pour la notification (rss/mail) ce n'est peut-être pas une erreur fonctionnelle ni un bug, tout dépend par ce qu'on entend par verrouillage.
z0rglub a écrit:
Les requêtes que tu montres supposent que tous les utilisateurs ont été notifiés précédemment à la même date. C'est un raccourci bien trop facile à mon avis. Tu peux très bien vouloir à un moment donné notifié 35 utilisateurs dont la date de dernière notification par mail est différente pour chacun. Dans ce cas là, t'es bon pour pour faire 35 requêtes...
Oui, oui, je savais... Les notifications par mails étant faire par paquets, les querys auraient été faites par paquets suivant les dates... Donc pour 35 utilisateurs entr 1 et 35 requêtes suivant les dates.
z0rglub a écrit:
Tu remarques évidemment que ces problèmes ne se posent pas avec la notification tirée (flux RSS) par rapport à la notification poussée (mail) car on peut espèrer que chaque utilisateur interroge son flux en décalé.
Bien sur... NBM est la 1er (?) partie qui utilise les propriétés de chaque user pour construire quelque chose... D'habitude, c'est soit de la gestion de users, soit la "construction" de quelque chose pour un seul user...
z0rglub a écrit:
Mon avis est que la seule solution raisonnable est de limiter le nombre d'utilisateurs notifié à la fois.
Ok, c'est vendu... ca sera limité par un paramètre.
(De touté façon, mais si j'avais utilisé les requêtes imbriquées, j'aurais mis un paramètre car le sendmail peut aussi avoir des temps de réponses non correctes.)
J'ai aussi modifié un peu les requêtes pour faire le count dans la query et c'est un peu plus rapide aussi
function new_comments($start, $end) { global $user; $query = ' SELECT DISTINCT c.id AS comment_id FROM '.COMMENTS_TABLE.' AS c , '.IMAGE_CATEGORY_TABLE.' AS ic WHERE c.image_id = ic.image_id AND c.validation_date > \''.$start.'\' AND c.validation_date <= \''.$end.'\' AND category_id NOT IN ('.$user['forbidden_categories'].') ;'; return array_from_query($query, 'comment_id'); } $res := count(new_comments(...,...));
est remplacé par
function new_comments($start, $end) { global $user; $query = ' SELECT count(DISTINCT c.id) FROM '.COMMENTS_TABLE.' AS c , '.IMAGE_CATEGORY_TABLE.' AS ic WHERE c.image_id = ic.image_id AND c.validation_date > \''.$start.'\' AND c.validation_date <= \''.$end.'\' AND category_id NOT IN ('.$user['forbidden_categories'].') ;'; list($count) = mysql_fetch_array(pwg_query($query)); return $count; } $res := new_comments(...,...);
Je verrais aussi s'il n'y a pas encore de petites modifications à faire pour optimiser le tout...
VDigital a écrit:
:idea:
J'ai peut être une autre solution à vous proposer, dès que j'ai un peu de temps pour y réfléchir, je vous ferai une proposition d'une logique différente.
On est impatient ;-)
z0rglub a écrit:
Les requêtes que tu montres supposent que tous les utilisateurs ont été notifiés précédemment à la même date. C'est un raccourci bien trop facile à mon avis. Tu peux très bien vouloir à un moment donné notifié 35 utilisateurs dont la date de dernière notification par mail est différente pour chacun. Dans ce cas là, t'es bon pour pour faire 35 requêtes...
Je suis d'accord avec toi sur tous les points.
:idea:
J'ai peut être une autre solution à vous proposer, dès que j'ai un peu de temps pour y réfléchir, je vous ferai une proposition d'une logique différente.
8-)
(désolé rub, ce post risque de briser quelques espoirs)
Les requêtes imbriquées, c'est du MySQL 4.1, donc c'est non. Que MySQL 4.0 devienne éventuellement le prérequis à partir de la branche 1.6 de PhpWebGallery, pourquoi pas (le code actuel ne l'impose pas il me semble, mais je ne peut plus vérifier étant moi-même passé en 4.0 depuis plus de 6 mois).
Remplacer la concaténation des identifiants de catégories inaccessibles stockée en cache utilisateur par une table associant {user_id,category_id}, c'est non. Car un NOT IN (...) est bien plus rapide qu'une jointure. Pour information, cette table que tu proposes existait en des temps immémoriaux (en branche 1.3) et elle a été très avantageusement remplacé par user_cache.forbidden_categories, sans conteste. Je rappelle que nous devons concentrer nos efforts d'amélioration des performances sur category.php/index.php et picture.php, les autres pages ne doivent pas être trop lentes, mais ce n'est pas la priorité.
Ne pas prendre en compte les catégories verrouillées ??? Bien sûr que si, ce serait une erreur fonctionnelle que de ne pas le faire et un bug à corriger en branche 1.6.
Les requêtes que tu montres supposent que tous les utilisateurs ont été notifiés précédemment à la même date. C'est un raccourci bien trop facile à mon avis. Tu peux très bien vouloir à un moment donné notifié 35 utilisateurs dont la date de dernière notification par mail est différente pour chacun. Dans ce cas là, t'es bon pour pour faire 35 requêtes...
Tu remarques évidemment que ces problèmes ne se posent pas avec la notification tirée (flux RSS) par rapport à la notification poussée (mail) car on peut espèrer que chaque utilisateur interroge son flux en décalé.
Mon avis est que la seule solution raisonnable est de limiter le nombre d'utilisateurs notifié à la fois.
rvelices a écrit:
Malheureusement je n'ai pas MySql 3 pour confirmer si ca marche ...
Dommage...
rvelices a écrit:
Mais je pense que les perfs ne seront pas si mauvaises que ca meme si tu fais plusieurs requetes par utilisateur... (et puis meme si ca prend 5 secondes, on ne va pas faire ca tous les jours)
Bha, en fait, je teste avec 60 utilisateurs et ca fait à peu près 700 requêtes et on arrive facile à 24 secondes... J'ai modifié les requêtes de la fonction news pour mettre le count dans le sql et on est passé à 18 s... Avec les tables optimisées, la nouvelle requête est executée en moins d'une seconde, ce qui ferait au total un temps < à 5 secondes, je pense... sans compter l'envoi des mail par le smtp qui être long aussi...
Bref, le but est d'éviter d'arriver au time-out de la page php.. je vais aussi limiter l'envoi à un nombre fini d'utilisateur à chaque passe (comme pour les miniatures par exemple...)
Sinon pour l'optimisation des tables, elle n'est pas à faire à chaque fois mais il faudrait plus créer un lien dans maintenance et le faire aussi à chaque upgrade de pwg...
Malheureusement je n'ai pas MySql 3 pour confirmer si ca marche ...
Mais je pense que les perfs ne seront pas si mauvaises que ca meme si tu fais plusieurs requetes par utilisateur... (et puis meme si ca prend 5 secondes, on ne va pas faire ca tous les jours)
En fait, pour résumer, je voudrais remplacer :
les requêtes, executés pour CHAQUE utlisateur, du type suivant
SELECT DISTINCT c.id AS comment_id FROM phpwebgallery_comments AS c , phpwebgallery_image_category AS ic WHERE c.image_id = ic.image_id AND c.validation_date > '' AND c.validation_date <= '2006-03-27 23:31:33' AND category_id NOT IN ( 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,28,29, 30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55, 56,57,58,59,60,61,62,63,65,67,69,71,72,74,76,78,80,82,84,87,89,91,92,95,96,97, 98,101,102,104,106,107,109,110,112,114,116,118,119,121,123,125,126,128,130,131, 133,139,141,142,145,147,148,149,153,155,156,158,162,163,165,167,169,171,172, 173,174,177,178,181,182,185,186,187,188,189,190,191,192,193,199,218,219,220, 221,222,223,224,225,226,228,229,230,231,232,233,276,277,278,279,280,281,282, 283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301, 302,303,304,305,306,307,308,309,310,311,312,313,314,325,327,334,344,349,359, 360,361,362,366,367,370,371,372,373,374,378,379,380,381,382,383,384,385,386, 387,388,389,390,391,392,393,398,401,402,406,409,411,413,416,418,419,420,423, 424,427,428,429,433,434,-1 );
par cette requête executée UNE seule fois pour l'ensemble des utilisateurs
SELECT user_id, count(DISTINCT c.id) FROM phpwebgallery_comments AS c , phpwebgallery_image_category AS ic , ( select user_id, cat_id from phpwebgallery_group_access ga, phpwebgallery_user_group ug where ga.group_id = ug.group_id and ug.user_id in (1,3,5,6,7) union select user_id, cat_id from phpwebgallery_user_access where user_id in (1,3,5,6,7,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45) union select u.id user_id, c.id cat_id from phpwebgallery_categories c, phpwebgallery_users u where c.status = 'public' and u.id in (1,3,5,6,7,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45) ) authorized_cat WHERE c.image_id = ic.image_id AND c.validation_date > '' AND c.validation_date <= '2006-03-27 23:31:33' AND authorized_cat.cat_id = category_id GROUP BY user_id ;
Par contre, pour que cette requete fonctionne bien, il faut que les tables soit optimisée. J'ajouterais une optimisation des tables à chaque notification. Qu'en pensez-vous?
Par contre, je ne sais pas si cette requête est compatible avec la version minimal de myql supportée par pwg. Pierrick ou quelqu'un d'autre pourrait me confirmer assez vite, si c'est OK avec la version miminal de mysql?
Dans la version [Subversion] r1105 de la BSF, au niveau de la notification par mail, pour récupérer le nombre de nouveautés des utilisateurs, j'exécute pour CHAQUE USER la fonction news de l'unité functions_notification.inc.php, qui elle-même éxecute de NOMBREUSES REQUêTES.
Donc, plus il y a de users, plus il y a de requêtes à faire.
Je suis entrain d'optimiser le traitement pour que quelque soit le nombre de users, le temps d'execution soit à peu près le même et pour ca, je voudrais executer les requêtes de la functions en 1 SEULE FOIS pour l'ensemble des UTILISATEURS. Le petit hic, c'est l'utilisation de $user['forbidden_categories'] qui ne me permet pas de faire les requêtes sur plusieurs utlisateus en même temps.
Pour ne plus utiliser $user['forbidden_categories'], plusieurs possibilités me viennet à l'esprit:
o (Solution 1) tout d'abord, transposer $user['forbidden_categories'] dans une nouvelle table (user_id, cat_id) et faire les jointure left + conditions pour faire pareil que $user['forbidden_categories']
> Cette transposition peut être faire dans un table temporaire
> ou dans une table fixe qui sera alimenté en même temps que le champs forbidden_categories de la tabcle cache
Si on adopte cette table, faut-il ou non modifier toutes les requêtes et supprimer $user['forbidden_categories']
o (Solution 2) Mais après reflexion, je me suis dit qu'il fallait mieux ne pas utliser de nouvelles tables mais faire les jointures directement avec les tables #phpwebgallery_group_access, #phpwebgallery_user_access, #phpwebgallery_categories (status = public) (Utiliser les 3 tables avec un UNION). (Par contre, contrairement à la génération de $user['forbidden_categories'], je ne gérerais pas les catégories verrouillées car ca complique encore la requête et c'est par necessaire pour compter les nouveaux éléments)
Je vais partir sur la solution de reprendre les tables existantes (Solution 2).
J'evoquais plusieurs possibilités car j'ai lu que certains voulaientt des changements concernant la gestion du cache, donc si la solution 1 était une de celles prévus, c'est peut-être le moment pour commencer.