Один из самых прожорливых (в плане работы с MySQL) модулей в Drupal это Path. Для каждой ссылки, будь то ссылка на ноду, термин или форму ответа в комментариях, модуль создаёт запрос к таблице url_alias
с целью выяснить, не добавили ли мы для этой ссылки alias, и если добавляли, то использовать его вместо дефолтного url.
Например у вас включён модуль Path и Pathauto. Pathauto создаёт псевдонимы для записей типа "Блог" вида /blog/nid
. Тогда для того чтобы вывести 10 последних записей в блоге, модуль Path сделает 10 запросов к MySQL. Если при этом у каждой записи есть теги, то Path сделает ещё по запросу на каждый тег. В итоге, на главной странице этого блога, Path создаёт около 70 запросов.
Если у вас хороший хостинг с включённым query_cache
у MySQL, на это можно не обращать внимания. Однако меня такое положение дел не устраивает :) Будем резать!
Открываем файл includes/path.inc, идём в строчку 63 и находим там такой кусок:
if ($action == 'alias') {
if (isset($map[$path_language][$path])) {
return $map[$path_language][$path];
}
// Get the most fitting result falling back with alias without language
$alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '') ORDER BY language DESC", $path, $path_language));
$map[$path_language][$path] = $alias;
return $alias;
}
Заменяем его на:
// start hack ----
if (count($map) == 0) {
$allAliasResult = db_query("SELECT src, dst FROM {url_alias}");
while ($row = db_fetch_array($allAliasResult)){
$map[$path_language][$row['src']] = $row['dst'];
}
}
// end hack ------
if ($action == 'alias') {
if (isset($map[$path_language][$path])) {
return $map[$path_language][$path];
}
// start hack ----
else { return false; }
// end hack ------
// Get the most fitting result falling back with alias without language
$alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '') ORDER BY language DESC", $path, $path_language));
$map[$path_language][$path] = $alias;
return $alias;
}
При первом вызове функции drupal_lookup_path
, информация обо всех псевдонимах попадает в кэш, и в будущем берётся от туда, минуя БД.
Вот логи модуля Devel до и после патча:
Executed 207 queries in 211.37 milliseconds.
Executed 139 queries in 131.15 milliseconds.
−68 запросов!
Результаты теста утилитой ab, кэширование отключено, до и после патча:
Requests per second: 3.05-3.62 (в основном 3.50)
Requests per second: 3.71-4.01 (в основном 3.90)
Минусом этого патча является то, что из базы вытаскиваются все псевдонимы, независимо от того — используются они на странице или нет.
Примечание: данный патч предназначен только для одноязычных сайтов.
- Дружим Sape и Internal Page Cache (вставка динамического содержимого в закэшированную страницу)
- Плагин блока, генерящий динамический контент с помощью #lazy_builder
- Тюнинг кэширования блоков с формой
- Оптимизация кэширования больших меню
- Автоматическое удаление устаревших анонимных заказов в статусе "корзина"
Комментарии
Супер спосибо
Если memcache подключен, то можно использовать патч от ванДюка.
Кеш синонимов сбрасывается каждый раз когда я добавляю в базу новый синоним?
Кеш синонимов сбрасывается каждый раз когда загружается очередная страница
интересно, а в 7-ке как обстоят дела с запросами? не смотерли случайно?
Sergey, http://xandeadx.ru/blog/drupal/242
спасибо.
в целом это грустно... но да ладно, что не потерпеть ради любимого друпала =)
Автор статьи неприменно прав. Сам я тоже дошел до этого исследуя запросы к базе на довольно тяжелом ресурсе.
Но есть одно но. Если Ваш ресурс больших объемов и таблице алиасов храниться большое кол-во записей (в моем случае больше 10k - и хватило), то картина следующая:
- без хака: около 100 запросов по ~2мс на одной странице.
- с хаком: 1 запрос, но ~ 400мс.
В моем случае что тот первый вариант что второй одинаково ужасные. Поэтому да здравствует memcache.
Эффект обратно пропорциональный. Потребление памяти возрастает на моей конфигурации в 10 раз, как и время обработки страницы примерно в 8.
где-то накосячил
По части ядра(6.22) я очень мало чего трогал в отношении путей и алиасов. Код просто перенёс и всё. Может быть какой-то модуль хардкорит, не важно в принципе :)
Вот за это:
http://xandeadx.ru/blog/drupal/197
http://xandeadx.ru/blog/drupal/43
Спасибо
Что делал с
Уведомлять меня о новых комментариях
? У тебя ведь 6 стоит?ничего не делал. да 6
Ясно.
Спасибо большое!
нагрузка на базу сократилась почти в 4 раза! ускорения нет, но зато нет и оверлимитов :)
А вы не знаете случайно не появился ли способ избавления от минуса, например, путем сохранения кэша в отдельной таблице или еще как то? ...для 6, не могу с нее уйти :(
ой, не то написала, не в 4 раза, а на 25% почти :)
Добавить комментарий