Один из самых прожорливых (в плане работы с 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)
Минусом этого патча является то, что из базы вытаскиваются все псевдонимы, независимо от того — используются они на странице или нет.
Примечание: данный патч предназначен только для одноязычных сайтов.