Снижение нагрузки на сервер. Оптимизация VitrueMart.
posted in Полезности, Программирование |В рамках цикла заметок по вычислению и снижению нагрузки на сервер было бы не правильно не опубликовать логическое завершение «разборок» с VirtueMart, как одним из виновников в жёстском ступоре сервера, выявленном по создаваемым нагрузкам на MySQL — подробнее в предыдущей заметке Вычисление нагрузки на сервер. Part 1 — MySQL Так же стоит заметить — торможение MySQL цепляет за собой и нагрузку на память в виде ожидающего данных веб-сервера (на данный момент у меня это сильно сжирающий память индеец).
Итак:
- изначально о слишком большой нагрузке узнал в реальном режиме просматривая top
- далее захотелось узнать кто же конретно грузит — с этой задачей справилась утилита mtop
- конкретные «тормозные» SQL запрос смотрим в логах, предварительно включив нужную опцию
Виновник вычислен, скрипт известен — что же дальше ?
Ну а дальше самый важный шаг — оптитизация приложения.
Грамотно реализованное приложение будет работать быстрее аналогичного по задачам на обычном VDS против супер-навороченного выделенного сервера — это факт !
Ладно — хватит лирики .. .По нашей задаче — далее всеми мыслимыми и немыслимыми способами ищем программный код, генерирующий вычисленный запрос — гуглим, разбираемся в Joomla, VitueMart, ищем по «select distinct», включаем интуицию, метод «научного тыка» — в общем все эти «пляски с бубном» лично мне помогли вычислить файл — shop_browse_queries.php
Далее анализируем и оптимизируем сам запрос — вычисляем неиспользуемые и ненужные поля — убираем их, проверям заново (всё это можно делать отдельно от приложения — например, в чистом MySQL.
Далее дело за малым — правим наш shop_browse_queries.php в соответствие с нашим запросом.
Всё ! В результате проделанных махинаций запрос стал отрабатывать раз в 10 быстрее, в лог «тормозов» не попадает — сервер вздохнул свободно (по крайней мере падений пока не наблюдалось).
Кому интересно, вот подробности:
Мой файлик после корректировки
Вычисленный запрос
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
SELECT DISTINCT `product_name`,`products_per_row`,`category_browsepage`,`category_flypage`,`jos_vm_category`.`category_id`, `jos_vm_product`.`product_id`,`product_full_image`,`product_thumb_image`,`product_s_desc`,`product_parent_id`,`product_publish`,`product_in_stock`,`product_sku`, `product_url`, `product_weight`,`product_weight_uom`,`product_length`,`product_width`,`product_height`,`product_lwh_uom`,`product_in_stock`,`product_available_date`,`product_availability`,`jos_vm_product`.`mdate`, `jos_vm_product`.`cdate` FROM (`jos_vm_product`, `jos_vm_category`, `jos_vm_product_category_xref`,`jos_vm_shopper_group`) LEFT JOIN `jos_vm_product_price` ON `jos_vm_product`.`product_id` = `jos_vm_product_price`.`product_id` WHERE (`jos_vm_product_category_xref`.`product_id`=`jos_vm_product`.`product_id` OR `jos_vm_product_category_xref`.`product_id`=`jos_vm_product`.`product_parent_id`) AND `jos_vm_product_category_xref`.`category_id`=`jos_vm_category`.`category_id` AND `jos_vm_product_category_xref`.`category_id`=19 AND ((`jos_vm_product`.`product_id`=`jos_vm_product_price`.`product_id` AND `jos_vm_shopper_group`.`shopper_group_id`=`jos_vm_product_price`.`shopper_group_id`) OR `jos_vm_product_price`.`product_id` IS NULL) AND `jos_vm_shopper_group`.`default` = 1 AND `product_parent_id`=0 AND `product_publish`='Y' AND `category_publish`='Y' GROUP BY `jos_vm_product`.`product_sku` ORDER BY `jos_vm_product`.`product_name` ASC LIMIT 0, 20 |
Запрос после модификации (внимание — подобное вырезание, конечно же вырезает и функционал, я просто многое не использую — поэтому порезал. так что «7 раз отмерь 1 отреж»)
1 2 3 4 5 6 7 8 9 10 11 |
SELECT DISTINCT `product_name`,`jos_vm_category`.`category_id`,`jos_vm_product`.`product_id`,`product_full_image`,`product_thumb_image`,`product_s_desc`,`product_publish`,`product_sku`, `product_weight`,`product_weight_uom`,`jos_vm_product`.`mdate`, `jos_vm_product`.`cdate` FROM (`jos_vm_product`, `jos_vm_category`, `jos_vm_product_category_xref`,`jos_vm_shopper_group`) LEFT JOIN `jos_vm_product_price` ON `jos_vm_product`.`product_id` = `jos_vm_product_price`.`product_id` WHERE `jos_vm_product_category_xref`.`product_id`=`jos_vm_product`.`product_id` AND `jos_vm_product_category_xref`.`category_id`=`jos_vm_category`.`category_id` AND `jos_vm_product_category_xref`.`category_id`=19 AND `jos_vm_product`.`product_id`=`jos_vm_product_price`.`product_id` AND `product_publish`='Y' GROUP BY `jos_vm_product`.`product_sku` ORDER BY `jos_vm_product`.`product_name` ASC LIMIT 0, 20 |
Статистика до (товаров в базе около 5k)
1 2 3 4 5 6 7 8 9 |
Информация о профиле Application afterLoad: 0.000 seconds, 0.44 MB Application afterInitialise: 0.061 seconds, 4.05 MB Application afterRoute: 0.069 seconds, 4.92 MB Application afterDispatch: 1.149 seconds, 16.96 MB Application afterRender: 1.877 seconds, 18.51 MB Использование памяти 19457648 Зарегистрировано запросов: 413 |
Статистика «после»
1 2 3 4 5 6 7 8 9 |
Информация о профиле Application afterLoad: 0.000 seconds, 0.45 MB Application afterInitialise: 0.047 seconds, 4.05 MB Application afterRoute: 0.055 seconds, 4.92 MB Application afterDispatch: 0.626 seconds, 16.96 MB Application afterRender: 0.701 seconds, 18.52 MB Использование памяти 19461440 Зарегистрировано запросов: 413 |
P.S. Следующим шагом будет полный отказ от Apache — переход на связку nginx+php as fastcgi
Что по идее должно сильно разгрузить память (если получится — можно на мускул будет побольше выделить).