Tracker - модулек малюсенький, но тяжеленный...
Даже в исходном коде видим комментик:
// TODO: These queries are very expensive, see http://drupal.org/node/105639
У меня Tracker начал ронять базу на неслабом дедике при таких объемах: около 10 тысяч юзеров, чуть больше 100тыс нод и 500тыс комментов.
Шаманство над my.cnf помогало весьма слабо... Пришлось покопаться в коде и поколдовать над запросами.
Итак.
1. Ну так как влазить в код ядра совсем некошерно, то первым шагом создаем папочку, к примеру, alttracker в sites/all/modules, копируем в нее все файлы модуля tracker, переименовываем их в alttracker.* и внутри них заменяем все вхождения словечка *tracker* на *alttracker*, *track* на *alttrack*.
2. Самое главное, ради чего все и затевалось. Облегчаем запросы.
Идем в alttracker.pages.inc и меняем там:
Строка 25
$sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, GREATEST(n.changed, l.last_comment_timestamp) AS last_updated, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d) ORDER BY last_updated DESC';
Меняем на
$sql = 'SELECT n.nid, n.title, n.type, n.changed, n.uid, (select name from {users} u where u.uid=n.uid) as name, GREATEST(n.changed, (select l.last_comment_timestamp from {node_comment_statistics} l where l.nid=n.nid)) AS last_updated, (select l.comment_count from {node_comment_statistics} l where l.nid=n.nid) as comment_count FROM {node} n WHERE n.status = 1 AND (n.uid = %d or exists (select c.nid from {comments} c where c.nid = n.nid and c.uid = %d and c.status = %d)) ORDER BY last_updated DESC';
Строка 27
$sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d)';
меняем на
$sql_count = 'SELECT COUNT(n.nid) FROM {node} n WHERE n.status = 1 AND (n.uid = %d or exists (select c.nid from {comments} c where c.nid = n.nid and c.uid = %d and c.status = %d))';
Строка 29
$result = pager_query($sql, 25, 0, $sql_count, COMMENT_PUBLISHED, $account->uid, $account->uid);
меняем на
$result = pager_query($sql, 25, 0, $sql_count, $account->uid, $account->uid, COMMENT_PUBLISHED);
Строка 32
$sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, GREATEST(n.changed, l.last_comment_timestamp) AS last_updated, l.comment_count FROM {node} n INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 ORDER BY last_updated DESC';
меняем на
$sql = 'SELECT n.nid, n.title, n.type, n.changed, n.uid, (select name from {users} u where u.uid=n.uid) as name, GREATEST(n.changed, (select l.last_comment_timestamp from {node_comment_statistics} l where l.nid=n.nid)) AS last_updated, (select l.comment_count from {node_comment_statistics} l where l.nid=n.nid) as comment_count FROM {node} n WHERE n.status = 1 order by last_updated desc';
На всякий случай комментим строки с db_rewrite_sql (строки 26, 28, 33, 35), если конечно они вам не особо нужны. Как эти запросы поведут себя, если их пропустить через db_rewrite_sql, не проверял:)
3. Идем в "Админ-Модули", отключаем Tracker и включаем наш AltTracker...
Итог:
1. База падать перестала;
2. Recent posts ("Последние сообщения" в меню) вместо 8-10 секунд отрабатывает за 2-3;
3. Track ("Следить" в профиле пользователя) - работает тоже заметно быстрее.
Осталась одна неясность: смысл проверки *** OR c.status IS NULL *** в первом запросе. У меня ни на одном из сайтов нет ни одной строки с comment.status IS NULL, в каких ситуациях он вообще может NULL-ом оказаться? Впрочем, даже если где-то и окажется, вряд ли это будет критично.
Дамы и господа, жду ваших критичных оценок. В первую очередь большая просьба глянуть незамыленным взглядом на предмет того, нет ли в оттюненых запросах каких-то ляпов:)
Комментарии
где тесты?
Было бы неплохо приложить explain.
Вообще существует модуль tracker 2 который вменяемо решает сии проблемы на drupal.org
я вообще вьюсом вывожу
у меня в трекере чего то не переводилось нормально