Уменьшаем кол-во запросов к бд на комьюнити сайтах

Главные вкладки

Аватар пользователя penexe penexe 3 апреля 2009 в 1:06

Все что будет ниже касается моего проекта, но у вас при использование таких же модулей скорее всего та же ситуация.

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 разница, причем кол-во растет пропорционально кол-ву пользователей) это бред

так дальше для тех кто хочет похакать Smile

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

Комментарии

Аватар пользователя batbug batbug 3 апреля 2009 в 7:10

можно некоторые блоки на странице подгружать аяксом, уже после загрузки страницы.. например, блоки расположенные где-нибудь внизу страницы.

Аватар пользователя penexe penexe 3 апреля 2009 в 7:28

batbug wrote:
можно некоторые блоки на странице подгружать аяксом, уже после загрузки страницы.. например, блоки расположенные где-нибудь внизу страницы.

если путь по которому будет вызываться контент в таком блоке будет обрабатываться друпалом прибавьте еще примерно 20 запросов.
upd даже 17 запросов, притом что данные выбираются из кеша.

Аватар пользователя seaji seaji 3 апреля 2009 в 13:01

Еще несколько советов по оптимизации базы данных.

В таблице 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') - какие названия ролей у вас используются.

Аватар пользователя achadidi achadidi 3 апреля 2009 в 17:18

seaji wrote:
Еще несколько советов по оптимизации базы данных.

Используйте status при выборе по type из таблицы node

В таком случае будет использоваться специальный индекс. Если статус не использовать, то индекс использоваться не будет.


объясните, пожалуйста, поподробнее как это сделать. спасибо

Аватар пользователя seaji seaji 4 апреля 2009 в 14:54

SELECT * FROM node n WHERE n.type = "page" - это не оптимальный запрос
SELECT * FROM node n WHERE n.status = 1 AND n.type = "page" - это оптимальный запрос

Может пригодиться тем кто пишет всякие сниппеты.

Аватар пользователя batbug batbug 3 апреля 2009 в 17:08

"penexe" wrote:
если путь по которому будет вызываться контент в таком блоке будет обрабатываться друпалом прибавьте еще примерно 20 запросов.
upd даже 17 запросов, притом что данные выбираются из кеша.

Согласен, зато это позволит
а) сократить кол-во запросов при выводе основной страницы,
б) тем самым ускорит время ее загрузки
в) распределит запросы по времени, что снизит вероятность "пиковых загрузок"

Аватар пользователя penexe penexe 4 апреля 2009 в 3:29

"batbug" wrote:
Согласен, зато это позволит
а) сократить кол-во запросов при выводе основной страницы,
б) тем самым ускорит время ее загрузки
в) распределит запросы по времени, что снизит вероятность "пиковых загрузок"

по мне так проще вызвать 1 запрос на странице, чем через аякс давать сделать еще 20...

Аватар пользователя seaji seaji 4 апреля 2009 в 14:49

"Valeratal" wrote:
а как длина поля влияет на производительность?

Днина поля влияет на длину ключа в индексе. Соответственно, чем меньше длина ключа, тем быстрей выборка.
PS. Совсем забыл сказать. Если меняете длину поля в БД, то после этого не забудьте сделать анализ измененных таблиц, после анализа индекс перестроится.
В phpMyAdmin зайдите на страницу со списком таблиц, поставьте нужные галочки и внизу в выпадающем списке выберите "анализировать".

Аватар пользователя seaji seaji 4 апреля 2009 в 15:11

И еще у меня есть важное замечание по поводу общей тематики топика.
Конечно, уменьшать количество запросов к БД это хорошо, это дает прирост производительности. Но самое важное это следить за качеством запросов.
Скажем, если Вы избавитесь от десятка оптимальных запросов, которые выполняются за 1 мс. И при этом вставите себе сниппет с не оптимальным запросом, который будет выполняться 100 мс, то в итоге вы все равно проиграете в производительности.

Аватар пользователя Valeratal Valeratal 2 июня 2009 в 16:46

я вот не понял

SELECT * FROM node n WHERE n.type = "page"
- это не оптимальный запрос
SELECT * FROM node n WHERE n.status = 1 AND n.type = "page"
- это оптимальный запрос

разница в том, что сначало проверили на "опубликованность" ?

Аватар пользователя seaji seaji 3 июня 2009 в 12:02

"Valeratal" wrote:
разница в том, что сначало проверили на "опубликованность" ?

Разница в использовании индексов.
Курите мануал по MySQL. Конкретно вот эта глава про оптимизацию запросов:
http://dev.mysql.com/doc/refman/5.0/en/optimization.html

Пользуйтесь инструкцией EXPLAIN

Аватар пользователя Valeratal Valeratal 3 июня 2009 в 12:16

спасибо почитаю

а если разница в порядке применения фильтров
1. опубликован
2. размещено на главной
3. закреплено на главной

или порядок наложения фильтров не имеет значения?

Аватар пользователя seaji seaji 4 июня 2009 в 14:57

Там много тонкостей.
Порядок то же имеет свое значение.
Допустим у Вас есть таблица (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"

Аватар пользователя Mr.Alinaki@drupal.org Mr.Alinaki@drup... 19 ноября 2009 в 15:37

В последних версиях OG хакать уже ничего не надо. Но меня не оставляет два вопроса:
1) зачем грузить каждому пользователю постоянно список его подписок
2) зачем вообще выполнять user_load для того, чтобы отобразить имя пользователя?

Ужас...

Аватар пользователя penexe penexe 19 ноября 2009 в 16:35

<a href="mailto:Mr.Alinaki@drupal.org">Mr.Alinaki@drupal.org</a> wrote:
В последних версиях OG хакать уже ничего не надо. Но меня не оставляет два вопроса:
1) зачем грузить каждому пользователю постоянно список его подписок
2) зачем вообще выполнять user_load для того, чтобы отобразить имя пользователя?

Ужас...


как вы узнаете имя пользователя?

Аватар пользователя Mr.Alinaki@drupal.org Mr.Alinaki@drup... 20 ноября 2009 в 0:44

penexe wrote:
как вы узнаете имя пользователя?

Очень смешно. Выбирая ноду, выберу и имя пользователя по uid, который в базе есть. Нахрена мне данные по флагам, по подпискам по бог весть чему ещё? При установленном OG на каждое отображаемое имя пользователя накидывается ещё один запрос!! Зачем мне список подписок на каждого пользователя? Естественно, я хакну, чтобы отображалось только я текущего и в профилях!

Ну я уже промолчу о "великолепном" Voting API, который до усрачки гибкий, но 300 комментариев - плюс 300 запросов. Минимум... Sad Правда, используя идеи из Comments Bonus API можно резко всё исправить Smile

Аватар пользователя penexe penexe 20 ноября 2009 в 1:02

<a href="mailto:Mr.Alinaki@drupal.org">Mr.Alinaki@drupal.org</a> wrote:
penexe wrote:
как вы узнаете имя пользователя?

Очень смешно. Выбирая ноду, выберу и имя пользователя по uid, который в базе есть. Нахрена мне данные по флагам, по подпискам по бог весть чему ещё? При установленном OG на каждое отображаемое имя пользователя накидывается ещё один запрос!! Зачем мне список подписок на каждого пользователя? Естественно, я хакну, чтобы отображалось только я текущего и в профилях!

Ну я уже промолчу о "великолепном" Voting API, который до усрачки гибкий, но 300 комментариев - плюс 300 запросов. Минимум... Sad Правда, используя идеи из Comments Bonus API можно резко всё исправить :)


а вы не думали что имя пользователя может отличатся от значения в базе? так как заголовки нод и тд.
когда вам придется добавить во все выводы имени пользователя свою строчку например "реальное имя". будет геморой от того что вы где-то когда-то похакали. тоже касается и потписок и всего.

Аватар пользователя Mr.Alinaki@drupal.org Mr.Alinaki@drup... 20 ноября 2009 в 1:17

Вот уж подписки мне точно жалко не будет Smile Можно было и опционально.

Ключевое слово - может. В общем, жертвуем всем ради гибкости, я понимаю конечно... Но вот всё подряд пихать в пользователя тоже не стоит, по-моему.