интересный алгоритм голосования

#1 24 февраля 2010 в 21:37
Разбираясь опять же с индексами, наткнулся на запросы формирующиеся при голосовании за пост блога. Количество запросов меня удивило. Оно (количество запросов) пропорционально количеству пользователей. Т.е. если пользователей к примеру 2000, то запросов будет порядка 2000, плюс количество запросов равное количеству клубов!
Собственно поэтому на этом сайте при голосовании за пост или за комент сайт начинает сильно тупить.
Чтобы не быть голословным, вот функция (выдержка из файла lib_karma.php папки core)
  1. function setUsersRating(){
  2. $inDB = cmsDatabase::getInstance();
  3. $sql = "SELECT id FROM cms_users WHERE is_locked = 0 AND is_deleted = 0";
  4. $res = $inDB->query($sql);
  5.  
  6. while($user = $inDB->fetch_assoc($res)){
  7. $sql = "SELECT SUM( r.points ) AS rating
  8. FROM cms_ratings r
  9. LEFT JOIN cms_content c ON r.item_id = c.id AND r.target = 'content'
  10. LEFT JOIN cms_photo_files f ON r.item_id = f.id AND r.target = 'photo'
  11. LEFT JOIN cms_blog_posts p ON r.item_id = p.id AND r.target = 'blogpost'
  12. WHERE c.user_id = ".$user['id']." OR f.user_id = ".$user['id']." OR p.user_id = ".$user['id'];
  13. $rs = $inDB->query($sql);
  14. if ($inDB->num_rows($rs)){
  15. $data = $inDB->fetch_assoc($rs);
  16. $rating = $data['rating'] * 5;
  17. } else {
  18. $rating = 0;
  19. }
  20.  
  21. $sql = "SELECT SUM(v.vote) AS votes
  22. FROM cms_comments_votes v
  23. LEFT JOIN cms_comments c ON v.comment_id = c.id
  24. WHERE c.user_id = ".$user['id']." AND v.comment_type = 'com'";
  25. $rs = $inDB->query($sql);
  26. if ($inDB->num_rows($rs)){
  27. $data = $inDB->fetch_assoc($rs);
  28. $rating += $data['votes'] * 2;
  29. }
  30.  
  31. $sql = "UPDATE cms_users SET rating = $rating WHERE id = ".$user['id'];
  32. $inDB->query($sql);
  33. }
  34. }
  35.  

А также не понятно зачем при голосовании за пост в обычном блоге вызывается функция setClubsRating(); — это файл karma.php папки /core/ajax.

Собственно суть моего поста:

У кого есть знания прошу помочь мне, да и в общем то всем, в пересмотрении указанного алгоритма.
Я конечно сам тоже попробую, но как говорится одна голова хорошо, а целое сообщество лучше.
#2 24 февраля 2010 в 23:23
хз… что придумать, но однозначно надо что-то с этим делать… голосование за что либо очень накладная операция получается.
Я только одного не пойму, зачем ВСЕХ пользователей перебирать в запросе?
Не проще передать функции id пользователя и все?

Может я конечно не очень понял...
#3 24 февраля 2010 в 23:46
Ну я так себе и представлял. так же переписал для юзеров, но почему-то в таблице цмс_юзер рейтинг не прибавлялся(((

Вопрос: а откуда взять переменную $club_id?

В общем утро вечера…
#4 1 марта 2010 в 12:01
вот временное решение проблемы до выхода 1.5.4:

1. Открыть файл /core/lib_karma.php
2. Найти функцию setUsersRating
3. Заменить ее полностью:

  1.  
  2. function setUsersRating(){
  3.  
  4. $inCore = cmsCore::getInstance();
  5. $inDB = cmsDatabase::getInstance();
  6.  
  7. $target = $inCore->request('target', 'str', '');
  8. $item_id = $inCore->request('item_id', 'int', 0);
  9. $opt = $inCore->request('opt', 'str', 'plus');
  10.  
  11. $comment_id = $inCore->request('comment_id', 'int', 0);
  12. $comment_vote = $inCore->request('vote', 'int', 1);
  13.  
  14. if ($comment_id) { $target = 'comment'; $item_id = $comment_id; }
  15.  
  16. $table = '';
  17.  
  18. switch($target){
  19. case 'blogpost': $table = 'cms_blog_posts'; break;
  20. case 'content': $table = 'cms_content'; break;
  21. case 'comment': $table = 'cms_comments'; break;
  22. }
  23.  
  24. if (!$table) { return false; }
  25.  
  26. $author_sql = "SELECT u.id as id
  27. FROM cms_users u, {$table} t
  28. WHERE t.id = {$item_id} AND t.user_id = u.id
  29. LIMIT 1";
  30.  
  31. $author_res = $inDB->query($author_sql);
  32.  
  33. if (!$inDB->num_rows($author_res)) { return false; }
  34.  
  35. $author = $inDB->fetch_assoc($author_res);
  36.  
  37. if ($comment_id){
  38. $inc = ($comment_vote>0 ? ('+'.$comment_vote*2) : ($comment_vote*2));
  39. } else {
  40. $inc = ($opt=='plus' ? '+ 5' : '- 5');
  41. }
  42.  
  43. $inDB->query("UPDATE cms_users SET rating = rating {$inc} WHERE id = {$author['id']}");
  44.  
  45. }
  46.  
на этом сайте исправлено, сейчас посты и комменты оцениваются очень быстро, сайт больше не тупит
#5 1 марта 2010 в 12:15
Спасибо, дядя Админ! v
#6 1 марта 2010 в 12:22
Админ, спасибо. Не трудно будет выложить листинг архивом, чтобы не таскать через буфер обмена? Заранее чмок)))
#7 1 марта 2010 в 12:32
feba7, наводим мышку на код, жмем кнопку "Исходный код" справа, в открывшемся окне "Сохранить как..."
#8 1 марта 2010 в 13:15
Администратор, спасибо, теперь увидела, когда растолковали)))!
#9 1 марта 2010 в 15:10
Администратор, спасибо.
Вы не можете отвечать в этой теме.
Войдите или зарегистрируйтесь, чтобы писать на форуме.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.