drupal + mysql - самые "дорогие" модули

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

Аватар пользователя andribas@drupal.org andribas@drupal.org 16 декабря 2010 в 11:41

Здравствуйте!

Напишу сюда результат анализа лога mysql за примерно пол-месяца работы сайта на друпале.
О том, как нехорошо кешировать данные в mysql, я уже писал. Там рассматривалась работа CacheRouter при выборе хранилища в БД - то есть стандартное кеширование друпала.
Теперь был проведен анализ после перевода кеша в memcache.

Вот некоторая статистика:
#memcached-tool localhost stats
bytes_read 1593512968640 = 1.5 Терабайта
bytes_written 5899978353864 = почти 6 Терабайт

mysql:
Трафик			ø в час
Принято 	81 ГБ 	217 МБ
Отправлено 	464 ГБ 	1,234 МБ
Всего	 	545 ГБ 	1,451 МБ

Анализ бинарного лога

Вот список запросов, которые изменяют информацию:

1. CAPTCHA - стоит графическая, при вводе комментариев: 36% запросов

Модуль: CAPTCHA
Число запросов: 696.77k (12.12%)
Запрос: UPDATE captcha_sessions SET token='S' WHERE csid=N

Модуль: CAPTCHA
Число запросов: 696.11k (12.11%)
Запрос: UPDATE captcha_sessions SET TIMESTAMP=N, solution='S' WHERE csid=N

Модуль: CAPTCHA
Число запросов: 695.75k (12.10%)
Запрос: INSERT INTO captcha_sessions (uid, sid, ip_address, TIMESTAMP, form_id, solution, STATUS, attempts) VALUES (N, 'S', 'S', N, 'S', 'S', N, N)

2. Стандартный модуль статистики, считает количество посещений ноды: 28% запросов
Модуль: Statistics
Число запросов: 1.60M (27.84%)
Запрос: UPDATE node_counter SET daycount = daycount + 1, totalcount = totalcount + 1, TIMESTAMP = N WHERE nid = N

3. Ядро (сессии) - записывает и обновляет сессии: 18% запросов
Модуль: Core
Число запросов: 835.58k (14.53%)
Запрос: UPDATE sessions SET uid = N, cache = N, hostname = 'S', SESSION = 'S', TIMESTAMP = N WHERE sid = 'S'

Модуль: Core
Число запросов: 213.20k (3.71%)
Запрос: INSERT INTO sessions (sid, uid, cache, hostname, SESSION, TIMESTAMP) VALUES ('S', N, N, 'S', 'S', N)

4. Database logging (core) - записывает события в базу данных: 10% запросов

Модуль: Database logging
Число запросов: 597.70k (10.39%)
Запрос: INSERT INTO watchdog (uid, TYPE, message, VARIABLES, severity, link, location, referer, hostname, TIMESTAMP) VALUES (N, 'S', 'S', 'S', N, 'S', 'S', 'S', 'S', N)

Модуль:
Число запросов:
Запрос:  

Итого, 4 модуля делают 36% + 28% + 18% + 10% = 92% !!! запросов на изменение информации

Что может быть предложено:

1. Капча - сейчас она показывается всем, кто смотрит ноду, т.к. стоит модуль ajax_comments и комментарии вместе с формой расположены на той же странице. Т.к. оставляет комментарии намного меньше людей, чем те, кто смотрят ноду, то если форму для комментариев разместить на отдельной странице - нагрузка снизится почти до нуля.
Либо альтернативный вариант помещать ее каким-то образом в кеш - такое возможно?

2. Модуль статистики - вещь полезная, например, для определения популярного контента за сегодня / за все время по числу просмотров. Сейчас ВСЯ таблица node_counter у меня весит 5-6 мегабайт!!! есть ли какой-то способ (модуль), чтобы поместить эту таблицу также в кеш, и, допустим, сбрасывать в mysql по крону? При таком подходе нагрузка также станет 0.

Также было замечено, что daycount имеет некорректное значение - по моему представлению, если я запускаю крон раз в час, то обновление должно происходить например в 00:00, когда вызывается крон - там же реализовано обновление через переменную, это неправильно, поскольку вначале переменная не установлена в 00:00, а потом, т.к. крон запускается в одно и то же время, statistics_day_timestamp может "убежать" на 1 сек, и следующий запрос уже будет выполнен в 01:00

<?phpstatistics.module , строка 179
function statistics_cron() {
  $statistics_timestamp = variable_get('statistics_day_timestamp', '');

  if ((time() - $statistics_timestamp) >= 86400) {
    // Reset day counts.
    db_query('UPDATE {node_counter} SET daycount = 0');
    variable_set('statistics_day_timestamp', time());
  }
}
?>

3. Сессии - я уменьшил время сессии в default.settings.php с 23 дней до 5 дней, сейчас размер этой таблицы 10-15 мегабайт. Хотелось бы также ее в кеш.

4. Лог - как изменится производительность системы, если весь лог отправлять в syslog? По идее, любая серверная программа отправляет в syslog - web сервер, mysql, почта и т.д. и тормозами от этого не страдает - думаю, надо настроить src и destination для друпала, пусть складывается все туда.

Итого: при выполнении этих действий нагрузка на сервер mysql по части изменений (update, insert) снизится более, чем в 10 раз!!!

Анализ медленных (или использующих много строк) запросов

Также был проанализирован slow_query.log на предмет отлавливания нехороших запросов.
Предпосылкой к этому стали следующие данные:

Количество запросов, на чтение строки, основанных на ее позиции. Большое значение переменной может быть обусловлено частым выполнением запросов использующих сортировку результата, выполнением большого числа запросов требующих полного сканирования таблиц, наличием объединений не использующих индексы надлежащим образом.

Handler_read_rnd 150 M

Количество запросов на чтение следующей строки из файла данных. Данное значение будет высоким, при частом сканировании таблиц. Обычно это означает, что таблицы не проиндексированы надлежащим образом или запросы не используют преимущества индексов.

Handler_read_rnd_next 1,976 M

Количество временных таблиц, автоматически созданных сервером на диске, во время выполнения SQL-выражений. Если значение Created_tmp_disk_tables велико, следует увеличить значение переменной tmp_table_size, чтобы временные таблицы располагались в памяти, а не на жестком диске.

Created_tmp_disk_tables 2,458 k

Количество запросов-объединений, выполненных без использования индексов. Если значение переменной не равно 0, рекомендуется проверить индексы таблиц.

Select_full_join 8,620

Количество проходов, сделанных алгоритмом сортировки. При большом значении следует увеличить значение переменной sort_buffer_size.

Sort_merge_passes 502

А также

Количество запросов, добавленных в кеш запросов.

Qcache_inserts 33 M

Количество запросов, удаленных из кеша для освобождения памяти под кеширование новых запросов. Эта информация может помочь при настройке размера кеша запросов. Кеш запросов использует стратегию LRU (дольше всего не использующиеся страницы заменяются новыми) при принятии решения об удаления запроса из кеша.

Qcache_lowmem_prunes 20 M

Очевидно, что делается скан таблиц с большим количеством строк

Вот анализ:

1. views - материал: новость, опубликован, рубрика = 10, 3 последних

Количество запросов: 14199 (3 последних) + 1485 (10 последних) + 268 (4 последних) + 153 (20 последних - таксономия)
Общее время: 16760 + 1906 + 227 + 185 = 19078 секунд, в среднем: 1.18 / 1.28 / 0.84 / 1.21
Количество строк: 13674 - 126552 /

SET TIMESTAMP=1292480648;
SELECT node.nid AS nid,
   node.created AS node_created,
   node.title AS node_title
 FROM node node
 INNER JOIN term_node term_node ON node.vid = term_node.vid
 WHERE (node.type IN ('news')) AND (node.status <> 0) AND (term_node.tid = 10)
   ORDER BY node_created DESC
 LIMIT 0, 3;

2. Облако тегов по словарю, модуль tagadelic

Количество запросов: 1053
Общее время: 936, в среднем: 0.89
Количество строк: 15154 - 15326
Запрос:

SELECT COUNT(*) AS COUNT, td.tid, td.vid, td.name, td.description FROM term_data td INNER JOIN term_node tn ON td.tid = tn.tid INNER JOIN node n ON tn.vid = n.vid WHERE td.vid IN (5) GROUP BY td.tid, td.vid, td.name, td.description HAVING COUNT(*) > 0 ORDER BY COUNT DESC LIMIT 0, 12;

3. xmlsitemap - я так понимаю, это запрос по крону на добавление новых нод в сайтмап - ПОЛНЫЙ СКАН

Количество запросов: 368
Общее время: 436, в среднем: 1.18
Количество строк: 171575 - 172750
Запрос:

SELECT n.nid FROM node n LEFT JOIN xmlsitemap x ON x.type = 'node' AND n.nid = x.id WHERE x.id IS NULL AND n.type IN ('news','reviews') ORDER BY n.nid DESC LIMIT 0, 100;

4. Снова xmlsitemap - выдача "подкарты" сайта - это даже хуже, чем полный скан

Количество запросов: 459
Общее время: 326, в среднем: 0.71
Количество строк: 134500 - 344905
Запрос:

SELECT x.loc, x.lastmod, x.changefreq, x.changecount, x.priority, x.language FROM xmlsitemap x WHERE x.access = 1 AND x.status = 1 ORDER BY x.language, x.loc LIMIT 172500, 500;

5. url_alias - снова xmlsitemap ?

Количество запросов: 388
Общее время: 210, в среднем: 0.54
Количество строк: 171762 - 345745
Запрос:

SELECT src, dst FROM url_alias WHERE LANGUAGE = 'ru' ORDER BY pid;

Остальные запросы не такие затратные, или их мало.

Итого, самый "трудный" запрос является запрос views - материал: новость, опубликован, рубрика = 10, 3 последних - самая большая нагрузка - 19078 секунд - это больше 5 часов из 15 дней полной работы

Следующим запросом идет облако тегов по словарю - 936 секунд, а словарь еще до конца не заполнен.

И последние запросы относятся к xmlsitemap.

Получается, самые дорогие запросы делает модуль views при выборке из словаря с сортировкой по дате, модуль tagadelic при составлении облака тегов и xmlsitemap.

Самым "болезненным" запросом для моего сайта получается все-таки views, о том, что с ним можно сделать хотел бы услышать Ваши комментарии, с остальным вроде более-менее понятно, с tagadelic и xmlsitemap я пока готов смириться.

Комментарии

Аватар пользователя glu2006 glu2006 16 декабря 2010 в 11:50

По таксономии, я уже писал кому-то в посте, создайте руками в базе в таблице term_node индекс по tid и по паре tid, nid Smile вы будете очень приятно удивлены результатом даже для вьюсов.
Написать про этот косяк статейку все руки не доходят.

Аватар пользователя MaNaX MaNaX 16 декабря 2010 в 12:39

glu2006 wrote:
По таксономии, я уже писал кому-то в посте, создайте руками в базе в таблице term_node индекс по tid и по паре tid, nid Smile вы будете очень приятно удивлены результатом даже для вьюсов.
Написать про этот косяк статейку все руки не доходят.

(Дружно хором): Про-сим-Про-сим...

Аватар пользователя Ne_L Ne_L 29 декабря 2010 в 17:44

посмотрел (SHOW INDEXES FROM term_node) эту таблицу у себя

Table           Non_unique      Key_name        Seq_in_index    Column_name     Collation       Cardinality     Sub_part        Packed  Null    Index_type      Comment
term_node       0               PRIMARY         1               tid             A               NULL            NULL            NULL            BTREE    
term_node       0               PRIMARY         2               vid             A               17248           NULL            NULL            BTREE    
term_node       1               vid             1               vid             A               8624            NULL            NULL            BTREE    
term_node       1               nid             1               nid             A               8624            NULL            NULL            BTREE

Индексы вроде есть - или я что то не понимаю - специально их не создавал.

Аватар пользователя MaNaX MaNaX 16 декабря 2010 в 12:29

ООООО Спасибо, человечище!!!! За 3 месяца первый топик, который не спам типа "помогите".
В закладки, однозначно)))

Аватар пользователя andribas@drupal.org andribas@drupal.org 16 декабря 2010 в 12:38

"glu2006" wrote:
По таксономии, я уже писал кому-то в посте, создайте руками в базе в таблице term_node индекс по tid и по паре tid, nid Smile вы будете очень приятно удивлены результатом даже для вьюсов.

Действительно, после запроса
ALTER TABLE term_node ADD INDEX tid (tid)
с модулем tagadelic проблем не стало,
но для views это не помогло.
Насчет индекса tid,nid не совсем понял - вроде join везде делается по vid, как это может помочь?

Аватар пользователя glu2006 glu2006 16 декабря 2010 в 13:32

<a href="mailto:andribas@drupal.org">andribas@drupal.org</a> wrote:

Действительно, после запроса
ALTER TABLE term_node ADD INDEX tid (tid)
с модулем tagadelic проблем не стало,
но для views это не помогло.
Насчет индекса tid,nid не совсем понял - вроде join везде делается по vid, как это может помочь?

Отвечу как Паниковский, вы не спрашивайте а сделайте Smile (Этот как риторический вопрос: "Чем программист отличается от философа?"). Потому что не везде join делается по vid.
В случае с вашим запросом видимо в тормоза сваливается INNER JOIN-ом попробуйте если не сделали индексом пару tid,nid все же сделать и проверьте, у меня во всяком случае после этих дел форум стал работать быстрее в 10!!! раз.
Вообще было бы интересно поковыряться с вашим запросом при большом количестве строк в таблице и найти истинную а не предполагаемую причину тормоза, поскольку в том что проблема в SQL запросе я не сомневаюсь.

Я бы просто погонял этот запрос без разных условий в самом SQL, к примеру начал бы без сортировки, потом с условиями поигрался, потом с JOIN и т.д.

Аватар пользователя andribas@drupal.org andribas@drupal.org 16 декабря 2010 в 12:40

"MaNaX" wrote:
ООООО Спасибо, человечище!!!! За 3 месяца первый топик, который не спам типа "помогите".

Осталось только найти решение, как поместить таблицы node_counter и sessions в кеш - CacheRouter или другой, потому как они наиболее затратные.

Аватар пользователя andribas@drupal.org andribas@drupal.org 16 декабря 2010 в 13:45

"glu2006" wrote:
Я бы просто погонял этот запрос без разных условий в самом SQL, к примеру начал бы без сортировки, потом с условиями поигрался, потом с JOIN и т.д.

спасибо, так и попробую сделать, что получилось напишу.

Аватар пользователя igor701 igor701 16 декабря 2010 в 16:53

Очень интересно, спасибо за познавательный анализ!
Даже не подозревал что механизм сессий капчи столько ресурсов занимают.

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 16 декабря 2010 в 17:05

а тип таблиц какой? InnoDb или MyISAM?
Я проводил эксперименты с Memmory и таблицами кеширования , но результаты были не ахти, поэтому я пока что отложил это до лучших времен. Но memmory как раз таки и позволяют существенно снизить нагрузку при обновлении данных!

Аватар пользователя ankheg ankheg 16 декабря 2010 в 17:10

С каптчей на комментариях для гостей есть еще проблема из области производительности: нельзя закешировать страницы node/* в статику, потому что у всех желающих прокомментировать будут появляться ошибки.

Кому-нибудь попадалось решение? Решает ли эту проблему модуль ajax_comments хотя бы для пользователей с включенным js? Может быть есть вариант обслуживать сессию каптчи и грузить токены формы комментариев аяксом?

Аватар пользователя Krotty@drupal.org Krotty@drupal.org 16 декабря 2010 в 20:24

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:
4. Лог - как изменится производительность системы, если весь лог отправлять в syslog? По идее, любая серверная программа отправляет в syslog - web сервер, mysql, почта и т.д. и тормозами от этого не страдает - думаю, надо настроить src и destination для друпала, пусть складывается все туда.

Увы, это не совсем так.
Во-первых, ни apache, ни mysql не используют syslog для логирования.
Во вторых, syslogd при записи каждой строки в лог выполняет вызов fsync() для синхронизации буфера на диск поэтому выгода от его использования для высоконагруженных сайтов не так очевидна.

Аватар пользователя andribas@drupal.org andribas@drupal.org 16 декабря 2010 в 21:27

"glu2006" wrote:
Вообще было бы интересно поковыряться с вашим запросом при большом количестве строк в таблице и найти истинную а не предполагаемую причину тормоза, поскольку в том что проблема в SQL запросе я не сомневаюсь.

Почитал про проблему pagination на сайтах mysql. Интересное решение предлагает Петр Зайцев (а также в комментах) на http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performanc...

Вот оригинальный запрос views:

SELECT node.nid AS nid,
   node.created AS node_created,
   node.title AS node_title
 FROM node node
 INNER JOIN term_node term_node ON node.vid = term_node.vid
 WHERE (node.type IN ('news')) AND (node.STATUS <> 0) AND (term_node.tid = 10)
   ORDER BY node_created DESC
 LIMIT 0, 3;

Вот EXPLAIN:

mysql> explain SELECT node.nid AS nid, node.created AS node_created, node.title AS node_title
FROM node node
INNER JOIN term_node term_node ON node.vid = term_node.vid
WHERE (node.type IN ('news')) AND (node.STATUS <> 0) AND (term_node.tid = 10)
ORDER BY node_created DESC  LIMIT 0, 3\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: term_node
         type: ref
possible_keys: PRIMARY,vid,tid
          key: PRIMARY
      key_len: 4
          ref: const
         rows: 20103
        Extra: Using index; Using temporary; Using filesort
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: node
         type: eq_ref
possible_keys: vid,vid_created,node_status_type,node_type
          key: vid
      key_len: 4
          ref: uralpress.term_node.vid
         rows: 1
        Extra: Using where
2 rows in set (0.00 sec)

rows: 20103 означает, что при данном запросе будет сделана ВСЯ выборка из таблицы node, которые принадлежат к данному термину, потом результат будет записан во временный файл, отсортирован и после этого отдан клиенту. Так решил оптимизатор mysql - он перевернул порядок таблиц и первую выборку делает по term_node.

Вот что получится, если принудительно заставить таблицу использовать индекс node_created (создан по умолчанию):

mysql> explain SELECT node.nid AS nid, node.created AS node_created, node.title AS node_title
FROM node node
force index (node_created)
INNER JOIN term_node term_node ON node.vid = term_node.vid
WHERE (node.type IN ('news')) AND (node.STATUS <> 0) AND (term_node.tid = 10)
ORDER BY node_created DESC  LIMIT 0, 3\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: node
         type: index
possible_keys: NULL
          key: node_created
      key_len: 4
          ref: NULL
         rows: 3
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: term_node
         type: eq_ref
possible_keys: PRIMARY,vid,tid
          key: PRIMARY
      key_len: 8
          ref: const,uralpress.node.vid
         rows: 1
        Extra: Using index
2 rows in set (0.00 sec)

Как видим, в этом случае будет выбрано РОВНО 3 строки - никаких сканов, filesort-ов.

Кстати, вот что об этом написано в документации mysql: http://dev.mysql.com/doc/refman/5.1/en/limit-optimization.html

Если сортировка результата (order by) выполнена с использованием index, то отдаются первые limit найденные строки, и это очень быстро. Если же выполняется filesort, то проверяются все строки.

Вот результат выполнения запросов к базе, используя оригинал и измененный (force index), в зависимости от количества нод с этим термином:

id	кол-во	время запроса	время запроса
термин	нод	оригинал	force index
6 	42204	0.1628		0.0006
132 	1121	0.0055		0.0010
116
137 	102	0.0012		0.0292
10005 	1	0.0006		0.5902

График не рисовал, но понятно, что оригинальный запрос хорош для небольших рубрик, там, где кол-во нод с одинаковым термином превышает 1000 выгоднее использовать измененный запрос.

Ну и есть еще один, "грязный" метод - если использовать сортировку вместо node.created - node.vid, в таком случае запрос будет также быстрее, но мне его использовать не хочется.

Был бы признателен, если бы кто-то указал как именно в друпале добавить FORCE INDEX в views query. А также не мешало бы добавить SQL_NO_CACHE для некоторых запросов - в идеале вообще бы галочку такую иметь во Views UI - disable mysql caching.

Также, для оптимизации второго запроса может быть использован индекс из нескольких столбцов (автор обращает внимание на порядок столбцов в индексе, а также на одинаковую направленность (оба ASC или оба DESC), если для сортировки используется несколько полей - типичный пример друпала: материал закреплен:убывание, дата создания:убывание ).
Некоторые вещи про mysql я до этого поста не знал.

Ну и еще описан эффективный метод "pagination" для форумов и просто нод при кол-ве 1млн.+, который работает мгновенно, но мне это пока не нужно. Для сравнения откройте и немного помотайте (чтобы не из кеша взять)
http://drupal.ru/tracker?page=500
http://www.pinkbike.com/photo/list/?date=all&page=500

Аватар пользователя andribas@drupal.org andribas@drupal.org 16 декабря 2010 в 20:39

В общем, из 19к запросов в slow_query.log при таких настройках

min_examined_row_limit                  = 10000
log_queries_not_using_indexes           = 1
slow_query_log                          = 1
slow_query_log_file                     = /var/log/mysql/slow_query.log
long_query_time                         = 0.5

5 вышенаписанных запросов составляют 18373 / 19к = 96% всех медленных запросов.
После оптимизации думаю понизить планку по min_examined_row_limit до 1к и, возможно, уменьшить long_query_time.
С Views, я, вроде, разобрался, tagadelic - подсказал glu2006, осталось посмотреть xmlsitemap.

В точности воспроизвести запрос длительностью 1 сек у меня не получилось, видимо это происходит в момент нагрузки, поэтому мои результаты получаются меньше, но статистика mysql - Handler_read_rnd, Handler_read_rnd_next меня беспокоят, поэтому буду анализировать дальше.

Вот какие изменения с mysql уже сделаны:

1 - ALTER TABLE comments ADD INDEX TIMESTAMP ( TIMESTAMP );
2 - ALTER TABLE captcha_sessions ADD INDEX TIMESTAMP ( TIMESTAMP );
3 - ALTER TABLE term_node ADD INDEX tid (tid);

1 - используется, если Вы выводите комментарии в плоском виде
2 - если не добавить, то операция удаления раз в сутки кроном будет долгой
3 - для модуля tagadelic

Аватар пользователя andribas@drupal.org andribas@drupal.org 16 декабря 2010 в 21:14

"<a href="mailto:Krotty@drupal.org">Krotty@drupal.org</a>" wrote:
Во вторых, syslogd при записи каждой строки в лог выполняет вызов fsync() для синхронизации буфера на диск поэтому выгода от его использования для высоконагруженных сайтов не так очевидна.

Здесь пишут, что вроде как для таких сайтов и сделали этот модуль - http://drupal.org/handbook/modules/syslog
Вторая альтернатива - отключить лог. Я, пожалуй, попробую переключить на syslog и посмотрю, что получилось.

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 16 декабря 2010 в 22:42

Из моих изысканий на данную тему (Все нижеизложенное относится к MySQL). Все мы знаем, что есть такие таблицы, как cache_XXX и они позволяют существенно снизить нагрузку тоже по очевидным причинам, но вот делема, эти таблицы имеют формат либо MyISAM? либо InnoDB, что в итоге выражается в том, что они хранятся на ... диске, а не в виртуальной памяти, как того хотелось бы и следовало ожидать.

Но зато есть клевый тип таблиц - Memory, в чем их прикол:
1. они хранятся в виртуальной памяти, поэтому доступ и модификация данных проходят моментально;
2. они могут использовать на всю катушку hash index;
3. они не используют диск!

Разумеется, у этого типа есть свой существенный недостаток - максимальная длина строки не м.б. больше 64k байт! Если посмотреть на структуру типичной drupal кеш таблицы, то не трудно заметить, что она использует такой тип как blob, т.е. явно больше 64k (хотя и их мы не получим под кеш, т.к. есть еще другие поля и под них надо будет выделять пространство из этих пресловутых 64k)!

И недостаток поменьше - если виртуальная память закончилась, то данные записываются на диск в myisam таблицу, то в общем то возвращает нас к тому, от чего мы хотели бы уйти...

Что в итоге я попробовал сделать, я модифицировал таблицы в тип Memory и добавил новое индекс поле, кроме того, я переработал файл cache.inc, чтобы иметь возможность дробить общий блок данных на небольшие порции где то по 40k каждая и запихивать их не в одну строку, а в n строк, благо по теории вероятности, данных, которые смогут уместиться в одну строку намного больше, чем тех, которым надо будет несколько строк. Подтверждено империческим путем.

В итоге я действительно выиграл в скорости доступа и обновлении данных (mysql, видно по devel логам), но вот итоговая скорость пострадала (т.е. mysql + php, опять таки исходя из devel логов). В чем была причина я не стал разбираться досконально, пока нет на это времени. Тестировал на windows, MySQL 5.1.36, eaccselerator и php 5.2.10.

Для чего я распинался. Кому интересно было бы помочь мне в моих начинаниях по этой теме я завтра выложу мой новый cache.inc и sql команды для создания модифицированных кеш таблиц.

В чем плюс от таких изысканий - кеш должен стать поистине космически шустрым...

Буду рад за участие и дельные советы!

Аватар пользователя podarok@drupal.org podarok@drupal.org 23 декабря 2010 в 11:09

<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a> wrote:

Для чего я распинался. Кому интересно было бы помочь мне в моих начинаниях по этой теме я завтра выложу мой новый cache.inc и sql команды для создания модифицированных кеш таблиц.

В чем плюс от таких изысканий - кеш должен стать поистине космически шустрым...

Буду рад за участие и дельные советы!

Разгребусь с переносом друпалера на localize.drupal.org и помогу всю эту работу закомитить патчиками на drupal.org

Спасибо за столь познавательный анализ! Читаю и учусь с удовольствием!

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 24 декабря 2010 в 10:39

<a href="mailto:podarok@drupal.org">podarok@drupal.org</a> wrote:
<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a> wrote:

Для чего я распинался. Кому интересно было бы помочь мне в моих начинаниях по этой теме я завтра выложу мой новый cache.inc и sql команды для создания модифицированных кеш таблиц.

В чем плюс от таких изысканий - кеш должен стать поистине космически шустрым...

Буду рад за участие и дельные советы!

Разгребусь с переносом друпалера на localize.drupal.org и помогу всю эту работу закомитить патчиками на drupal.org

Спасибо за столь познавательный анализ! Читаю и учусь с удовольствием!

Спасибо за помощь, но andribas@drupal.org подсказал, что уже похожий модуль существует. Беглый анализ показал, что он как минимум "не сырой". Я не проводил с ним эксперименты, планирую ими заняться чуть попозже. Но по сравнению с memcache я уже вижу ряд минусов такого подхода, хотя плюсы остаются прежними (см. выше):
1. память, ее д.б. достаточно!
2. информация, помещаемая в таблицу по размеру д.б. по возможности максимального размера (memory не оптимизирует расход памяти, а тупо использует всю строку, т.е. например 40k, что для записи например 500 байт жирновато будет...)
3. не понятно, если использовать сжатие, как это отразится на скорости работы?

Так что такие таблицы имеет смысл дробить не по названию cache, cache_menu, а по размеру отведенных полей под данные, например 512, 1k, 2k, 4k, 8k, 16k, 32k. Уровень сегментации лучше определять империческим путем. Но насколько это будет быстрее и эффективнее, чем тот же memcached я не знаю, т.к. для поиска того же кеша придется шестрить все созданные кеш таблицы...

Аватар пользователя podarok@drupal.org podarok@drupal.org 24 декабря 2010 в 11:25

<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a> wrote:

Спасибо за помощь, но andribas@drupal.org подсказал, что уже похожий модуль существует. Беглый анализ показал, что он как минимум "не сырой". Я не проводил с ним эксперименты, планирую ими заняться чуть попозже. Но по сравнению с memcache я уже вижу ряд минусов такого подхода, хотя плюсы остаются прежними (см. выше):
1. память, ее д.б. достаточно!
2. информация, помещаемая в таблицу по размеру д.б. по возможности максимального размера (memory не оптимизирует расход памяти, а тупо использует всю строку, т.е. например 40k, что для записи например 500 байт жирновато будет...)
3. не понятно, если использовать сжатие, как это отразится на скорости работы?

Так что такие таблицы имеет смысл дробить не по названию cache, cache_menu, а по размеру отведенных полей под данные, например 512, 1k, 2k, 4k, 8k, 16k, 32k. Уровень сегментации лучше определять империческим путем. Но насколько это будет быстрее и эффективнее, чем тот же memcached я не знаю, т.к. для поиска того же кеша придется шестрить все созданные кеш таблицы...

Сжатие кеша точно умедляет работу, я проверял на xcache + gzip
По сегментации - очень здравая мысль, но определенно нужно перехватывать алгоритм cache_bins и разделять отправку елементов в соответствующе сегментированные хранилища.
Здесь правда появится елемент поиска хранилища уже на стадии запроса и это тема для разговора и обдумывания... Не уверен, что есть смысл париться - проще на сервер докупить +4 гига оперативки... Тем более, что анализируя статистику размеров елементов кеша - они есть от пары байт до почти мегабайта(bin localize, bin menu)

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 24 декабря 2010 в 13:56

<a href="mailto:podarok@drupal.org">podarok@drupal.org</a> wrote:
<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a> wrote:

3. не понятно, если использовать сжатие, как это отразится на скорости работы?

Сжатие кеша точно умедляет работу, я проверял на xcache + gzip

А сжимали с каким качеством? Если использовать максимально быстрое сжатие только для больших данных, которые например не влезут в 32k, а таких заведомо будет не много, то м.б. игра будет стоить свеч.

Аватар пользователя podarok@drupal.org podarok@drupal.org 24 декабря 2010 в 14:13

<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a> wrote:
<a href="mailto:podarok@drupal.org">podarok@drupal.org</a> wrote:
<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a> wrote:

3. не понятно, если использовать сжатие, как это отразится на скорости работы?

Сжатие кеша точно умедляет работу, я проверял на xcache + gzip

А сжимали с каким качеством? Если использовать максимально быстрое сжатие только для больших данных, которые например не влезут в 32k, а таких заведомо будет не много, то м.б. игра будет стоить свеч.

Вот результат работы xcache http://podanenko.com/fe/1.png несколько секунд на огромнейшем сайте... (около 200 модулей)
Как видно - размеры bin в основном несколько килобайт и есть несколько больших...
После того, как натравить на сайт apachebench ( ab -c5 -n500 ) http://podanenko.com/fe/2.png
Видно, что вся страница тянеться из кеша... Размер ее ~20-190К. Для того же xcache и memcached это не есть что-то особенное.
Даже если одновременно доступяться 30 пользователей (Это трафик сайтов с лямом пользователей) Друпал вполне за секунду сгенерит страницу и отдаст ее дальше только из кеша...

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 24 декабря 2010 в 15:21

<a href="mailto:podarok@drupal.org">podarok@drupal.org</a> wrote:

Здесь правда появится элемент поиска хранилища уже на стадии запроса и это тема для разговора и обдумывания... Не уверен, что есть смысл париться - проще на сервер докупить +4 гига оперативки...

Кстати о птичках, а почему бы не добавить еще одну табличку, типа cache_saved, в который мы бы как раз и хранили информацию в какую таблицу и какие данные мы положили...

Да и еще, для разной длины данных можно использовать разную степень сжатия, а именно, если у нам надо сжать 64k, то проще будет использовать быстрое сжатие, а если 640k, то можно и самое эффективное, тогда для небольших данных мы будем сжимать быстро и они все равно влезут в свои 32k - 42k, а для больших будем использовать самое эффективное, чтобы рационально использовать место в памяти...

Ну и выигрыш - если кешировать раз в пять минут, то скорее всего соотношение загрузка проца/время генерации и вся оперативка/оперативка под кеш будут достаточно неплохо смотреться на общем фоне.

В общем надо будет поиграться с этим...

Аватар пользователя podarok@drupal.org podarok@drupal.org 27 декабря 2010 в 19:57

<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a> wrote:
<a href="mailto:podarok@drupal.org">podarok@drupal.org</a> wrote:

Здесь правда появится элемент поиска хранилища уже на стадии запроса и это тема для разговора и обдумывания... Не уверен, что есть смысл париться - проще на сервер докупить +4 гига оперативки...

Кстати о птичках, а почему бы не добавить еще одну табличку, типа cache_saved, в который мы бы как раз и хранили информацию в какую таблицу и какие данные мы положили...


Да, это реально, но сегментирование додает хопы для доступа к кешу
Поиск данных становится более медленным и скорее всего это будет еффективным при authcache + 10K+ пользователей именно зарегестрированных. (опять же нужно тестирование и нагрузка тем же апачбенчем с соответствующими куками)
Quote:

Да и еще, для разной длины данных можно использовать разную степень сжатия, а именно, если нам надо сжать 64k, то проще будет использовать быстрое сжатие, а если 640k, то можно и самое эффективное, тогда для небольших данных мы будем сжимать быстро и они все равно влезут в свои 32k - 42k, а для больших будем использовать самое эффективное, чтобы рационально использовать место в памяти...


Сама система кеширования уже на словах усложняется. Вполне возможно что разширение вширь даст более приемлемые результаты. К примеру установка в 2U сервер несколько MiniITX нод(150$ каждая, 4-8 гиг оперативы) кластером memcache с балансировкой нагрузки по нодам memcache тем же haproxy позволит без лишнего кодирования добиться хранения данных в зависимости от размера бинок кеша на разных нодах, оптимизированых под разные нужды + добавит устойчивость от падений.
Три ноды + балансер потянут на тыщу баксов(для проэкта с такими нагрузками это не деньги) и смогут обслужить очень много запросов.

Quote:

Ну и выигрыш - если кешировать раз в пять минут, то скорее всего соотношение загрузка проца/время генерации и вся оперативка/оперативка под кеш будут достаточно неплохо смотреться на общем фоне.

В общем надо будет поиграться с этим...

Аватар пользователя bodro bodro 28 декабря 2010 в 11:36

>> К примеру установка в 2U сервер несколько MiniITX нод

Был опыт? Есть ли на эту тему руководства или готовые решения, чтоб потом с таким сервером в датацентре в кружок юных техников не отослали )

Аватар пользователя podarok@drupal.org podarok@drupal.org 28 декабря 2010 в 19:27

bodro wrote:
>> К примеру установка в 2U сервер несколько MiniITX нод

Был опыт? Есть ли на эту тему руководства или готовые решения, чтоб потом с таким сервером в датацентре в кружок юных техников не отослали )


пока тестирование проводил только с виртуальными машинками...
но двигаюсь в эту сторону... Под MiniITX кластеры даже есть уже созданные корпуса...

Аватар пользователя glu2006 glu2006 17 декабря 2010 в 0:04

Во вьюсах структуру запроса можно поменять с помощью хука
http://drupalcontrib.org/api/function/hook_views_query_alter/6

Вообще понять бы что курит Мерлин (откуда у человека столько энергии), когда ваяет модули типа вьюсов, цтулс и панелей ;), от бы где развернулись.

Аватар пользователя vgoodvin vgoodvin 17 декабря 2010 в 0:02

"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:

InnoDB тоже можно перевести в память, будет ли при этом запись на диск не знаю. Почитайте про HandlerSocketPlugin для мускуля, он для кеша судя по всему то что надо и на php уже враппер есть.

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 17 декабря 2010 в 8:20

vgoodvin wrote:
"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:

InnoDB тоже можно перевести в память, будет ли при этом запись на диск не знаю. Почитайте про HandlerSocketPlugin для мускуля, он для кеша судя по всему то что надо и на php уже враппер есть.

В том то и дело, что InnoDb пишет в память, при чем как минимум раз в секунду. А каждое обращение к диску - это тормоза. Ну и главное - зачем нам писать кеш на диск? Кеш на то и кеш, чтобы его хранить в памяти, да и он не очень то нужен после перезагрузки/восстановления системы, так что ему прямая дорога в memmory!

осталось только понять, где в моих изысканиях косяк, я подозреваю, что в нарезке / форматировании данных, т.к. периодически переменная variables начинала глючить и писала какую то хрень в качестве последней порции из нарезки данных. Я грешу на то, что надо было делать перекодировку в bibary формат, а не пихать string, но точнее не исследовал...

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

Аватар пользователя UnnamedNETUA UnnamedNETUA 17 декабря 2010 в 1:22

вот возник вопрос. думаю analytics у вас стоит, пройдитесь по ссылкам, кликают ли по этим самым читаемым материалам?

Аватар пользователя andribas@drupal.org andribas@drupal.org 17 декабря 2010 в 8:32

"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
В чем плюс от таких изысканий - кеш должен стать поистине космически шустрым...

До того, как написать этот пост, о чем я написал в самом начале - у меня был настроен CacheRouter на использование хранилища в БД - при этом за сутки в bin лог mysql сваливалось около гигабайта (изменений информации) - даже если использовать таблицы в памяти - не знаю, насколько это будет эффективно, будет ли информация из этих таблиц попадать в кеш mysql? если да, то она будет вытеснять оттуда остальные "полезные" сохраненные запросы. Ну и самое главное - чем Вам не нравится CacheRouter + memcached? он уже написан и готов к употреблению, чем Ваш подход лучше / эффективней? Там точно также реализовано хранение всех таблиц cache_ в памяти. Ну или если Вы твердо уверены, что таблицы в памяти mysql быстрее, может проще будет добавить Ваше хранилище в CacheRouter - там вроде аккуратно все сделано?

"tema" wrote:

Спасибо за статью. Как раз на эту тему:

Из того, что указано на скриншоте - accesslog у меня выключен, весь кеш не попадает в БД (используется хранилище memcached) - а капчи и считалки там видимо нет. Первое, что необходимо сделать - это кеш убрать из БД, я уже это сделал, теперь смотрю, что осталось - получается, что sessions очень хороший кандидат на кеширование.
SELECT url_alias у меня не всплывал в логе, может запросов и много, но быстрые - а, возможно, это обнаружится при следующем рассмотрении, спасибо.

"glu2006" wrote:
Во вьюсах структуру запроса можно поменять с помощью хука

Спасибо, посмотрю.

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 17 декабря 2010 в 8:48

<a href="mailto:andribas@drupal.org">andribas@drupal.org</a> wrote:
"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
В чем плюс от таких изысканий - кеш должен стать поистине космически шустрым...

Ну и самое главное - чем Вам не нравится CacheRouter + memcached? он уже написан и готов к употреблению


Надо почитать про это поподробнее будет. Но я не раз слышал, что после активации этой связки начинались танцы с бубнами в других модулях, но почитать про это поподробнее все таки стоит Smile

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 20 декабря 2010 в 8:33

<a href="mailto:andribas@drupal.org">andribas@drupal.org</a> wrote:
"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
В чем плюс от таких изысканий - кеш должен стать поистине космически шустрым...

До того, как написать этот пост, о чем я написал в самом начале - у меня был настроен CacheRouter на использование хранилища в БД - при этом за сутки в bin лог mysql сваливалось около гигабайта (изменений информации) - даже если использовать таблицы в памяти - не знаю, насколько это будет эффективно, будет ли информация из этих таблиц попадать в кеш mysql? если да, то она будет вытеснять оттуда остальные "полезные" сохраненные запросы. Ну и самое главное - чем Вам не нравится CacheRouter + memcached? он уже написан и готов к употреблению, чем Ваш подход лучше / эффективней? Там точно также реализовано хранение всех таблиц cache_ в памяти. Ну или если Вы твердо уверены, что таблицы в памяти mysql быстрее, может проще будет добавить Ваше хранилище в CacheRouter - там вроде аккуратно все сделано?

Я поставил себе модуль memcache + memcached, результат по скорости был нулевой, хотя потребление памяти слегка уменьшилось.

Я начал копать, в чем причина и вот что нашел на http://code.google.com/p/memcached/wiki/FAQ#Memcached_is_not_faster_than...?

Memcached is not faster than my database. Why?¶

In a one to one comparison, memcached may not be faster than your SQL queries. However, this is not its goal. Memached's goal is scalability. As connections and requests increase, memcached will perform better than most database only solutions. Please test your code under high load with simultaneous connections and requests before deciding memcached is not right for you.

Т.е. к вопросу, а зачем на memory - видать memory может бытьпросто шустрее, хотя на маштабируемой системе было бы неплохо юзать memcache.

Аватар пользователя run run 17 декабря 2010 в 11:56

"glu2006" wrote:
По таксономии, я уже писал кому-то в посте, создайте руками в базе в таблице term_node индекс по tid и по паре tid, nid Smile вы будете очень приятно удивлены результатом даже для вьюсов.
Написать про этот косяк статейку все руки не доходят.

Напиши. Как получиться, хоть ногами, главное напиши!

Аватар пользователя Dan Dan 17 декабря 2010 в 12:09

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:
Модуль статистики - вещь полезная,

Полезная, но жрущая. Лучше искать сторонние решения.

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:
Statistics...Database logging

Их отключать однозначно. Если сервер свой, то попробуй заюзать syslog.

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:
Самым "болезненным" запросом для моего сайта получается все-таки views, о том, что с ним можно сделать хотел бы услышать Ваши комментарии, с остальным вроде более-менее понятно, с tagadelic и xmlsitemap я пока готов смириться.

Или переписать руками или hook_query_alter.

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:
то если форму для комментариев разместить на отдельной странице - нагрузка снизится почти до нуля.
Либо альтернативный вариант помещать ее каким-то образом в кеш - такое возможно?

Может грузить её аяксом, без перехода на другую страницу?

Аватар пользователя vgoodvin vgoodvin 17 декабря 2010 в 12:27

"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
В том то и дело, что InnoDb пишет в память, при чем как минимум раз в секунду. А каждое обращение к диску - это тормоза.

Вот это я не совсем понял. Пишет в память но причем здесь диск?

Для кеша более важна скорость чтения - хвалят HSplugin, бенчмарки дают скорость выше чем memcached и к тому же остается доступ через обычный SQL
Для статистики важна скорость записи - хвалят MongoDB (особенно capped collections)

Кто-нибудь пробовал что-то из вышеперечисленного?

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 17 декабря 2010 в 13:32

vgoodvin wrote:
"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
В том то и дело, что InnoDb пишет в память, при чем как минимум раз в секунду. А каждое обращение к диску - это тормоза.

Вот это я не совсем понял. Пишет в память но причем здесь диск?

Я не правильно выразился, пишет на диск. Она ведь поддерживает транзакции, вот и приходится обновлять логи и синхронизировать данные...

Аватар пользователя UnnamedNETUA UnnamedNETUA 17 декабря 2010 в 12:42

Было бы интересно, если ТС бы поставил MariaDB, прозрачная замена с супер скоростью и отписал результат работы, сравнение по скорости до и после.

Аватар пользователя vgoodvin vgoodvin 17 декабря 2010 в 14:51

А данные синхронизирует при каждой транзакции?

"UnnamedNETUA" wrote:
MongoDB вообще другая тема, люди пробовали плагин для работы с ним, говорят даже не ставиться друпал на него.

Есть такой. Не ставится и нет необходимости держать весь друпал на монге ибо это повлечет проблемы.
Можно использовать монго только для записи статистики и каких-либо логов. Плагин не обязателен, можно работать напрямую а иногда даже необходимо.

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 17 декабря 2010 в 15:22

vgoodvin wrote:
А данные синхронизирует при каждой транзакции?

Слава богу нет. есть настройка, которая позволяет управлять, как синхронизировать данные. Нол смысл все равно в том, что юзается диск, а для кеша это как то глупо!

попробовал memcache - на локальной машинке завелось, понравилось, правда немного смущает, что если что то не то станется с демоном memcached, то могут быть большие проблемы с кешированием, а точнее его отсутствием... Но все равно, такой механизм есть и он работает, а это главное!

Аватар пользователя darkdim darkdim 17 декабря 2010 в 20:10

вопрос аффтору: почему Вы выбрали CacheRouter + memcached?
у мну почему-то эта связка не вызвала восторга((
Заранее благодарен за ответ!

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 декабря 2010 в 10:04

"darkdim" wrote:
вопрос аффтору: почему Вы выбрали CacheRouter + memcached?
у мну почему-то эта связка не вызвала восторга((

CacheRouter использовал сразу, другие не смотрел.
В качестве хранилища первоначально использовал APC, но там нет LRU, и память быстро кончалась.
потом мне подсказали на этом сайте (Crea), что у memcached LRU есть - поэтому не вижу ему альтернативы.

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 декабря 2010 в 15:10

"ankheg" wrote:
Кому-нибудь попадалось решение? Решает ли эту проблему модуль ajax_comments хотя бы для пользователей с включенным js? Может быть есть вариант обслуживать сессию каптчи и грузить токены формы комментариев аяксом?

К сожалению, на drupal.org все рассуждения и feature requests сводятся к тому, что юзайте платный mollom Дриса Байерта. Выше человек указал его пост о нагрузке отдельных модулей. Удивлен, что он не постебался и про капчу не стал писать - что какая она есть - полный отстой, юзайте моллом.

"Dan" wrote:
Может грузить её аяксом, без перехода на другую страницу?

А как это можно сделать? Сейчас стоит ajax_comments, он может только "раскрывать" форму, подгружать не умеет, других модулей тоже не нашел - по идее, хорошо бы весь comment_form грузить отдельно, потому что он кеш тоже засирает прилично, а комменты пишут далеко не все.
А если сделать на отдельной странице форму комментариев, то в ajax_comments смысла нет.

Так что Ваша идея намного лучше - подгружать целиком всю форму комментов, для этого есть готовое решение?
AJAX module это умеет?

"vgoodvin" wrote:
Для кеша более важна скорость чтения - хвалят HSplugin, бенчмарки дают скорость выше чем memcached и к тому же остается доступ через обычный SQL

Я читал в блоге разработчика плагина, там первое, что делается - это все данные в память грузятся (там где 750к/сек запросов), еще тестировали с SSD, и как преимущество они описывают именно разделение кеша запросов с mysql. В его схеме memcached используется для хранения выполненных запросов, причем запросов простых, а в случае с друпалом memcached используется для хранения более сложных данных - блоки, формы, страницы и т.д. - собранные из 200-300 запросов. Если же весь кеш друпала сделать доступным через Handler Socket Plugin, то кеш запросов mysql будет бесполезным, разве не так? Вряд ли это будет лучше, чем memcached.

Аватар пользователя vgoodvin vgoodvin 18 декабря 2010 в 15:30

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:
Я читал в блоге разработчика плагина, там первое, что делается - это все данные в память грузятся (там где 750к/сек запросов), еще тестировали с SSD, и как преимущество они описывают именно разделение кеша запросов с mysql. В его схеме memcached используется для хранения выполненных запросов, причем запросов простых, а в случае с друпалом memcached используется для хранения более сложных данных - блоки, формы, страницы и т.д. - собранные из 200-300 запросов. Если же весь кеш друпала сделать доступным через Handler Socket Plugin, то кеш запросов mysql будет бесполезным, разве не так? Вряд ли это будет лучше, чем memcached.

не совсем Вас понял, причем здесь кеш запросов? http://l-o-n-g.livejournal.com/153756.html

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 декабря 2010 в 15:48

"vgoodvin" wrote:
не совсем Вас понял, причем здесь кеш запросов?

"Когда HandlerSocket обращается к хранилищу InnoDB, запись будет закеширована только буфере, и будет доступна для использования другими SQL запросами."
весь кеш друпал будет в кеше mysql.
Там вообще основная идея не кеширование, а быстрое получение результата запроса вида «SELECT user_name, user_email, created FROM user WHERE user_id=?» - это решение отлично подходит для url_alias, т.к. запросы будут миновать SQL layer, но там не рассматривается ведение кеша (именно его искусственное создание) в mysql.

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 декабря 2010 в 19:09

"Dan" wrote:
Я не делал, но пишут, что могёт.

С капчей у него проблемы - с нынешней версией несовместимо. Сейчас в модуле капча стоит приоритет на него "критический" уже давным-давно http://drupal.org/node/334377, другие спрашивают умрет ли AJAX в D7.
И я так и не понял, может ли он загружать форму? из того, что о нем прочитал, понял только, что он может проверить, средиректить и т.д., но не загрузить. Поставил, так оно и есть, как загрузить не понял.

Из коробки работает Dialog API, там как раз делать ничего не надо, только включить модуль и по ссылке добавить комментарий будет открываться модальное окно. Попробую его использовать.

Аватар пользователя andribas@drupal.org andribas@drupal.org 19 декабря 2010 в 10:41

1. Написал запрос на форум mysql что можно сделать с запросом views - ответ неутешительный, единственный способ - это денормализация таблиц - например, добавление обязательной таксономии в таблицу node или создание дополнительной таблицы vid,created,tid + поля, по которым делается фильтр - http://forums.mysql.com/read.php?24,399387,399642#msg-399642. До друпала у меня так и было - на 2 типа материала 2 таблицы, в каждой есть обязательный cat_id.
Вообще, медленный запрос невозможно ускорить, если выборка делается из двух таблиц - либо будет filesort, либо полный скан пусть и не таблиц, но индексов.

2. Пока сделал FORCE INDEX там, где он работает быстрее таким вот способом:

<?phpfunction views_rewrite_views_query_substitutions($view)
{
  if($view->name == 'news_by_topic')
  {
    return array('FROM {node} node' => 'FROM {node} node FORCE INDEX (node_created)');
  }
  if($view->name == 'same_topic')
  {
    return array('FROM {node} node' => 'FROM {node} node FORCE INDEX (node_created)');
  }
}

function views_rewrite_query_xmlsitemap_generate_alter(array &$query, array &$args, array $sitemap) {
    $query['FROM'] .= " FORCE INDEX (access_status_language_loc)";
}
?>

hook_pre_execute мне не помог, hook_query_alter это не умеет.

3. Для xmlsitemap добавил индекс ALTER TABLE xmlsitemap ADD UNIQUE INDEX UNIQUE access_status_language_loc (access,STATUS,LANGUAGE,loc) и хук, один запрос победил.

Это что касается медленных запросов. По нагрузке update, insert:

4. Капча - тестирую Dialog API, вроде все работает, надо только темизировать.
5. Статистика считалка - есть три подхода:

  • как я написал вначале, нашел такую же идею на друпал.орг - помещать таблицу в кеш и обновлять таблицу в БД по крону, готового решения нет.
  • что-то, что предлагал UnnamedNETUA - использовать гугл, здесь идею эту описывают - использовать модуль Google Alalytics API, выдергивая оттуда по крону просмотры. Готового решения опять же нет, и меня немного напрягает, сколько будет идти такой запрос при большом количестве просмотров.
  • использовать AWStats или другую стороннюю систему для сбора статистики, а потом помещать ее в друпал - тоже неплохой вариант. Когда искал решение, наткнулся на такую фразу "First, AWSTAT's are not visible. One of the reasons is that the 4th largest referrer on Drupal.org is a porn site." - http://drupal.org/node/166252 Smile

6. Сессии - поставил вместо CacheRouter Memcache, сейчас для тестирования завел на каждую таблицу кеша отдельный memcached 16Mb и поставил собирать cacti - всего получилось 12 таблиц вместе с sessions,users. Читал о каких-то проблемах memcache с загрузкой фото и другими формами - сегодня потестирую, также читал рекомендации именно для форм использовать cacherouter.
7. Лог отправил в syslog. Настройки для syslog-ng такие:

destination drupal { file("/var/log/drupal.log"); };
destination messages { file("/var/log/messages"); };

filter f_drupal { facility(local0); };
filter f_syslog { not facility(local0); };

log { source(src); filter(f_syslog); destination(messages); };
log { source(src); filter(f_drupal); destination(drupal); };

Еще заметил, что хоть у меня и включено кеширование блоков, на самом деле почти ничего не кешируется. Вот, согласно http://drupaler.ru/table/drupal/blocks/6 , там где cache=-1 кеширование выключено.
У меня запрос

SELECT *
FROM `blocks`
WHERE theme = 'mytheme'
AND STATUS =1
LIMIT 0 , 100

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

В общем, осталось только статистику просмотров node_counter собирать по другому. А Вы как это делаете?

Аватар пользователя Dеmimurych Dеmimurych 19 декабря 2010 в 13:01

"vgoodvin" wrote:
HandlerSocketPlugin

Никакого отношения к кешам и прочему не имеет.
Исследователь заметил, что при совершении громадного количества запросов к mysql серверу по типу ключ знание, основные нак5ладные расходы это не сама выборка данных, а разбор запроса самим сервером. Его анализ, оптимизация, и уже потом выборка данных.
Имеено эту проблему и решает это плагин. Доводя производительность мйскль до уровня NoSql решений. В случае ДРУПАЛА, это плагин мог бы дать резкий скачек в производительности, именно из за большого количества мелких запросов типа ключ значение.

По поводу большого коллективиста insert ov.
Переведите таблицы на InnodDB и в mysql поставьте настройку innodb_flush_log_at_trx_commit=0
что даст указание серверу сбрасывать на диск данный раз в секунду. А не сразу после запроса.
Это кончено опасно тем, что при падении сервера вы можете потерять данные за последнюю секунду. Но вы сразу ощутите как стало легче жить

Общие правила по переходу на innodb таковы, вы получите заметный прирост в производительности в случает если у вас ведется активная работа на запись в таблицы.

Quote:
В общем, осталось только статистику просмотров node_counter собирать по другому. А Вы как это делаете?

НЕ используем виевс. Это конечно холивар. И у Виевс есть серьезный аргумент - в виде простоты поддержки проекта. Но и такой же серьезный контраргумент. Сложности с производительностью на высоконагруженных проектах.

Далее. правильная работа с мемкешем. В случае если основное количество нагрузки у вас это просмотр материала, то при правильной настройке memcesha в связке с друпал кешем, вы должны получать НОЛЬ запросов на просмотр кешированной страницы.

Аватар пользователя Mirocow Mirocow 20 декабря 2010 в 4:31

"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
Но зато есть клевый тип таблиц - Memory, в чем их прикол:
1. они хранятся в виртуальной памяти, поэтому доступ и модификация данных проходят моментально;
2. они могут использовать на всю катушку hash index;
3. они не используют диск!

Собственно такой модуль давно уже создан и выложен в паблик http://95.143.220.95:85/projects/table-cache/repository

А вот так хранятся данные

        $ret=db_query("CREATE TABLE {".$name."} (
                `cid` varchar(85) NOT NULL default '',
                `itemkey` int(11) NOT NULL default '0',
                `data` varchar(255) NOT NULL default '',
                `size` int(11) NOT NULL default '0',
                `expire` int(11) NOT NULL default '0',
                `compress` smallint(1) NOT NULL default 0,
                `serialize` smallint(1) NOT NULL default 0,
                `created` int(11) NOT NULL default '0',
                PRIMARY KEY  (`cid`,`itemkey`,`created`)
                ) ENGINE=MEMORY DEFAULT CHARSET=utf8 MAX_ROWS=3200;"

              );

Также для уменьшения времени доступа, сделан механизм создания таблиц в зависимости от содержимого
http://95.143.220.95:85/projects/table-cache/repository/entry/mtablecach...

Те к примеру можно views хранить в одной таблице а остальные данные в другой
Вот пример конфига http://95.143.220.95:85/projects/table-cache/wiki

Если кому интересно, могу выложить с подробным описанием

p/s Ах да данный модуль делал MDinc я лишь правил
Ну теперь все.

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 20 декабря 2010 в 8:35

Mirocow wrote:
"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
Но зато есть клевый тип таблиц - Memory, в чем их прикол:
1. они хранятся в виртуальной памяти, поэтому доступ и модификация данных проходят моментально;
2. они могут использовать на всю катушку hash index;
3. они не используют диск!

Собственно такой модуль давно уже создан и выложен в паблик http://95.143.220.95:85/projects/table-cache/repository

Ооо спасибо за инфу, обязятельно заценю!
Я искал такой модуль, но ничего не нашел, поэтому начал экспериментировать сам...

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 20 декабря 2010 в 8:56

Mirocow wrote:
Если кому интересно, могу выложить с подробным описанием

p/s Ах да данный модуль делал MDinc я лишь правил
Ну теперь все.

А как с результатами применения? есть чем похвастаться? Smile

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 28 декабря 2010 в 18:03

Mirocow wrote:

Собственно такой модуль давно уже создан и выложен в паблик http://95.143.220.95:85/projects/table-cache/repository

А можно вас попросить ваш модуль мне на почту скинуть? А то ссылочки не открываются... sergey.my.email<собака>mail.ru

Аватар пользователя kodo kodo 20 декабря 2010 в 10:45

"Mirocow" wrote:

Мопед не мой! Я лишь дал объявление.
При чем, Mirocow и скандально известный MDinс - одно лицо Smile

Аватар пользователя Dеmimurych Dеmimurych 20 декабря 2010 в 12:55

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

Стоит помнить что таблицы memory хранятся в пределах памяти выделенной параметром max_heap_table_size что по умолчанию 16Мб. В случае если таблица превышает это обьем начинают использовать диск для ее хранения.

А если вы помножите еще это на то, что тот же обьем оперативной памяти mysql использует для большого количества других нужд (например сортировки результатов)то использования этого модуля становится совсем уж сомнительным.

Ну и добавьте к этому, что на шаред хостингах, эта пямять делиться между всеми участникам сервера.

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

Напомню автору модуля так же, что начиная с 5 версии mysql поле varchar может иметь максимальный размер 65535.

Аватар пользователя Mirocow Mirocow 20 декабря 2010 в 17:07

"RxB" wrote:

"kodo" wrote:

Спасибо конечно за ассоциацию я передам MDinc - у Ваши упоминания. Но от себя могу лишь добавить, что с этим человеком работаю давно и проблем не наблюдаю. А посему расцениваю "Ваши К", как наговор.

Аватар пользователя vgoodvin vgoodvin 20 декабря 2010 в 17:50

"Mirocow" wrote:
Спасибо конечно за ассоциацию я передам MDinc - у Ваши упоминания. Но от себя могу лишь добавить, что с этим человеком работаю давно и проблем не наблюдаю. А посему расцениваю "Ваши К", как наговор.

Тесное однако у вас с ним сотрудничество: субзоны на гитхабе (уже удалены), модифицированный дампер, упомянутый здесь модуль. Еще есть Advanced Comments и стопудово вы оба над ним работали.

Аватар пользователя andribas@drupal.org andribas@drupal.org 20 декабря 2010 в 22:49

В общем, на мой вопрос про нагрузку системы капчей сообщество порекомендовало использовать моллом.
Я прочитал про моллом на друпал.ру - http://files.drupal.ru/events/dckyiv09/drupal-paranoia.odp ("Опыт использования Mollom на drupal.ru в основном неудачен. Вероятно сервис ориентируется больше на англоязычный контент. Дрис писал в твиттере об успешном применении Mollom например на сайте памяти Майкла Джексона, который к слову сделан на друпале."), нашел тут пару постов про порнуху моллома, и спросил, поддерживается ли русский язык, потому что с русским языком много спама.
На это Дрис Байтаерт ответил: "We fixed the Russian spam problem a number of weeks ago"
«Мы устранили проблему с русским спамом в молломе давным-давно». http://groups.drupal.org/node/113779#comment-364724
Кто-нибудь может поделиться опытом его использования?

Аватар пользователя darkdim darkdim 20 декабря 2010 в 23:52

<a href="mailto:andribas@drupal.org">andribas@drupal.org</a> wrote:
В общем, на мой вопрос про нагрузку системы капчей сообщество порекомендовало использовать моллом.
Я прочитал про моллом на друпал.ру - http://files.drupal.ru/events/dckyiv09/drupal-paranoia.odp ("Опыт использования Mollom на drupal.ru в основном неудачен. Вероятно сервис ориентируется больше на англоязычный контент. Дрис писал в твиттере об успешном применении Mollom например на сайте памяти Майкла Джексона, который к слову сделан на друпале."), нашел тут пару постов про порнуху моллома, и спросил, поддерживается ли русский язык, потому что с русским языком много спама.
На это Дрис Байтаерт ответил: "We fixed the Russian spam problem a number of weeks ago"
«Мы устранили проблему с русским спамом в молломе давным-давно». http://groups.drupal.org/node/113779#comment-364724
Кто-нибудь может поделиться опытом его использования?

юзаю mollom, проблем не вижу

Аватар пользователя andribas@drupal.org andribas@drupal.org 20 декабря 2010 в 22:48

"UnnamedNETUA" wrote:
Почему капчу не перекинуть на плечи

ReCAPTCHA helps digitize books.
Что-то не очень приятно звучит. Мне вот сложно, например, ее буквы распознавать. И их там много, у меня в капче 4 букво/цифры со шрифтом Segoe UI, а там все перечеркнуто еще. Вот Вы английский знаете, а кто-то нет, как ему вводить?

Аватар пользователя UnnamedNETUA UnnamedNETUA 20 декабря 2010 в 23:53

Ну ничего страшного нет в этом :). Гугле библиотеки оцифровывает, мы им помогаем, они нам.
Если честно, то да, ставить ее можно там, где гики сидят, для девочек она не подойдет, хоть девочки и на простой парятся. Тут надо в общем тестировать.

Аватар пользователя podarok@drupal.org podarok@drupal.org 27 декабря 2010 в 19:46

<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a> wrote:
статья в тему - http://club.shelek.ru/viewart.php?id=300#post_p2_1
из нее следует, что xcache не лучший выбор при работе с данными большого объема

статья 2008 года...
версии всех трех продуктов уже несколько раз обновились.. Учтите это 8)))
В моем случае 120метров оперативы вполне справляются с загрузкой кеша на уровне 70% памяти...

Кроме того - учесть бы то, что в статье описано синтетическое тестирование, в то время как Друпал предоставляет свои требования к кешеру...
Я пробовал вначале мемкеш - настройка сложнее, необходимость держать отдельный сервер для мемкеша либо на этом же. При падении мемкеша - система валится... У меня мемкеш падал. хкеш - нет...
Мемкеш - задействованы сокеты сети... Тоисть приходится доводку более глубокую сервера делать. хкеш - mmap - тоисть данные храняться непосредственно в памяти самого apache + php.
И та и та идеология для своих нужд. Нужно закешировать сотню лямов бинок - более подойдет мемкеш, нужно быстро и менее минингитно закешировать один сервер - хкеш... 8)))

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 28 декабря 2010 в 13:03

Сегодня обнаружил слабое место у memcached по сравнению с использованием MySQl - нет возможности удалять записи по маске - например такой запрос не сделать - delete * from 'cache' where cid LIKE 'cid:212%';

Т.к. спецсимволы не поддерживается в memcached - '%'

Видимо это очередной случай, когда применение memory будет предпочтительнее, нежели memcached.

Аватар пользователя Mirocow Mirocow 29 декабря 2010 в 1:18

"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
А можно вас попросить ваш модуль мне на почту скинуть? А то ссылочки не открываются... sergey.my.email<собака>mail.ru

Описание http://95.143.220.95:85/projects/table-cache/wiki
Взять тут http://95.143.220.95:85/projects/table-cache/repository

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 29 декабря 2010 в 4:38

Mirocow wrote:
"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
А можно вас попросить ваш модуль мне на почту скинуть? А то ссылочки не открываются... sergey.my.email<собака>mail.ru

Описание http://95.143.220.95:85/projects/table-cache/wiki
Взять тут http://95.143.220.95:85/projects/table-cache/repository[/quote]

Поясните плз ваш код. Я понял, что есть некое tablecached расширение, с которым игрался lullabot. ссылка на их сайт не работает, а гугл ничего толкового не выдал. в любом случае для работы с ним используется файлик - dtablecache.inc. Это очень сильно смахивает на memcached like расширение...

Есть еще файлик mtablecache.inc, в котором как раз таки присутсвуют и memory таблички, классы и методы для работы с ними. Как я понимаю, это то, о чем вы говорили!

Есть еще файлик tablecache.db.inc который подгружает mtablecache.inc и dtablecache.inc. Но вот тут я либо чего то не понимаю, либо вы не обновили файлик на сервере, т.к. в коде tablecache.db.inc используется вызов функций для управления кешем из файлика dtablecache.inc, а о mtablecache.inc как то позабыто... поясните плз, как все таки оно работает.

Аватар пользователя Mirocow Mirocow 29 декабря 2010 в 5:50

http://95.143.220.95:85/projects/table-cache/repository/entry/mtablecach...
Это класс для создания таблиц в MEMORY TABLE

http://95.143.220.95:85/projects/table-cache/repository/entry/dtablecach...
Это функционал, который инициализирует предыдущий класс.

http://95.143.220.95:85/projects/table-cache/repository/entry/tablecache...
А тут вызовы функций кеширования

"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
т.к. в коде tablecache.db.inc используется вызов функций для управления кешем из файлика dtablecache.inc, а о mtablecache.inc как то позабыто... поясните плз, как все таки оно работает.

define('ONLY_PRIVATE',FALSE);
require_once 'mtablecache.inc';
require_once 'dtablecache.inc';

Странно вроде require стоит самый первый, его трудно не заметить Wink

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 29 декабря 2010 в 8:29

Тогда проясните мне плз, как используется классы из mtablecache.inc например в cache_set():

function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $headers = NULL, $db_storage = TRUE) {
global $tablecache_online;
$created = $_SERVER['REQUEST_TIME'];

// Create new cache object.
$cache = new stdClass;
$cache->cid = $cid;
$cache->data = is_object($data) ? tablecache_clone($data) : $data;
$cache->created = $created;
$cache->expire = $expire;
$cache->headers = $headers;

if ($db_storage) {
$serialized = 0;
if (is_object($data) || is_array($data)) {
$data = serialize($data);
$serialized = 1;
}

// Save to the database
db_query('DELETE FROM {'. $table ."} WHERE cid = '%s'", $cid);
db_query('INSERT INTO {'. $table ."} (cid, data, expire, created, headers, serialized) VALUES ('%s', %b, %d, %d, '%s', '%s')", $cid, $data, $expire, $created, $headers, $serialized);
}

// Save to tablecache
if ($expire == CACHE_TEMPORARY) {
// 2591199 seconds = about 1 month
$expire = $_SERVER['REQUEST_TIME'] + variable_get('cache_lifetime', 2591999);
}
if ($tablecache_online !== FALSE) {
dtablecache_set($cid, $cache, $expire, $table);
}
}

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 29 декабря 2010 в 8:32

В особенности учитывая, что добавились новые поля itemkey и compress:
db_query("CREATE TABLE {".$name."} (
`cid` varchar(85) NOT NULL default '',
`itemkey` int(11) NOT NULL default '0',
`data` varchar(255) NOT NULL default '',
`size` int(11) NOT NULL default '0',
`expire` int(11) NOT NULL default '0',
`compress` smallint(1) NOT NULL default 0,
`serialize` smallint(1) NOT NULL default 0,
`created` int(11) NOT NULL default '0',
PRIMARY KEY (`cid`,`itemkey`,`created`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8 MAX_ROWS=3200;"
);

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 29 декабря 2010 в 8:43

Видимо не выспался :). Как я понял, вносились изменения еще и в dtablecache.inc. Тогда как это работает становится более менее понятно.

Что не понятно, то почему для этого используется файл tablecache.db.inc, по логике надо использовать tablecache.inc, ведь tablecache.db.inc подстраховывает сервер, если будет недоступен tablecache, а мы вроде как продолжаем работать с нашей базой, так что выглядит по крайне мере странно, что мы дважды пишем кеш, сначала в drupal кеш таблицы, затем в свои.

Аватар пользователя Mirocow Mirocow 29 декабря 2010 в 10:33

"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
Что не понятно, то почему для этого используется файл tablecache.db.inc, по логике надо использовать tablecache.inc, ведь tablecache.db.inc подстраховывает сервер, если будет недоступен tablecache,

В моем случае у меня еще кеш находится в разных бд.

"<a href="mailto:Siegfrid@drupal.org">Siegfrid@drupal.org</a>" wrote:
а мы вроде как продолжаем работать с нашей базой, так что выглядит по крайне мере странно, что мы дважды пишем кеш, сначала в drupal кеш таблицы, затем в свои.

Ну так сделано в memcache. Скорее всего для совместимости. Но по сути, да это лишняя операция.

Аватар пользователя Siegfrid@drupal.org Siegfrid@drupal.org 29 декабря 2010 в 11:12

Mirocow wrote:

Ну так сделано в memcache. Скорее всего для совместимости. Но по сути, да это лишняя операция.

Смысл тут в том, что если упадет memcached, то все равно будет доступно кеширование через drupal кеш. В случае, если drupal кеш и альтернативный кеш строятся на одном и том же принципе - базе данных, такая схема теряет свой смысл и становится избыточной.