Здравствуйте!
Напишу сюда результат анализа лога 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 /
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
Запрос:
3. xmlsitemap - я так понимаю, это запрос по крону на добавление новых нод в сайтмап - ПОЛНЫЙ СКАН
Количество запросов: 368
Общее время: 436, в среднем: 1.18
Количество строк: 171575 - 172750
Запрос:
4. Снова xmlsitemap - выдача "подкарты" сайта - это даже хуже, чем полный скан
Количество запросов: 459
Общее время: 326, в среднем: 0.71
Количество строк: 134500 - 344905
Запрос:
5. url_alias - снова xmlsitemap ?
Количество запросов: 388
Общее время: 210, в среднем: 0.54
Количество строк: 171762 - 345745
Запрос:
Остальные запросы не такие затратные, или их мало.
Итого, самый "трудный" запрос является запрос views - материал: новость, опубликован, рубрика = 10, 3 последних - самая большая нагрузка - 19078 секунд - это больше 5 часов из 15 дней полной работы
Следующим запросом идет облако тегов по словарю - 936 секунд, а словарь еще до конца не заполнен.
И последние запросы относятся к xmlsitemap.
Получается, самые дорогие запросы делает модуль views при выборке из словаря с сортировкой по дате, модуль tagadelic при составлении облака тегов и xmlsitemap.
Самым "болезненным" запросом для моего сайта получается все-таки views, о том, что с ним можно сделать хотел бы услышать Ваши комментарии, с остальным вроде более-менее понятно, с tagadelic и xmlsitemap я пока готов смириться.
Комментарии
Вот это мне нравится, а не как прошлый топик про тяжёлые модули "Пишите! Я считаю что токен и pathauto"
По таксономии, я уже писал кому-то в посте, создайте руками в базе в таблице term_node индекс по tid и по паре tid, nid вы будете очень приятно удивлены результатом даже для вьюсов.
Написать про этот косяк статейку все руки не доходят.
(Дружно хором): Про-сим-Про-сим...
посмотрел (SHOW INDEXES FROM term_node) эту таблицу у себя
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
Индексы вроде есть - или я что то не понимаю - специально их не создавал.
ООООО Спасибо, человечище!!!! За 3 месяца первый топик, который не спам типа "помогите".
В закладки, однозначно)))
Действительно, после запроса
ALTER TABLE term_node ADD INDEX tid (tid)
с модулем tagadelic проблем не стало,
но для views это не помогло.
Насчет индекса tid,nid не совсем понял - вроде join везде делается по vid, как это может помочь?
Отвечу как Паниковский, вы не спрашивайте а сделайте (Этот как риторический вопрос: "Чем программист отличается от философа?"). Потому что не везде join делается по vid.
В случае с вашим запросом видимо в тормоза сваливается INNER JOIN-ом попробуйте если не сделали индексом пару tid,nid все же сделать и проверьте, у меня во всяком случае после этих дел форум стал работать быстрее в 10!!! раз.
Вообще было бы интересно поковыряться с вашим запросом при большом количестве строк в таблице и найти истинную а не предполагаемую причину тормоза, поскольку в том что проблема в SQL запросе я не сомневаюсь.
Я бы просто погонял этот запрос без разных условий в самом SQL, к примеру начал бы без сортировки, потом с условиями поигрался, потом с JOIN и т.д.
Осталось только найти решение, как поместить таблицы node_counter и sessions в кеш - CacheRouter или другой, потому как они наиболее затратные.
спасибо, так и попробую сделать, что получилось напишу.
Для сессий попробуйте модуль no_anon
Очень интересно, спасибо за познавательный анализ!
Даже не подозревал что механизм сессий капчи столько ресурсов занимают.
Поддержка кэширования sessions есть в memcache (у меня, правда, при помещении сессий в мемкэш не получается залогиниться).
подпишусь
а тип таблиц какой? InnoDb или MyISAM?
Я проводил эксперименты с Memmory и таблицами кеширования , но результаты были не ахти, поэтому я пока что отложил это до лучших времен. Но memmory как раз таки и позволяют существенно снизить нагрузку при обновлении данных!
С каптчей на комментариях для гостей есть еще проблема из области производительности: нельзя закешировать страницы node/* в статику, потому что у всех желающих прокомментировать будут появляться ошибки.
Кому-нибудь попадалось решение? Решает ли эту проблему модуль ajax_comments хотя бы для пользователей с включенным js? Может быть есть вариант обслуживать сессию каптчи и грузить токены формы комментариев аяксом?
Суперский анализ
Благодарю, в мемориз однозначно.
Увы, это не совсем так.
Во-первых, ни apache, ни mysql не используют syslog для логирования.
Во вторых, syslogd при записи каждой строки в лог выполняет вызов fsync() для синхронизации буфера на диск поэтому выгода от его использования для высоконагруженных сайтов не так очевидна.
Почитал про проблему pagination на сайтах mysql. Интересное решение предлагает Петр Зайцев (а также в комментах) на http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performanc...
Вот оригинальный запрос views:
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:
rows: 20103 означает, что при данном запросе будет сделана ВСЯ выборка из таблицы node, которые принадлежат к данному термину, потом результат будет записан во временный файл, отсортирован и после этого отдан клиенту. Так решил оптимизатор mysql - он перевернул порядок таблиц и первую выборку делает по term_node.
Вот что получится, если принудительно заставить таблицу использовать индекс node_created (создан по умолчанию):
Как видим, в этом случае будет выбрано РОВНО 3 строки - никаких сканов, filesort-ов.
Кстати, вот что об этом написано в документации mysql: http://dev.mysql.com/doc/refman/5.1/en/limit-optimization.html
Если сортировка результата (order by) выполнена с использованием index, то отдаются первые limit найденные строки, и это очень быстро. Если же выполняется filesort, то проверяются все строки.
Вот результат выполнения запросов к базе, используя оригинал и измененный (force index), в зависимости от количества нод с этим термином:
График не рисовал, но понятно, что оригинальный запрос хорош для небольших рубрик, там, где кол-во нод с одинаковым термином превышает 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
В общем, из 19к запросов в slow_query.log при таких настройках
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 уже сделаны:
2 - ALTER TABLE captcha_sessions ADD INDEX TIMESTAMP ( TIMESTAMP );
3 - ALTER TABLE term_node ADD INDEX tid (tid);
1 - используется, если Вы выводите комментарии в плоском виде
2 - если не добавить, то операция удаления раз в сутки кроном будет долгой
3 - для модуля tagadelic
Здесь пишут, что вроде как для таких сайтов и сделали этот модуль - http://drupal.org/handbook/modules/syslog
Вторая альтернатива - отключить лог. Я, пожалуй, попробую переключить на syslog и посмотрю, что получилось.
Модуль статистики? Откройте для себя https://www.google.com/analytics
Упустил, это да..
Из моих изысканий на данную тему (Все нижеизложенное относится к 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 команды для создания модифицированных кеш таблиц.
В чем плюс от таких изысканий - кеш должен стать поистине космически шустрым...
Буду рад за участие и дельные советы!
Разгребусь с переносом друпалера на 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 я не знаю, т.к. для поиска того же кеша придется шестрить все созданные кеш таблицы...
Сжатие кеша точно умедляет работу, я проверял на xcache + gzip
По сегментации - очень здравая мысль, но определенно нужно перехватывать алгоритм cache_bins и разделять отправку елементов в соответствующе сегментированные хранилища.
Здесь правда появится елемент поиска хранилища уже на стадии запроса и это тема для разговора и обдумывания... Не уверен, что есть смысл париться - проще на сервер докупить +4 гига оперативки... Тем более, что анализируя статистику размеров елементов кеша - они есть от пары байт до почти мегабайта(bin localize, bin menu)
А сжимали с каким качеством? Если использовать максимально быстрое сжатие только для больших данных, которые например не влезут в 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 пользователей (Это трафик сайтов с лямом пользователей) Друпал вполне за секунду сгенерит страницу и отдаст ее дальше только из кеша...
Кстати о птичках, а почему бы не добавить еще одну табличку, типа cache_saved, в который мы бы как раз и хранили информацию в какую таблицу и какие данные мы положили...
Да и еще, для разной длины данных можно использовать разную степень сжатия, а именно, если у нам надо сжать 64k, то проще будет использовать быстрое сжатие, а если 640k, то можно и самое эффективное, тогда для небольших данных мы будем сжимать быстро и они все равно влезут в свои 32k - 42k, а для больших будем использовать самое эффективное, чтобы рационально использовать место в памяти...
Ну и выигрыш - если кешировать раз в пять минут, то скорее всего соотношение загрузка проца/время генерации и вся оперативка/оперативка под кеш будут достаточно неплохо смотреться на общем фоне.
В общем надо будет поиграться с этим...
Да, это реально, но сегментирование додает хопы для доступа к кешу
Поиск данных становится более медленным и скорее всего это будет еффективным при authcache + 10K+ пользователей именно зарегестрированных. (опять же нужно тестирование и нагрузка тем же апачбенчем с соответствующими куками)
Сама система кеширования уже на словах усложняется. Вполне возможно что разширение вширь даст более приемлемые результаты. К примеру установка в 2U сервер несколько MiniITX нод(150$ каждая, 4-8 гиг оперативы) кластером memcache с балансировкой нагрузки по нодам memcache тем же haproxy позволит без лишнего кодирования добиться хранения данных в зависимости от размера бинок кеша на разных нодах, оптимизированых под разные нужды + добавит устойчивость от падений.
Три ноды + балансер потянут на тыщу баксов(для проэкта с такими нагрузками это не деньги) и смогут обслужить очень много запросов.
>> К примеру установка в 2U сервер несколько MiniITX нод
Был опыт? Есть ли на эту тему руководства или готовые решения, чтоб потом с таким сервером в датацентре в кружок юных техников не отослали )
пока тестирование проводил только с виртуальными машинками...
но двигаюсь в эту сторону... Под MiniITX кластеры даже есть уже созданные корпуса...
полезный материал
Спасибо! субскрибе ... p.s.: капча -- это жесть
Во вьюсах структуру запроса можно поменять с помощью хука
http://drupalcontrib.org/api/function/hook_views_query_alter/6
Вообще понять бы что курит Мерлин (откуда у человека столько энергии), когда ваяет модули типа вьюсов, цтулс и панелей ;), от бы где развернулись.
InnoDB тоже можно перевести в память, будет ли при этом запись на диск не знаю. Почитайте про HandlerSocketPlugin для мускуля, он для кеша судя по всему то что надо и на php уже враппер есть.
В том то и дело, что InnoDb пишет в память, при чем как минимум раз в секунду. А каждое обращение к диску - это тормоза. Ну и главное - зачем нам писать кеш на диск? Кеш на то и кеш, чтобы его хранить в памяти, да и он не очень то нужен после перезагрузки/восстановления системы, так что ему прямая дорога в memmory!
осталось только понять, где в моих изысканиях косяк, я подозреваю, что в нарезке / форматировании данных, т.к. периодически переменная variables начинала глючить и писала какую то хрень в качестве последней порции из нарезки данных. Я грешу на то, что надо было делать перекодировку в bibary формат, а не пихать string, но точнее не исследовал...
Сегодня выложу наработки + создам новый пост, кому будет интересно, вливайтесь.
вот возник вопрос. думаю analytics у вас стоит, пройдитесь по ссылкам, кликают ли по этим самым читаемым материалам?
Спасибо за статью. Как раз на эту тему:
http://buytaert.net/playing-with-new-relic-on-acquia-hosting
До того, как написать этот пост, о чем я написал в самом начале - у меня был настроен CacheRouter на использование хранилища в БД - при этом за сутки в bin лог mysql сваливалось около гигабайта (изменений информации) - даже если использовать таблицы в памяти - не знаю, насколько это будет эффективно, будет ли информация из этих таблиц попадать в кеш mysql? если да, то она будет вытеснять оттуда остальные "полезные" сохраненные запросы. Ну и самое главное - чем Вам не нравится CacheRouter + memcached? он уже написан и готов к употреблению, чем Ваш подход лучше / эффективней? Там точно также реализовано хранение всех таблиц cache_ в памяти. Ну или если Вы твердо уверены, что таблицы в памяти mysql быстрее, может проще будет добавить Ваше хранилище в CacheRouter - там вроде аккуратно все сделано?
Из того, что указано на скриншоте - accesslog у меня выключен, весь кеш не попадает в БД (используется хранилище memcached) - а капчи и считалки там видимо нет. Первое, что необходимо сделать - это кеш убрать из БД, я уже это сделал, теперь смотрю, что осталось - получается, что sessions очень хороший кандидат на кеширование.
SELECT url_alias у меня не всплывал в логе, может запросов и много, но быстрые - а, возможно, это обнаружится при следующем рассмотрении, спасибо.
Спасибо, посмотрю.
Надо почитать про это поподробнее будет. Но я не раз слышал, что после активации этой связки начинались танцы с бубнами в других модулях, но почитать про это поподробнее все таки стоит
Я поставил себе модуль 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.
подписался
Напиши. Как получиться, хоть ногами, главное напиши!
Полезная, но жрущая. Лучше искать сторонние решения.
Их отключать однозначно. Если сервер свой, то попробуй заюзать syslog.
Или переписать руками или hook_query_alter.
Может грузить её аяксом, без перехода на другую страницу?
Вот это я не совсем понял. Пишет в память но причем здесь диск?
Для кеша более важна скорость чтения - хвалят HSplugin, бенчмарки дают скорость выше чем memcached и к тому же остается доступ через обычный SQL
Для статистики важна скорость записи - хвалят MongoDB (особенно capped collections)
Кто-нибудь пробовал что-то из вышеперечисленного?
Я не правильно выразился, пишет на диск. Она ведь поддерживает транзакции, вот и приходится обновлять логи и синхронизировать данные...
MongoDB вообще другая тема, люди пробовали плагин для работы с ним, говорят даже не ставиться друпал на него.
Было бы интересно, если ТС бы поставил MariaDB, прозрачная замена с супер скоростью и отписал результат работы, сравнение по скорости до и после.
А данные синхронизирует при каждой транзакции?
Есть такой. Не ставится и нет необходимости держать весь друпал на монге ибо это повлечет проблемы.
Можно использовать монго только для записи статистики и каких-либо логов. Плагин не обязателен, можно работать напрямую а иногда даже необходимо.
Слава богу нет. есть настройка, которая позволяет управлять, как синхронизировать данные. Нол смысл все равно в том, что юзается диск, а для кеша это как то глупо!
попробовал memcache - на локальной машинке завелось, понравилось, правда немного смущает, что если что то не то станется с демоном memcached, то могут быть большие проблемы с кешированием, а точнее его отсутствием... Но все равно, такой механизм есть и он работает, а это главное!
Я, вероятно, удивлю здесь присутствующих, но мы (it-patrol) добились снижения IO, именно перейдя на InnoDB
вопрос аффтору: почему Вы выбрали CacheRouter + memcached?
у мну почему-то эта связка не вызвала восторга((
Заранее благодарен за ответ!
CacheRouter использовал сразу, другие не смотрел.
В качестве хранилища первоначально использовал APC, но там нет LRU, и память быстро кончалась.
потом мне подсказали на этом сайте (Crea), что у memcached LRU есть - поэтому не вижу ему альтернативы.
К сожалению, на drupal.org все рассуждения и feature requests сводятся к тому, что юзайте платный mollom Дриса Байерта. Выше человек указал его пост о нагрузке отдельных модулей. Удивлен, что он не постебался и про капчу не стал писать - что какая она есть - полный отстой, юзайте моллом.
А как это можно сделать? Сейчас стоит ajax_comments, он может только "раскрывать" форму, подгружать не умеет, других модулей тоже не нашел - по идее, хорошо бы весь comment_form грузить отдельно, потому что он кеш тоже засирает прилично, а комменты пишут далеко не все.
А если сделать на отдельной странице форму комментариев, то в ajax_comments смысла нет.
Так что Ваша идея намного лучше - подгружать целиком всю форму комментов, для этого есть готовое решение?
AJAX module это умеет?
Я читал в блоге разработчика плагина, там первое, что делается - это все данные в память грузятся (там где 750к/сек запросов), еще тестировали с SSD, и как преимущество они описывают именно разделение кеша запросов с mysql. В его схеме memcached используется для хранения выполненных запросов, причем запросов простых, а в случае с друпалом memcached используется для хранения более сложных данных - блоки, формы, страницы и т.д. - собранные из 200-300 запросов. Если же весь кеш друпала сделать доступным через Handler Socket Plugin, то кеш запросов mysql будет бесполезным, разве не так? Вряд ли это будет лучше, чем memcached.
не совсем Вас понял, причем здесь кеш запросов? http://l-o-n-g.livejournal.com/153756.html
По поводу капчи, значит надо делать простую регистрацию и постить только зарегеным...
"Когда HandlerSocket обращается к хранилищу InnoDB, запись будет закеширована только буфере, и будет доступна для использования другими SQL запросами."
весь кеш друпал будет в кеше mysql.
Там вообще основная идея не кеширование, а быстрое получение результата запроса вида «SELECT user_name, user_email, created FROM user WHERE user_id=?» - это решение отлично подходит для url_alias, т.к. запросы будут миновать SQL layer, но там не рассматривается ведение кеша (именно его искусственное создание) в mysql.
Да, респект ТС. Действительно есть над чем подумать.
Я не делал, но пишут, что могёт.
С капчей у него проблемы - с нынешней версией несовместимо. Сейчас в модуле капча стоит приоритет на него "критический" уже давным-давно http://drupal.org/node/334377, другие спрашивают умрет ли AJAX в D7.
И я так и не понял, может ли он загружать форму? из того, что о нем прочитал, понял только, что он может проверить, средиректить и т.д., но не загрузить. Поставил, так оно и есть, как загрузить не понял.
Из коробки работает Dialog API, там как раз делать ничего не надо, только включить модуль и по ссылке добавить комментарий будет открываться модальное окно. Попробую его использовать.
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. Статистика считалка - есть три подхода:
6. Сессии - поставил вместо CacheRouter Memcache, сейчас для тестирования завел на каждую таблицу кеша отдельный memcached 16Mb и поставил собирать cacti - всего получилось 12 таблиц вместе с sessions,users. Читал о каких-то проблемах memcache с загрузкой фото и другими формами - сегодня потестирую, также читал рекомендации именно для форм использовать cacherouter.
7. Лог отправил в syslog. Настройки для syslog-ng такие:
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 кеширование выключено.
У меня запрос
FROM `blocks`
WHERE theme = 'mytheme'
AND STATUS =1
LIMIT 0 , 100
показал, что почти ничего не кешируется, кроме системных блоков и блоков сторонних модулей.
В общем, осталось только статистику просмотров node_counter собирать по другому. А Вы как это делаете?
Никакого отношения к кешам и прочему не имеет.
Исследователь заметил, что при совершении громадного количества запросов к mysql серверу по типу ключ знание, основные нак5ладные расходы это не сама выборка данных, а разбор запроса самим сервером. Его анализ, оптимизация, и уже потом выборка данных.
Имеено эту проблему и решает это плагин. Доводя производительность мйскль до уровня NoSql решений. В случае ДРУПАЛА, это плагин мог бы дать резкий скачек в производительности, именно из за большого количества мелких запросов типа ключ значение.
По поводу большого коллективиста insert ov.
Переведите таблицы на InnodDB и в mysql поставьте настройку innodb_flush_log_at_trx_commit=0
что даст указание серверу сбрасывать на диск данный раз в секунду. А не сразу после запроса.
Это кончено опасно тем, что при падении сервера вы можете потерять данные за последнюю секунду. Но вы сразу ощутите как стало легче жить
Общие правила по переходу на innodb таковы, вы получите заметный прирост в производительности в случает если у вас ведется активная работа на запись в таблицы.
НЕ используем виевс. Это конечно холивар. И у Виевс есть серьезный аргумент - в виде простоты поддержки проекта. Но и такой же серьезный контраргумент. Сложности с производительностью на высоконагруженных проектах.
Далее. правильная работа с мемкешем. В случае если основное количество нагрузки у вас это просмотр материала, то при правильной настройке memcesha в связке с друпал кешем, вы должны получать НОЛЬ запросов на просмотр кешированной страницы.
Собственно такой модуль давно уже создан и выложен в паблик http://95.143.220.95:85/projects/table-cache/repository
А вот так хранятся данные
`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 я лишь правил
Ну теперь все.
Ооо спасибо за инфу, обязятельно заценю!
Я искал такой модуль, но ничего не нашел, поэтому начал экспериментировать сам...
А как с результатами применения? есть чем похвастаться?
А можно вас попросить ваш модуль мне на почту скинуть? А то ссылочки не открываются... sergey.my.email<собака>mail.ru
Дима, у тебя опять раздвоение личности?
бгг.
Мопед не мой! Я лишь дал объявление.
При чем, Mirocow и скандально известный MDinс - одно лицо
по поводу модуля с таблицами memory
беглый просмотр сразу дал понять, что этот модуль может не только помогать но и сильно вредить.
Стоит помнить что таблицы memory хранятся в пределах памяти выделенной параметром max_heap_table_size что по умолчанию 16Мб. В случае если таблица превышает это обьем начинают использовать диск для ее хранения.
А если вы помножите еще это на то, что тот же обьем оперативной памяти mysql использует для большого количества других нужд (например сортировки результатов)то использования этого модуля становится совсем уж сомнительным.
Ну и добавьте к этому, что на шаред хостингах, эта пямять делиться между всеми участникам сервера.
Впрочем для маленьких сайтов с небольшим количеством данных модуль может быть полезен.
Напомню автору модуля так же, что начиная с 5 версии mysql поле varchar может иметь максимальный размер 65535.
Спасибо конечно за ассоциацию я передам MDinc - у Ваши упоминания. Но от себя могу лишь добавить, что с этим человеком работаю давно и проблем не наблюдаю. А посему расцениваю "Ваши К", как наговор.
Тесное однако у вас с ним сотрудничество: субзоны на гитхабе (уже удалены), модифицированный дампер, упомянутый здесь модуль. Еще есть Advanced Comments и стопудово вы оба над ним работали.
Ты сборник лулзов, ей богу.
В общем, на мой вопрос про нагрузку системы капчей сообщество порекомендовало использовать моллом.
Я прочитал про моллом на друпал.ру - 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, проблем не вижу
Почему капчу не перекинуть на плечи http://drupal.org/project/recaptcha?
Тем более что ее народ знает, и она сейчас гуглевская, так что стабильная штука.
ReCAPTCHA helps digitize books.
Что-то не очень приятно звучит. Мне вот сложно, например, ее буквы распознавать. И их там много, у меня в капче 4 букво/цифры со шрифтом Segoe UI, а там все перечеркнуто еще. Вот Вы английский знаете, а кто-то нет, как ему вводить?
Ну ничего страшного нет в этом :). Гугле библиотеки оцифровывает, мы им помогаем, они нам.
Если честно, то да, ставить ее можно там, где гики сидят, для девочек она не подойдет, хоть девочки и на простой парятся. Тут надо в общем тестировать.
Простите меня, но мне стало интересно, какой специфики у вас сайт, что без авторизации требуется писать?
Подписался
Мы сейчас везде ставим recaptcha.
тем более его пару дней на д7 портанули
В общем есть с чем поработать и над чем подумать
статья в тему - http://club.shelek.ru/viewart.php?id=300#post_p2_1
из нее следует, что xcache не лучший выбор при работе с данными большого объема
статья 2008 года...
версии всех трех продуктов уже несколько раз обновились.. Учтите это 8)))
В моем случае 120метров оперативы вполне справляются с загрузкой кеша на уровне 70% памяти...
Кроме того - учесть бы то, что в статье описано синтетическое тестирование, в то время как Друпал предоставляет свои требования к кешеру...
Я пробовал вначале мемкеш - настройка сложнее, необходимость держать отдельный сервер для мемкеша либо на этом же. При падении мемкеша - система валится... У меня мемкеш падал. хкеш - нет...
Мемкеш - задействованы сокеты сети... Тоисть приходится доводку более глубокую сервера делать. хкеш - mmap - тоисть данные храняться непосредственно в памяти самого apache + php.
И та и та идеология для своих нужд. Нужно закешировать сотню лямов бинок - более подойдет мемкеш, нужно быстро и менее минингитно закешировать один сервер - хкеш... 8)))
Спасибо! Буду читать и разбираться.
Сегодня обнаружил слабое место у memcached по сравнению с использованием MySQl - нет возможности удалять записи по маске - например такой запрос не сделать - delete * from 'cache' where cid LIKE 'cid:212%';
Т.к. спецсимволы не поддерживается в memcached - '%'
Видимо это очередной случай, когда применение memory будет предпочтительнее, нежели memcached.
http://www.idotpc.com/TheStore/pc/viewCategories.asp?idCategory=176
Описание http://95.143.220.95:85/projects/table-cache/wiki
Взять тут http://95.143.220.95:85/projects/table-cache/repository
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...
А тут вызовы функций кеширования
define('ONLY_PRIVATE',FALSE);
require_once 'mtablecache.inc';
require_once 'dtablecache.inc';
Странно вроде require стоит самый первый, его трудно не заметить
Тогда проясните мне плз, как используется классы из 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);
}
}
В особенности учитывая, что добавились новые поля 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;"
);
Видимо не выспался :). Как я понял, вносились изменения еще и в dtablecache.inc. Тогда как это работает становится более менее понятно.
Что не понятно, то почему для этого используется файл tablecache.db.inc, по логике надо использовать tablecache.inc, ведь tablecache.db.inc подстраховывает сервер, если будет недоступен tablecache, а мы вроде как продолжаем работать с нашей базой, так что выглядит по крайне мере странно, что мы дважды пишем кеш, сначала в drupal кеш таблицы, затем в свои.
В моем случае у меня еще кеш находится в разных бд.
Ну так сделано в memcache. Скорее всего для совместимости. Но по сути, да это лишняя операция.
Смысл тут в том, что если упадет memcached, то все равно будет доступно кеширование через drupal кеш. В случае, если drupal кеш и альтернативный кеш строятся на одном и том же принципе - базе данных, такая схема теряет свой смысл и становится избыточной.
Возможно расположение кеша на разных БД и разных серверах.
В этом топике говорится о парных индексах
Тогда каким образом можно создать парный индекс или как проверить не создан ли он?
Присоединяюсь к последнему вопросу. Так как создать парный индекс?
ALTER TABLE