Ris

Ris

+657
Репутация
3771
Рейтинг
#1 Долгие запросы MySql 5 марта 2018 в 08:55
@ivanpolyakov,
В robots.txt Crawl-delay: 100
#2 Долгие запросы MySql 3 марта 2018 в 23:42
Продолжение мерлезонского балета.
Сегодня на яндексе проснулся какой-то злой дух и начал сканировать комментарии семилетней давности. И всё, сайт лёг.
В логе долгих запросов 100500 записей типа:
  1.  
  2. # Query_time: 51.697987 Lock_time: 0.000473 Rows_sent: 20 Rows_examined: 1843896
  3. SET TIMESTAMP=1520069949;
  4. SELECT i.*, r.score AS is_rated, u.nickname AS user_nickname, u.avatar AS user_avatar
  5. FROM cms_comments i
  6. LEFT JOIN cms_users AS u ON u.id = i.user_id
  7. LEFT JOIN cms_comments_rating AS r ON r.comment_id = i.id AND r.user_id='0'
  8. WHERE (i.is_private = '0') AND (i.is_deleted IS NULL) AND (i.is_approved = '1')
  9. ORDER BY i.date_pub DESC
  10. LIMIT 922000, 20;
Полез в список комментариев, а там на последних страницах выборка по минуте:
Ничего умнее не придумал, как доработать \system\controllers\comments\frontend.php, по этой инструкции habrahabr.ru/post/217521/ таким образом:
  1. // Получаем количество и список записей
  2. $total = !empty($this->count) ? $this->count : $this->model->getCommentsCount();
  3. $this->model->limit($perpage)->join .= ("JOIN (SELECT id FROM cms_comments ORDER BY id DESC LIMIT ".($page-1)*$perpage.", $perpage ) c ON c.id = i.id ");
  4. $items = $this->model->getComments();
Сразу стало всё гораздо веселее:
  1. /system\controllers\comments\model.php => 296 => modelComments->getComments()
  2. SELECT i.*, r.score AS is_rated, u.nickname AS user_nickname, u.avatar AS user_avatar
  3. FROM cms_comments i
  4. JOIN (SELECT id FROM cms_comments ORDER BY id DESC LIMIT 958740, 20 ) c ON c.id = i.id LEFT JOIN cms_users AS u ON u.id = i.user_id
  5. LEFT JOIN cms_comments_rating AS r ON r.comment_id = i.id AND r.user_id='86'
  6. WHERE (i.is_deleted IS NULL) AND (i.is_approved = '1')
  7. ORDER BY i.date_pub DESC
  8. LIMIT 20
  9. Время выполнения 0.22628 секунд
но пропали списки комментариев у пользователя в профиле.
Сил экспериментировать больше не было и поэтому ограничил нововведение списком всех комментариев:
  1. // Получаем количество и список записей
  2. $total = !empty($this->count) ? $this->count : $this->model->getCommentsCount();
  3. if (strpos($_SERVER['REQUEST_URI'], 'comments/all')) {$this->model->limit($perpage)->join .= ("JOIN (SELECT id FROM cms_comments ORDER BY id DESC LIMIT ".($page-1)*$perpage.", $perpage ) c ON c.id = i.id ");}
  4. $items = $this->model->getComments();
Костыль, конечно, но вроде работает:
Может кто может подсказать более человеческий способ борьбы с limit offset на больших таблицах?
#3 Вторая ветка - разбираюсь 3 марта 2018 в 14:13
Jestik,
Или лучше на главной странице выводить комментарии из всех типов контента?
Тогда так:
  1. <?php
  2.  
  3. class onContentCommentsListWidgetFilter extends cmsAction {
  4.  
  5. public function run($model){
  6.  
  7. /*Если не главная страница*/
  8. if ($_SERVER['REQUEST_URI'] != '/'){
  9.  
  10. /* Получаем все типы контента*/
  11. $ctypes = implode('|', $this->model->getContentTypesNames());
  12.  
  13. /* Получаем текущий тип контента */
  14. preg_match('/('.$ctypes.')/', $_SERVER['REQUEST_URI'], $matches);
  15.  
  16. /* Если тип контента опознан - фильтруем комментарии только из него */
  17. if (!empty($matches)){$model->filterEqual('target_subject', $matches[0]);}
  18.  
  19. }
  20.  
  21. // Отправляем данные обратно в компонент
  22. return $model;
  23.  
  24. }
  25.  
  26. }
#4 Поле 3 марта 2018 в 13:59

на практике как это сделать?

@gopik
Подумать надо. Погодите немного.
#5 Поле 3 марта 2018 в 10:16

Если это не сложно покажи на пальцах как это сделать? я не гуру в этом.

@gopik
Это я так… теорию излагаю. В реальности от этого HTTP_REFERER толку мало.
Ведь человек не сразу после входа на сайт бросается регистрироваться, а регистрировать все адреса, откуда какие гости приходят — база распухнет и лопнет.
В общем если нужно посмотреть, откуда приходят люди на сайт, есть замечательный инструмент у яндекса:
metrika.yandex.ru
Там нужно зарегистрировать свой сайт и тогда можно будет посмотреть, что за люди приходят, откуда, возраст, пол, размер бюстгальтера…
#6 Вторая ветка - разбираюсь 3 марта 2018 в 00:21

Та нужный это функционал. Я бы не отказался

Jestik
Вот это в хуки контента:
  1. <?php
  2.  
  3. class onContentCommentsListWidgetFilter extends cmsAction {
  4.  
  5. public function run($model){
  6.  
  7.  
  8. $ctypes = implode('|', $this->model->getContentTypesNames()); /* Получаем все типы контента*/
  9.  
  10. preg_match('/('.$ctypes.')/', $_SERVER['REQUEST_URI'], $matches); /* Получаем текущий тип контента */
  11.  
  12. $model->filterEqual('target_subject', $matches ? $matches[0] : str_replace('content:', '', $this->cms_config->frontpage));
  13.  
  14. // Отправляем данные обратно в компонент
  15. return $model;
  16.  
  17. }
  18.  
  19. }
#7 Поле 3 марта 2018 в 00:04
@gopik,
Да ладно!
getenv("HTTP_REFERER") — выдает адрес с которого пришел на страницу юзер, который эту страницу просматривает. То есть он покажет Вам, откуда Вы пришли на страницу. laugh
Осталось это только куда-нибудь сохранить (в базу данных) и потом оттуда доставать и показывать, где нужно.
#8 Поле 2 марта 2018 в 23:06
#9 Поле 2 марта 2018 в 22:39

Подскажите как создать поле в профиле в котором будет отображаться ссылка от куда пришел пользователь.

@gopik
Создать поле либо строка, либо ссылка. И всё, поле создано! laugh
А теперь самый интересный вопрос. А как Вы собираетесь узнавать, откуда пришел пользователь?
#10 [ЕСТЬ РЕШЕНИЕ] Фильтрация по двум столбцам из базы 2 марта 2018 в 22:35

Да сработало но перед этим стояло это $this->filterEqual('tournament_id', $tournament_id); но теперь он не работает.

Нико
Ну а кто знал, что там перед этим? smile
Тогда так:
$this->filterStart()->filterEqual('team_one, $id)->filterOr()->filterEqual('team_two, $id)->filterEnd();
#11 Вторая ветка - разбираюсь 2 марта 2018 в 21:46

Например я в новостях, и справа виджет комментарии, зачем мне там видеть комментарии со всего сайта, я хочу видеть комментарии именно с этого.

@infiniti
Вы собираетесь все время находиться на сайте в одиночестве? Или все же предполагается, что будут еще пользователи, которые по ссылкам на комментарии в виджете будут переходить на другие страницы сайта?

Но это лирическое отступление.
Я правильно понял, что на странице какого-либо типа контента в виджете должны быть комментарии только из этого типа контента?
Тогда можно сделать хук comments_list_widget_filter, который будет отфильтровывать комментарии в виджете только из этого типа контента.
#12 Не отображается меню панели управления в версиях 2.8, 2.9 2 марта 2018 в 20:02
@Random,
Зажмите CTRL и крутите колесо мыши.
#13 Вторая ветка - разбираюсь 2 марта 2018 в 19:47
@infiniti,
А другие виджеты, где будут комментарии из других типов контента тоже нужны? Или выводить только из одного типа?
#14 [ЕСТЬ РЕШЕНИЕ] Перестала работать задача в Cron 2 марта 2018 в 19:29
ParadoX,
Ищите ответ в логах ошибок на сервере.
#15 [ЕСТЬ РЕШЕНИЕ] Фильтрация по двум столбцам из базы 2 марта 2018 в 14:11
$this->filterEqual('team_one, $id)->filterOr()->filterEqual('team_two, $id);
🍪Мы используем файлы cookie для работы сайта. Читать подробнее.