Все что будет ниже касается моего проекта, но у вас при использование таких же модулей скорее всего та же ситуация.
Views:
1) на каждой странице вызывается дефолтный вид taxonomy_term, без понятия в чем причина сего действия, но лечится только его отключением. причем вызывался не только сам вид (2 запроса), но и валидация терминов из словаря с 20ю термами (20 запросов) итог - 22 запроса.
2) если вы используете views в связке с og и используете в качестве фильтра Organic groups: OG: Сообщения в текущей группе вид будет вызываться на всех станицах (4 запроса)
лечится кодом в настройках видимости блока
<?php
if($node = og_get_group_context()) {
return TRUE;
}
return FALSE;
?>
итог - 4*n запросов (где n - кол-во видов с этим фильтром)
User Karma:
в настройках обязательно отключаем:
Create a "karma" attribute for a $user
Create a "rank" attribute for a $user
так как врятли на каждой странице вам нужно выводить карму пользователя, лучше это делать
<?php
user_karma_user_karma($account->uid); если случай единичный.
?>
итог - n*2 не очень то и легких запросов ( где n кол-во user_load)
imagecache_profiles:
те кто использует модуль 5ки портированный под 6ку, обновляем на официальную версию
итог - n запросов (где n кол-во аватарок на странице просто жжесть...)
профиль пользователя и content_profile:
в моем случае, профиль пользователя темизировался напрямую через user-profile.tpl.php
там я загружал ноду профиля через node_load и выводил. Мне абсолютно было пофигу на те данные которые подгружаются через
hook_user($op, $edit, &$account, $category = NULL) где $op = 'view', тк эти данные я никуда не выводил
но туда грузились и группы и история и друзья и много много ненужных мне вещей.
проблема решается использованием
<?php
function mymodule_menu_alter(&$items) {
$items['user/%user_uid_optional']['page callback'] = 'mymodule_user_view';
}
function mymodule_user_view($account) {
drupal_set_title(check_plain($account->name));
// user_build_content($account); выполнение хуков мы отсекаем
return theme('user_profile', $account);
}
?>
friendlist:
friendlist предоставляет несколько страниц выводящих через views списки пользователей, если шарите в api лучше эти страницы выводить через кастом код.
для примера стараница из 6 друзей со своим кодом + на ней еще 1 блок. 40 запросов
тот же список из 6 друзей но через views и без блока - 65 запросов (25 разница, причем кол-во растет пропорционально кол-ву пользователей) это бред
так дальше для тех кто хочет похакать
User:
хакаем user_load функцию, добавляя статик кеширование наподобие тому как это сделано в node_load
OG:
в функции og_init
код
<?php
if ($user->uid) {
// $user = user_load(array('uid' => $user->uid)); зачем полностью грузить пользователя, если пожно обойтись строчкой ниже
$user->og_groups = og_get_subscriptions($user->uid); // HACK
}
else {
$user->og_groups = array();
}
?>
за ночь эти проблемы били выявлены и решены, в среднем число запросов сократилось на 100-150
на этом пока все, пишем в комментах другие проблемы и решения.
PS: забыл сказать что все вышеперечисленные проблемы легко обнаруживаются с помошью devel
Комментарии
Хорошая работа, спасибо!
можно некоторые блоки на странице подгружать аяксом, уже после загрузки страницы.. например, блоки расположенные где-нибудь внизу страницы.
если путь по которому будет вызываться контент в таком блоке будет обрабатываться друпалом прибавьте еще примерно 20 запросов.
upd даже 17 запросов, притом что данные выбираются из кеша.
Спасибо.
спасибо, полезно
ДА!! именно этого коммента я ждал))))
Еще несколько советов по оптимизации базы данных.
В таблице node можно уменьшить длину поля type.
Как часто Вы меняете типы материалов или создаете новые? Полагаю, что если это продакшн, то таких операций не должно быть вообще. Проведите анализ таблицы, в phpMyAdmin есть специальная ссылочка под структурой таблицы.
Используйте status при выборе по type из таблицы node
В таком случае будет использоваться специальный индекс. Если статус не использовать, то индекс использоваться не будет.
В таблице users_roles уменьшить длину rid
По умолчанию там стоит int(10) - это будет 10000000000 ролей, у вас на сайте есть столько ролей?
Если у вас ролей до десятка, то ставьте длину поля - 1, если от десятка до сотни ставьте 2.
Эта таблица используется достаточно часто, для определения различных прав доступа.
Для таблицы role уменьшить длину name и rid
По поводу rid - там все то же, что и в предыдущем случае. Длина name то же избыточна.
Если у вас твердый продакшен сайт и новых ролей не будет никогда, то можно сделать еще лучше.
Можно установить следующий тип полей rid и name:
ENUM('1','2') NOT NULL - здесь измените под себя, какие id ролей у вас используются.
ENUM('anonymous user','authenticated user') - какие названия ролей у вас используются.
объясните, пожалуйста, поподробнее как это сделать. спасибо
SELECT * FROM node n WHERE n.type = "page" - это не оптимальный запрос
SELECT * FROM node n WHERE n.status = 1 AND n.type = "page" - это оптимальный запрос
Может пригодиться тем кто пишет всякие сниппеты.
Спасибо, было интересно.
а как длина поля влияет на производительность?
Согласен, зато это позволит
а) сократить кол-во запросов при выводе основной страницы,
б) тем самым ускорит время ее загрузки
в) распределит запросы по времени, что снизит вероятность "пиковых загрузок"
по мне так проще вызвать 1 запрос на странице, чем через аякс давать сделать еще 20...
Днина поля влияет на длину ключа в индексе. Соответственно, чем меньше длина ключа, тем быстрей выборка.
PS. Совсем забыл сказать. Если меняете длину поля в БД, то после этого не забудьте сделать анализ измененных таблиц, после анализа индекс перестроится.
В phpMyAdmin зайдите на страницу со списком таблиц, поставьте нужные галочки и внизу в выпадающем списке выберите "анализировать".
И еще у меня есть важное замечание по поводу общей тематики топика.
Конечно, уменьшать количество запросов к БД это хорошо, это дает прирост производительности. Но самое важное это следить за качеством запросов.
Скажем, если Вы избавитесь от десятка оптимальных запросов, которые выполняются за 1 мс. И при этом вставите себе сниппет с не оптимальным запросом, который будет выполняться 100 мс, то в итоге вы все равно проиграете в производительности.
А кто-нибудь может показать примерную оптимизацию функции user_load и что это дает? А то я немного не догоняю
я вот не понял
- это не оптимальный запрос
SELECT * FROM node n WHERE n.status = 1 AND n.type = "page"
- это оптимальный запрос
разница в том, что сначало проверили на "опубликованность" ?
Разница в использовании индексов.
Курите мануал по MySQL. Конкретно вот эта глава про оптимизацию запросов:
http://dev.mysql.com/doc/refman/5.0/en/optimization.html
Пользуйтесь инструкцией EXPLAIN
спасибо почитаю
а если разница в порядке применения фильтров
1. опубликован
2. размещено на главной
3. закреплено на главной
или порядок наложения фильтров не имеет значения?
Там много тонкостей.
Порядок то же имеет свое значение.
Допустим у Вас есть таблица (table_name) с двойным индексом (key_1, key_2)
Вот в этих случаях индекс не будет использоваться:
SELECT * FROM table_name WHERE key_2 = "something"
SELECT * FROM table_name WHERE key_2 = "something 2" AND key_1 = "something 1"
Указывать ключи в условии нужно в том порядке, в каком они определены в индексе:
SELECT * FROM table_name WHERE key_1 = "something 1" AND key_2 = "something 2"
информация по imagecache_profiles устарела! Все приглашаются к тестированию новой версии!
В последних версиях OG хакать уже ничего не надо. Но меня не оставляет два вопроса:
1) зачем грузить каждому пользователю постоянно список его подписок
2) зачем вообще выполнять user_load для того, чтобы отобразить имя пользователя?
Ужас...
как вы узнаете имя пользователя?
Очень смешно. Выбирая ноду, выберу и имя пользователя по uid, который в базе есть. Нахрена мне данные по флагам, по подпискам по бог весть чему ещё? При установленном OG на каждое отображаемое имя пользователя накидывается ещё один запрос!! Зачем мне список подписок на каждого пользователя? Естественно, я хакну, чтобы отображалось только я текущего и в профилях!
Ну я уже промолчу о "великолепном" Voting API, который до усрачки гибкий, но 300 комментариев - плюс 300 запросов. Минимум... Правда, используя идеи из Comments Bonus API можно резко всё исправить
а вы не думали что имя пользователя может отличатся от значения в базе? так как заголовки нод и тд.
когда вам придется добавить во все выводы имени пользователя свою строчку например "реальное имя". будет геморой от того что вы где-то когда-то похакали. тоже касается и потписок и всего.
Вот уж подписки мне точно жалко не будет Можно было и опционально.
Ключевое слово - может. В общем, жертвуем всем ради гибкости, я понимаю конечно... Но вот всё подряд пихать в пользователя тоже не стоит, по-моему.