Оптимизируемся. Часть 1, MySQL

Прислано: emzi

пт, 30/03/2007 - 15:49

Другие статьи по теме:

Очевидное преимущество друпала - гибкость, является одной из причин поначалу неявного, но в какой-то момент неприятно дающего о себе знать недостатка: его тормознутости.
Можно добавлять процессоры, наращивать гигагерцы и увеличивать оперативную память. Это американизированный подход с позиции грубой силы. Мне он нравится. Но еще больше мне нравится проявлять русскую смекалку, внедряя интенсивные (терапевтичесие - без хирургии на ядре!) методы оптимизации.
Хотя, по правде говоря, ничего смекалистого я пока не сделал, копаясь в интернете и выискивая чужие решения.

Ближе к делу. Первая задача интенсивного терапевта - привести в чувство СУБД.
Большинство используют сервер MySQL, и я не вижу смысла (разве что у Вас гигабайтные базы и сотни тысяч посетителей в день) рассматривать что-либо другое в роли адекватной альтернативы.

Для начала - сделаем пациенту экспресс-анализ кэша: в командной строке mysql набираем:
mysql> show variables like 'query%';
в результате полчаем примерно вот такую табличку:

| Variable_name                | Value     
| query_alloc_block_size       | 8192      
| query_cache_limit            | 33554432  
| query_cache_min_res_unit     | 4096      
| query_cache_size             | 134217728 
| query_cache_type             | ON        
| query_cache_wlock_invalidate | OFF       
| query_prealloc_size          | 8192      

в первую очередь нас интересуют query_cache_size и query_cache_type.
query_cache_size определяет собственно размер кэша, в котором хранятся результаты запросов. Если он равен 0, у вас ничего не кэшируется.
query_cache_type - режим работы кэша, должен быть ON. Может быть OFF или что-то еще, но нам нужен именно ON
Как определить, сколько памяти нам нужно выделить? Поскольку этот объем выделяется один раз и используется всеми процессами сервера (общая куча), то его можно сделать побольше. В то же время, если для кэша отдать слишком много памяти, то ее перстанет хватать для веб-сервера.
Эмпирически я оцениваю приблизительный размер кэша, от которого можно начинать плясать, в четверть имеющейся оперативной памяти, плюс-минус глядя по обстоятельствам.

Следующий, не столь критичный, но тоже весьма полезный параметр - query_cache_limit. Определяет максимальный размер кэшируемого запроса. Выбор его размера полностью зависит структуры запросов на вашем сервере. На что влияет этот параметр? Если сделать его слишком большим, то большие запросы начнут выдавливать все остальные запросы, эффективность кэша снизится, прирост производительности уменьшится или вообще исчезнет. Если сделать его слишком маленьким, то перестанет кэшироваться слишком много запросов, что тоже приведет к уменьшению производительности.

Вот тот необходимый минимум, который должен помнить интенсивный терапевт при диагностике MySQL'я у задыхающегося Друпала

Комментарии


Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Применить"
Опубликовано B.X в пт, 30/03/2007 - 23:40.

если есть свой (или арендованный) сервер... проблем с Друпалом, скорее всего не будет... настроить всё можно... другое дело, что делать, если настройки недоступны?


Опубликовано investor в сб, 31/03/2007 - 22:34.

Интересно, конечно, но никто не думает, как можно физически урезать кол-во запросов, допустим путем удаления ненужных функций?


Опубликовано B.X в сб, 31/03/2007 - 22:39.

думают... но именно гибкость и мешает...
Друпал не поставляется в обрезанном виде, только комплексное решение "для всех", а значит, если у кого-то мало ресурсов, то ему придётся Друпал ограничить самому...
а одного решения хватает максимум на одну версию, потому что Друпал постоянно меняется...


Опубликовано investor в сб, 31/03/2007 - 23:07.

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


Опубликовано blackvl@drupal.org в вс, 01/04/2007 - 05:42.

В любом случае хотелось бы посмотреть ваш my.cnf


Опубликовано Valeratal в вс, 01/04/2007 - 20:50.

эмм, а можно точнее сам текст запроса, а то он (текст запроса) немного отформатировался в сообщении


Опубликовано investor в пн, 02/04/2007 - 01:16.

show variables like 'query%';


Опубликовано emzi в пн, 02/04/2007 - 06:20.

1. если нет возможности что-то сделать (на хостинге), то по крайней мере можно провести диагностику и сделать предположения о возможных причинах медленной работы. К счастью, хостингов у нас много, есть из чего выбрать.
2. "уменьшить количество запросов" - можно, я на эту тему тоже хочу сделать статеечку. К сожалению, проблема, на мой взгляд, не в универсальности, проблема носит системный характер.


Опубликовано corochoone (гостевой логин) в пн, 02/04/2007 - 08:18.

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


Опубликовано emzi в пн, 02/04/2007 - 11:11.

Автор не считает, что "производительность MySQL зависит только от одной переменной", он полагает, что мог бы посоветовать голословным критикам далеко не единственное место, куда можно было бы "сходить", однако не станет этого делать в силу очевидных причин.


Опубликовано corochoone (гостевой логин) в пн, 02/04/2007 - 13:01.

Я мог бы быть неголословным, но почему я должен вас учить MySQL? Ведь это не я написал статью, а вы. Причём не зная такой элементарной вещи как, например, даже то, что query_cache_size в MySQL 3.x отсутствует вообще. Версию MySQL вы не указали, тип таблиц тоже не указали MyISAM или InnoDB (а ведь многое зависит и от этого). О чём можно говорить дальше? Пионерская статья для пионеров.


Опубликовано ultraboy@drupal.org в пн, 02/04/2007 - 13:21.

Мне было интересно. Я - пионер? (Хотя, мо этой теме еще много можно рассказать...)

А Вас я бы попросил не быть таким заносчивым. Не все здесь админы БД и не всем все подробности реально нужны. (Хотя и интересно для общего развития)


Опубликовано corochoone (гостевой логин) в пн, 02/04/2007 - 13:40.

А мне вот другое интересно. Админы БД почему-то молчат, а статью пишут другие. Я например не считаю себя вправе кому-то что-то советовать по причине слабого знания MySQL (хотя вы меня почему-то записали в админы БД). Для того, чтобы кому-то советовать, на мой взгляд, я слишком мало знаю - это к вопросу о заносчивости. Но даже моего "мало" хватает, чтобы быть неголословным критикуя. Делайте выводы - стоит ли в следующий раз писать подобные статьи и выглядеть нелепо или лучше всё-таки изучить предмет на более высоком уровне, а потом писать.


Опубликовано Dan в пн, 02/04/2007 - 15:47.

Чем больше информации - тем лучше. Пусть обрывистой или частично неверной.
На то он и форум, чтоб люди информацию добавляли.

corochoone, закон критики: "отвергая предлагай"


Опубликовано blackvl@drupal.org в пн, 02/04/2007 - 17:02.

Предлагаю вместо бесполезных словопрений показать конфиги сервера. Это, на мой взгляд, единственная результирующая статьи.


Опубликовано corochoone (гостевой логин) в пн, 02/04/2007 - 17:10.

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

Предлагаю:
http://www.linuxshare.ru/docs/software/SQL/mysql/manual/MySQL_Optimisati...
В особенности раздел:
http://www.linuxshare.ru/docs/software/SQL/mysql/manual/Optimising_the_S...

Написано не мной, но даже этот старинный документ много информативней и полезней!

и что касается InnoDB:
http://www.mysql.ru/docs/man/InnoDB_start.html

А если что-то ещё кому не понятно, то надеюсь Яндексом все умеют пользоваться? Года 3 назад было мало чего на русском - сейчас даже для тех, кто в английском совсем не шарит - найти доки на русском нет проблем!

Конфиги сервера показывать нет смысла, потому что надо сперва разобраться у кого какая версия MySQL стоит, кто какие типы таблиц юзает - MyISAM или InnoDB, а также у кого какая конфигурация сервера. Именно всё это влияет на конфиги. Иначе это тоже самое, что показывать разные автомобили: запорожец и мерседес - и тот и другой ездят, но разницу надеюсь объяснять не надо!


Опубликовано kiev1 в вт, 24/04/2007 - 06:14.

> Админы БД почему-то молчат, а статью пишут другие.

потому что кроме друпаловского модуля db_maintenance ей ничего не поможет.
а друпал грузит mysql раз в 10 сильнее чем другие cms, не спасает даже выделенный сервер (


Опубликовано ultraboy@drupal.org в вт, 24/04/2007 - 07:58.

а друпал грузит mysql раз в 10 сильнее чем другие cms, не спасает даже выделенный сервер (

Сравнивать CMS только по нагрузке совсем не правильно. Не забывайте что по функциональности друпал тоже далеко впереди т.н. "других CMS". Уже есть десятки (если не сотни) работающих сайтов с огромной посещаемостью. Отсюда следует, что производительность для друпала не проблема. При условии нормального хостинга и прямых рук, конечно.

PS ничего личного, просто устал уже от таких необоснованных жалоб.


Опубликовано emzi в вт, 24/04/2007 - 08:20.

Задайтесь вопросом, почему почти самая частая претензия к Друпалу - его тормознутость?
Если исключить системные причины (такие, как использование php как такового, модульность), то вырисовывается интересная картина: это не Друпал тормозит о сравнению с другими CMS, это те, другие ЦМСки как-то сумели ужиться на площадках, которые нерадивые хостеры и сисадмины не в состоянии как следует настроить.


Опубликовано ultraboy@drupal.org в вт, 24/04/2007 - 08:36.

Именно так! "Сумели ужиться на площадках, которые нерадивые хостеры и сисадмины не в состоянии как следует настроить". Причем, ценой урезанного функционала.

А ведь найти вменяемый хостинг вполне реально.


Опубликовано kiev1 в вт, 24/04/2007 - 13:18.

шутите, да, издеваетесь? для обычных цмс-ок нормальным считается 10-30 запросов к базе на одну страничку, а 100 считается катастрофически много, а в друпале нормальным считается 100-300.


Опубликовано ultraboy@drupal.org в вт, 24/04/2007 - 15:46.

А в обычных CMSках есть модули path и locale? Отключите path и переведите тексты в исходном коде - вот Вам и 30 запросов!


Опубликовано kiev1 в вт, 24/04/2007 - 18:18.

да нет, 30 запросов это ерунда, включите модуль devel и посмотрите что творится, особенно в 4.7 друпале - мне так кажется что всю малину портит один единственный модуль - menu..., ну и еще views_build_view абсолютно везде лезет с запросом почти под 2 секунды.


Опубликовано Dan в вт, 24/04/2007 - 18:56.

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


Опубликовано Dan в вт, 24/04/2007 - 19:01.

- Купил Белаз, прикинь, 200 мешков цемента за раз может перевезти!
- А я на днях Феррари купил. Сколько мешков с цементом перевезёт не знаю... 3-4 влезет, наверное.
- Ацтой у тебя тачка!

Не надо говорить о средней температуре в больнице - пустое это...


Опубликовано ultraboy@drupal.org в вт, 24/04/2007 - 19:06.

2 СЕКУНДЫ?! Не миллисекунды, а секунды? Тогда, скорее всего, Вам надо идти искать пряморуких админов :)


Опубликовано kiev1 в ср, 25/04/2007 - 03:57.

при чем тут админы и белаз? вот запрос который везде цепляется из за того что почему-то блоки views просчитываются везде даже если они не выводятся, наверно ошибка в модуле block - не могу найти где.

1519.56 1 views_build_view SELECT node.nid, node.created AS node_created_created, node.created AS node_created, node.title AS node_title, node.changed AS node_changed, users.name AS users_name, users.uid AS users_uid FROM node node LEFT JOIN term_node term_node ON node.nid = term_node.nid AND term_node.tid = 'Array' LEFT JOIN term_node term_node2 ON node.nid = term_node2.nid AND term_node2.tid IN ('183') LEFT JOIN term_node term_node3 ON node.nid = term_node3.nid AND term_node3.tid IN ('138') LEFT JOIN users users ON node.uid = users.uid WHERE (term_node.tid IS NULL) AND (node.status = '1') AND (term_node2.tid IS NULL) AND (term_node3.tid IS NULL) ORDER BY node_created_created DESC LIMIT 0, 20

плюс откуда-то всегда берется по 5-10 различных левых произвольных node_load - из за того что и taxonomy_block тоже везде просчитывает блоки которые идут на главной.

7.45 1 node_load SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.moderate, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM node n INNER JOIN users u ON u.uid = n.uid INNER JOIN node_revisions r ON r.vid = n.vid WHERE n.nid = 531


Опубликовано ultraboy@drupal.org в ср, 25/04/2007 - 05:42.

Действительно, запрос серьезный. Но, все-таки, при хороших настройках базы должно быть намного меньше.


Опубликовано kiev1 в ср, 25/04/2007 - 06:23.

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

я заметил вот что - в друпале 4.7 (в 5 не смотрел) - блоки те что на главной по центру сделаны через views и taxonomy_block, они все равно просчитываются для каждой страницы, даже там где их нет - это у меня только или у всех? может потому что у страниц стоит признак "показывать на главной"?


Опубликовано lalex в ср, 25/04/2007 - 12:11.

шутите, да, издеваетесь? для обычных цмс-ок нормальным считается 10-30 запросов к базе на одну страничку, а 100 считается катастрофически много, а в друпале нормальным считается 100-300.
гм. иногда встречаю людей маникально заставляющих свой движок работать на 10 и менее запросах. только бред это.
во многих случаях один запрос может выполняться существенно медленнее чем с десяток simple (простых) запросов. Так что количество запросов - это еще не показатель производительности системы в целом.

Затянутые по времени запросы - возможно проблема индексов.
не всегда. иногда появляются запросы которые просто не могут по своей природе использовать индексы - в результате полное сканирование таблиц (не знаю как в Views - не пользуюсь им и не собираеюсь, нечто такое наблюдал в pathauto под 4.7).

to kiev1
а вы не пробовали смотреть что выдает EXPLAIN <запрос>?


Опубликовано kiev1 в ср, 25/04/2007 - 12:41.

> а вы не пробовали смотреть что выдает EXPLAIN <запрос>? вот этот запрос

SQL-запрос:
EXPLAIN SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.moderate, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data
FROM node n
INNER JOIN users u ON u.uid = n.uid
INNER JOIN node_revisions r ON r.vid = n.vid
WHERE n.nid =531


выдает вот что

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE n const PRIMARY,nid,uid,vid nid 4 const 1  
1 SIMPLE u const uid uid 4 const 1  
1 SIMPLE r ALL NULL NULL NULL NULL 464 Using where

только что это значит? и что с ним делать?


Опубликовано B.X в ср, 25/04/2007 - 15:07.

"ну и еще views_build_view абсолютно везде лезет с запросом почти под 2 секунды"

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

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


Опубликовано kiev1 в ср, 25/04/2007 - 18:03.

ну да, path, он конечно тоже долгие запросы делает и их не так уж много, потом эта revision везде лезет - как ее отключить - давайте придумаем, а?
И главное - вот с той табличкой - что из EXPLAIN получилась - с ней что делать? как теперь с этим жить? научите оптимизировать запросы.


Опубликовано B.X в ср, 25/04/2007 - 21:43.

есть модуль на Друпал.орг уничтожает все ревизии...
я не помню где он там, посмотрите по слову revision

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


Опубликовано kiev1 в ср, 25/04/2007 - 23:18.

а что табличка означает, особенно последняя строчка?


Опубликовано lalex в чт, 26/04/2007 - 08:04.

последняя строчка означает сканирование таблицы node_revisions ввиду того что не используются индексы (скорее всего в этой таблице отсутствует индекс по полю vid). в случае с небольшими сайтами - проблем по идее не должно возникать. но представьте сайт скажем так с 16-18 тыс. нод. это будет ужас :)

select type - тип оператора SELECT. В данном случае у вас все запросы "простые" (все запросы - т.е. запрос можно записать как три запроса, без использования JOIN)

type - тип соединения. const - это хорошо. т.к. считываются только один раз и содержат только максимум 1 строку. (что собственно видно из столбца rows). А вот ALL означает полное сканирование таблицы.Обычно это плохо. Избегать такой ситуации можно используя индексы.

possible_keys - используемые индексы. сразу видно что в последней строке не используются индексы.

extra - у вас в последней строке написано using where. Это означает что используется выражение where (в данном случае будет типа SELECT * node_revisions r WHERE r.vid=значение). Более жесткого ограничения для таблицы node_revisions не задается соответственно выбираются все записи с этим значением поля vid. Как я понимаю (если есть гуру подтвердите) - такой запрос приведет к сканированию таблицы node_revisions в не зависимости от ограничений n.nid.

Если оптимизировать этот запрос, то для начала конечно можно добавить индекс в node_revisions для поля vid. Но в целом лично мне этот запрос не понятен - т.е. что этот запрос делает:
выводит информацию о конкретной ноде (531й) из таблиц node и node_revisions, докучи подгружая данные о юзере.
Каким боком здесь INNER JOIN node_revisions r ON r.vid = n.vid ? Что дает эта конструкция кроме как лишнего сканирования таблицы node_revisions? имхо правильнее было бы INNER JOIN node_revisions r ON r.nid=n.nid (даже с логической точки зрения). И еще зачем в данном случае вообще использовать запрос заранее зная номер ноды? т.е. не проще ли использовать в нужном месте node_load и node_view и модифизировать шаблон в нужном месте для правильно вывода? (вот в этом моменте я сомневаюсь, т.к. для меня проще было бы самому модуль написать в котором реализуются нужные блоки а в теме - только вывод в независимости от содержания)


"потом эта revision везде лезет"

да но там содержимое хранится, не в node а в node_revisions в полях body и teaser. :) модуль который "убивает ревизии" убивает версии как я понимаю саму таблицу он наврядли убьет, это было бы неправильно наверное :)


Опубликовано kiev1 в пт, 27/04/2007 - 02:53.

спасибо!
у таблицы node_revisions есть все ключи
почему делается выборка из всей таблицы - не знаю - наверно это баг модуля views - потому что этот запрос делает функция views_build_view - вид совсем не сложный - вывод блока из нескольких таксономий.


Опубликовано Murz в сб, 28/07/2007 - 15:11.

emzi says: "уменьшить количество запросов" - можно, я на эту тему тоже хочу сделать статеечку.

Очень интересно было бы почитать статью на эту тему, а то меня данная проблема тоже очень волнует ;(


Опубликовано sashka в вт, 31/07/2007 - 20:03.

Эээээээ.... Кто-то сказал pgsql? Или всё можно списывать эту субд...? Топик напряженный - люди улыбайтесь чаще :)


Опубликовано kiev1 в вт, 31/07/2007 - 23:53.

Да, похоже у друпала это по-жизни проблема с тормознутостью - сайт drupal.org еле живой, поиск уже они отключили...


Опубликовано sashka в вт, 07/08/2007 - 13:13.

Встречал ссылку, что мол Ворнер брозерс что-то замутили на друпале... и типа Solaris у них там стоит :) SAMP: Solaris Apache MySQL PHP. Может вот оно что ему надо?


Опубликовано corochoone (гостевой логин) в чт, 16/08/2007 - 05:23.

Это Drupal тормознутый? Ребята, вы ещё Bitrix не видели :) Особенно последний. Там админку чтобы открыть надо мегабайт данных скачать (диалапщики уже могут отдыхать), а уж как сервер напрягается во время работы - это вообще сказка :)


Опубликовано orbisnull в чт, 16/08/2007 - 07:26.

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


Опубликовано sashka в вт, 11/09/2007 - 17:52.

Так оно бегало быстрее или нет ?:)
Заметка себе на будущее посмотреть к какие таблицам и по каким полям друпал круче всего муржит бд:) и самому поковырять...


Опубликовано corochoone (гостевой логин) в чт, 13/09/2007 - 13:12.

Я думаю, что в Друпал та же проблема, что и в Битрикс и других CMS. Просто разработчики тестируют всё на табличках с 10 колонками. Если нет индексов, то на таких данных и не напрягает. А если данных в таблице сотни тысяч и миллионы строк, вот тут-то тормоза и наступают.

Могу дать бесплатный совет для тех кто не знает. Включайте в mysql протоколирование тяжёлых запросов (long-queries) и смотрите какие запросы выполняются непозволительно долго. А дальше - хоть phpMyAdmin вам в руки, explain и осмотр всего этого дела на предмет наличия нужных индексов с последующим их созданием. Довольно неплохо помогает!


Опубликовано kiev1 в пт, 14/09/2007 - 08:11.

> Просто разработчики тестируют всё на табличках с 10 колонками.

не - в друпале все тестируют на самом drupal.org - а там очень много материалов, они делают что могут, наверно что-то придумают.


Опубликовано igdrasil@drupal.org в пт, 14/09/2007 - 09:30.

не - в друпале все тестируют на самом drupal.org
если говорить о ядре - да, но если бы все модули тестировались на ДО, он бы лежал перманентно


Опубликовано sas@drupal.org в пт, 14/09/2007 - 13:12.

Господа - на org черным по белому написано
Modules

Modules are plugins for Drupal that extend its core functionality. Only use matching versions of modules with Drupal. Modules released for Drupal 4.7.x will not work for Drupal 5.x. These contributed modules are not part of any official release and may not be optimized or work correctly.
Эти дополнительные модули не являются частью официального релиза и могут буть не оптимизированы или работать некорректно.


Опубликовано corochoone (гостевой логин) в сб, 15/09/2007 - 06:14.

Это правда, но согласитесь, что Drupal в core поставке мало кому интересен :)
А вообще спасение - дело рук самих утопающих. Слава Богу Drupal - это opensource проект и никто не мешает принять участие в его разработке. К сожалению и за мной такой грешок водится - что-то поправил, что-то соптимизировал, но выслать рецепты разработчикам... увы. :( В результате следующий кто наступит на эти грабли решает их самостоятельно!


Опубликовано emzi в вс, 16/09/2007 - 09:05.

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