Медленная работа Tickets
Здравствуйте.
На сайте используется Tickets.
Сайт, что-то типа блога. Имеется одна категория в которую пишутся все тикеты.
Количество тикетов уже 311000.
Основной запрос на выборку 10 тикетов в категории (разделе) очень медленно выполняется. Более 60 секунд.
Кто-нибудь использовал Tickets в таких же условиях? Такая же скорость?
На сайте используется Tickets.
Сайт, что-то типа блога. Имеется одна категория в которую пишутся все тикеты.
Количество тикетов уже 311000.
Основной запрос на выборку 10 тикетов в категории (разделе) очень медленно выполняется. Более 60 секунд.
Кто-нибудь использовал Tickets в таких же условиях? Такая же скорость?
Комментарии: 19
311 000 тикетов? Фигасе.
Это скорее всего связано с тем, что там криво написана выборка по parents c depth — по карте ресурсов всегда получаются id потомков и включаются в запрос. А карта у тебя ооочень большая.
В MS2 уже поправил, попробуй изменить getTickets так:
Ну а после этого вызывай getTickets с параметром &depth=0. Должно помочь.
Это скорее всего связано с тем, что там криво написана выборка по parents c depth — по карте ресурсов всегда получаются id потомков и включаются в запрос. А карта у тебя ооочень большая.
В MS2 уже поправил, попробуй изменить getTickets так:
else {
// Filter by parents
if (empty($parents) && $parents != '0') {$parents = $modx->resource->id;}
if (!empty($parents) && $parents > 0){
$pids = array_map('trim', explode(',', $parents));
$parents = $pids;
if (!empty($depth) && $depth > 0) {
foreach ($pids as $v) {
if (!is_numeric($v)) {continue;}
$parents = array_merge($parents, $modx->getChildIds($v, $depth));
}
}
if (!empty($parents)) {
$where['parent:IN'] = $parents;
}
}
}
Ну а после этого вызывай getTickets с параметром &depth=0. Должно помочь.
а когда выйдет обнова в репозитории? ms2 с этой заплаткой
Как запущу бета-тест нашего репозитория — новая версия MS2 будет там.
Надеюсь на завтра.
Надеюсь на завтра.
Василий, внес твои изменения — все по прежнему.
Начал копать дальше. Выполнил запрос из mysql-редактора.
Всплыло вот что. Проблема в самом mysql — долго выполняется сброс данных и их сортировка.
EXPLAIN запроса
Профайлер запроса
Есть у кого-нибудь какие либо мысли?
Начал копать дальше. Выполнил запрос из mysql-редактора.
Всплыло вот что. Проблема в самом mysql — долго выполняется сброс данных и их сортировка.
EXPLAIN запроса
Профайлер запроса
Есть у кого-нибудь какие либо мысли?
Мысль тут только одна: расставить дополнительных индексов (например, на deleted индекса нет) и написать свой собственный сниппет для вывода тикетов.
Убрать там все ненужные плюшки, лишние джоины и, возможно, разбить на несколько запросов, например отдельно считать кол-во комментов у тикета, или не считать вовсе.
Честно говоря, я вообще удивлен и очень рад, что 300 тысяч тикетов в принципе работают.
Убрать там все ненужные плюшки, лишние джоины и, возможно, разбить на несколько запросов, например отдельно считать кол-во комментов у тикета, или не считать вовсе.
Честно говоря, я вообще удивлен и очень рад, что 300 тысяч тикетов в принципе работают.
Скорее всего так и буду делать.
Покажи весь запрос
SELECT SQL_CALC_FOUND_ROWS
`Ticket`.`id`, `Ticket`.`type`, `Ticket`.`contentType`, `Ticket`.`pagetitle`, `Ticket`.`longtitle`, `Ticket`.`description`, `Ticket`.`alias`, `Ticket`.`link_attributes`, `Ticket`.`published`, `Ticket`.`pub_date`, `Ticket`.`unpub_date`, `Ticket`.`parent`, `Ticket`.`isfolder`, `Ticket`.`introtext`, `Ticket`.`richtext`, `Ticket`.`template`, `Ticket`.`menuindex`, `Ticket`.`searchable`, `Ticket`.`cacheable`, `Ticket`.`createdby`, `Ticket`.`createdon`, `Ticket`.`editedby`, `Ticket`.`editedon`, `Ticket`.`deleted`, `Ticket`.`deletedon`, `Ticket`.`deletedby`, `Ticket`.`publishedon`, `Ticket`.`publishedby`, `Ticket`.`menutitle`, `Ticket`.`donthit`, `Ticket`.`privateweb`, `Ticket`.`privatemgr`, `Ticket`.`content_dispo`, `Ticket`.`hidemenu`, `Ticket`.`class_key`, `Ticket`.`context_key`, `Ticket`.`content_type`, `Ticket`.`uri`, `Ticket`.`uri_override`, `Ticket`.`hide_children_in_tree`, `Ticket`.`show_in_tree`, `Ticket`.`properties`,
`Section`.`id` AS `section.id`, `Section`.`type` AS `section.type`, `Section`.`contentType` AS `section.contentType`, `Section`.`pagetitle` AS `section.pagetitle`, `Section`.`longtitle` AS `section.longtitle`, `Section`.`description` AS `section.description`, `Section`.`alias` AS `section.alias`, `Section`.`link_attributes` AS `section.link_attributes`, `Section`.`published` AS `section.published`, `Section`.`pub_date` AS `section.pub_date`, `Section`.`unpub_date` AS `section.unpub_date`, `Section`.`parent` AS `section.parent`, `Section`.`isfolder` AS `section.isfolder`, `Section`.`introtext` AS `section.introtext`, `Section`.`richtext` AS `section.richtext`, `Section`.`template` AS `section.template`, `Section`.`menuindex` AS `section.menuindex`, `Section`.`searchable` AS `section.searchable`, `Section`.`cacheable` AS `section.cacheable`, `Section`.`createdby` AS `section.createdby`, `Section`.`createdon` AS `section.createdon`, `Section`.`editedby` AS `section.editedby`, `Section`.`editedon` AS `section.editedon`, `Section`.`deleted` AS `section.deleted`, `Section`.`deletedon` AS `section.deletedon`, `Section`.`deletedby` AS `section.deletedby`, `Section`.`publishedon` AS `section.publishedon`, `Section`.`publishedby` AS `section.publishedby`, `Section`.`menutitle` AS `section.menutitle`, `Section`.`donthit` AS `section.donthit`, `Section`.`privateweb` AS `section.privateweb`, `Section`.`privatemgr` AS `section.privatemgr`, `Section`.`content_dispo` AS `section.content_dispo`, `Section`.`hidemenu` AS `section.hidemenu`, `Section`.`class_key` AS `section.class_key`, `Section`.`context_key` AS `section.context_key`, `Section`.`content_type` AS `section.content_type`, `Section`.`uri` AS `section.uri`, `Section`.`uri_override` AS `section.uri_override`, `Section`.`hide_children_in_tree` AS `section.hide_children_in_tree`, `Section`.`show_in_tree` AS `section.show_in_tree`, `Section`.`properties` AS `section.properties`,
`User`.`username`,
`Profile`.`internalKey`, `Profile`.`fullname`, `Profile`.`email`, `Profile`.`phone`, `Profile`.`mobilephone`, `Profile`.`blocked`, `Profile`.`blockeduntil`, `Profile`.`blockedafter`, `Profile`.`logincount`, `Profile`.`lastlogin`, `Profile`.`thislogin`, `Profile`.`failedlogincount`, `Profile`.`sessionid`, `Profile`.`dob`, `Profile`.`gender`, `Profile`.`address`, `Profile`.`country`, `Profile`.`city`, `Profile`.`state`, `Profile`.`zip`, `Profile`.`fax`, `Profile`.`photo`, `Profile`.`comment`, `Profile`.`website`, `Profile`.`extended`,
SUM(`Vote`.`value`) AS `votes`,
COUNT(DISTINCT `View`.`uid`) as `views`,
`LastView`.`timestamp` as `new_comments`,
COUNT(DISTINCT `Comment`.`id`) as `comments`
FROM `modx_site_content` AS `Ticket`
LEFT JOIN `modx_tickets_views` `View` ON Ticket.id=View.parent
LEFT JOIN `modx_tickets_views` `LastView` ON Ticket.id=LastView.parent AND LastView.uid = 1
LEFT JOIN `modx_tickets_votes` `Vote` ON Ticket.id=Vote.parent AND Vote.class='Ticket'
LEFT JOIN `modx_tickets_threads` `Thread` ON Thread.resource=Ticket.id AND Thread.closed=0 AND Thread.deleted=0
LEFT JOIN `modx_tickets_comments` `Comment` ON Comment.thread=Thread.id AND Comment.published=1
LEFT JOIN `modx_site_content` `Section` ON Section.id=Ticket.parent
LEFT JOIN `modx_users` `User` ON User.id=Ticket.createdby
LEFT JOIN `modx_user_attributes` `Profile` ON Profile.internalKey=User.id
WHERE ( `Ticket`.`class_key` = 'Ticket' AND `Ticket`.`published` = 1 AND `Ticket`.`deleted` = 0 )
GROUP BY `Ticket`.`id`
ORDER BY createdon DESC
LIMIT 10
1) modx_tickets_threads индекс к deleted
2) modx_tickets_votes индекс к class
3) modx_tickets_comments индекс к published, createdby
4) modx_site_content индекс к deleted
Без внедрения в код больше ничего не сделать. В идеале конечно разбить запрос на части. Я думаю у василия это уже в планах, т.к. разговор у нас с ним на эту тему был;-)
А вообще, после простановки этих индексов должен чутка быстрее работать не только листинг тикетов. Кстати, если не сложно покажите SHOW PROFILE и EXPLAIN запроса после простановки индексов.
2) modx_tickets_votes индекс к class
3) modx_tickets_comments индекс к published, createdby
4) modx_site_content индекс к deleted
Без внедрения в код больше ничего не сделать. В идеале конечно разбить запрос на части. Я думаю у василия это уже в планах, т.к. разговор у нас с ним на эту тему был;-)
А вообще, после простановки этих индексов должен чутка быстрее работать не только листинг тикетов. Кстати, если не сложно покажите SHOW PROFILE и EXPLAIN запроса после простановки индексов.
modx_tickets_votes — вообще пока не используется, это задел на систему голосования за тикеты и комменты.
Базовый сниппет я пока не планирую менять, ибо тут всё-таки крайне необычная ситуация. И я так понимаю, на 100 000 не особо тормозило =)
Если на сайте такая гора документов, значит с посещалкой все окей, и можно написать свой собственный сниппет для выборки из БД.
Базовый сниппет я пока не планирую менять, ибо тут всё-таки крайне необычная ситуация. И я так понимаю, на 100 000 не особо тормозило =)
Если на сайте такая гора документов, значит с посещалкой все окей, и можно написать свой собственный сниппет для выборки из БД.
Василий подскажите пожалуйста:
Планируем на тикетах сделать сервис отзывов.
По скромным оценкам будет 1,5 миллионов отзывов.
Вопрос:
1. Потянет ли Tickets такие объёмы?
2. Есть возможность проводить поиск по самим комментариям в тикете?
Спасибо
Планируем на тикетах сделать сервис отзывов.
По скромным оценкам будет 1,5 миллионов отзывов.
Вопрос:
1. Потянет ли Tickets такие объёмы?
2. Есть возможность проводить поиск по самим комментариям в тикете?
Спасибо
Я конечно не Василий, но отвечу вам.
1. Что значит потянет Tickets? Тут скорее вопрос, потянет ли MODx. Создаете чистый сайт, пишите скрипт который сгенерит вам 1.5 млн тикетов (отзывов). Смотрите и тестируете результат, скорость, поиск и т.д. За последний месяц, тут уже обсуждали, потянет ли MODx большой объем данных… Поищите.
2. mSearch2 индексирует комментарии Тикетс из коробки. С этим проблем нет.
1. Что значит потянет Tickets? Тут скорее вопрос, потянет ли MODx. Создаете чистый сайт, пишите скрипт который сгенерит вам 1.5 млн тикетов (отзывов). Смотрите и тестируете результат, скорость, поиск и т.д. За последний месяц, тут уже обсуждали, потянет ли MODx большой объем данных… Поищите.
2. mSearch2 индексирует комментарии Тикетс из коробки. С этим проблем нет.
Собственно развернул сайт. В итоге получилось порядка 800 000 комментариев и тикетов более 300 000.
Вcе работает более менее нормально на VPS.
Но имеется проблема в работе административной части, а именно в выводе вкладки с комментариями: joxi.ru/KAgBwwMcEW3qo2
Не очень понятно толи аяксом пытаеся всё подтянуть то ли еще как-то, т.е. очень длинны ответ идет.
А нужно всего лишь получить количество записей и вывести первую страницу пагинации, а далее выводить постранично все отсальное. Понятно что сортировка влияет на скорость, но все равно всё очень долго работает и прогружает раз с 5 после обновления и запроса страницы- это только 1 страницу пагинации.
Может есть смысл написать Василию чтобы поправили работы именно административной части сайта?
Вcе работает более менее нормально на VPS.
Но имеется проблема в работе административной части, а именно в выводе вкладки с комментариями: joxi.ru/KAgBwwMcEW3qo2
Не очень понятно толи аяксом пытаеся всё подтянуть то ли еще как-то, т.е. очень длинны ответ идет.
А нужно всего лишь получить количество записей и вывести первую страницу пагинации, а далее выводить постранично все отсальное. Понятно что сортировка влияет на скорость, но все равно всё очень долго работает и прогружает раз с 5 после обновления и запроса страницы- это только 1 страницу пагинации.
Может есть смысл написать Василию чтобы поправили работы именно административной части сайта?
Тикетами можно сказать не пользовался, но логика одна и та же практически во всех компонентах. Таблицы (и другие компоненты Extjs) в админке получают (обновляют) данные в БД делая запрос к процессорам, и уже процессоры выполняют всю работу с БД. Вот папка со всеми процессорами тикетов. Найти тот, который отвечает за вывод комментов (или какое-то другое действие), обычно это getlist.class.php в соответствующей папке. Чтобы не править исходники, можно расширить родной процессор, сделать свою логику получения данных, если что-то не устраивает, и новый файл в той же папке разместить. А путь к процессору подменить на фронте админки, вот так я подменял для таблицы товаров минишопа:
То есть в конфиг таблицы подсунул свой путь к процессору. Похожий js-файл подгрузить к странице каким-нибудь событием. У меня было минишоповское msOnManagerCustomCssJs, в тикетах может быть своё, не знаю. Или родными движка подключить скрипт к админке. Но это всё конечно имеет смысл, если реально данные выбираются не самым лучшим способом. Ну или используются всякие там MODXовские методы, проверка прав и т.д. Они могут снизить скорость. В конце концов в процессоре можно хоть на чистом SQL данные из БД получить. Так что тут вопрос не в движке или ограничениях админки, а в умении выбирать данные из БД, ну и целесообразности применения каждого способа. Где-то прокатит getCollection, а где-то нет.
Ext.ComponentMgr.onAvailable('minishop2-grid-products', function(){
this.config.baseParams.action = "mgr/product/customgetlist";
this.config.save_action = 'mgr/product/customupdatefromgrid';
});
То есть в конфиг таблицы подсунул свой путь к процессору. Похожий js-файл подгрузить к странице каким-нибудь событием. У меня было минишоповское msOnManagerCustomCssJs, в тикетах может быть своё, не знаю. Или родными движка подключить скрипт к админке. Но это всё конечно имеет смысл, если реально данные выбираются не самым лучшим способом. Ну или используются всякие там MODXовские методы, проверка прав и т.д. Они могут снизить скорость. В конце концов в процессоре можно хоть на чистом SQL данные из БД получить. Так что тут вопрос не в движке или ограничениях админки, а в умении выбирать данные из БД, ну и целесообразности применения каждого способа. Где-то прокатит getCollection, а где-то нет.
У меня при 100т ресурсов + 2 TV поля в индексе (всего около 8,5 мл строк) поиск с использованием mSearch2 если искать 1 слово распространенное (любовь) находит 30 тыс ресурсов — примерно за 30...40 сек. Если искать менее распространенное слово, например розетка, общее время посика 5 сек… (VPS у меня), но при выводе еще время тратится на сам вывод (там 1 рес + 4 TV).
Думаю, если вы хотите максимальной производительности, то на готовых решениях не будет все комфортно. Советую делать свои таблицы и поиск (а лючше посмотреть поиск в сторону специализированных решений, например Sphinx).
Думаю, если вы хотите максимальной производительности, то на готовых решениях не будет все комфортно. Советую делать свои таблицы и поиск (а лючше посмотреть поиск в сторону специализированных решений, например Sphinx).
Евгений, добавил предложенные индексы.
Запрос отрабатывается чуть быстрее, на 5-10 секунд. Но это не решает проблемы.
Однозначно нужно переделывать/разделять запрос.
Запрос отрабатывается чуть быстрее, на 5-10 секунд. Но это не решает проблемы.
Однозначно нужно переделывать/разделять запрос.
Если не секрет чем обусловлена такое количество? Это короткие какие-то заметки или статьи, или какой-то другой контент?
Что-то типа доски объявлений
м
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.