Оптимизация тяжёлого сайта WordPress. Memcache+Object Cache+Xhprof

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5
Загрузка...

Для меня уже давно не секрет, что CMS WordPress в сочетание с плагином Woocommerce, и огромной базой данных очень сильно тормозит сайт.

На практике удалось выяснить, что на скорость загрузки сайта влияет кол-во атрибутов. После парсинга информации, практически все сайты начинали «лагать».В интернете магазине, который загружался порядка 20-30 секунд потребовалась оптимизация, и причина как оказалось именно в атрибутах.

Карточка магазина:

  • 33 000 товаров
  • 195 атрибутов
  • 2142 категории с 3-уровневой вложенностью
  • 24 товара на странице
  • Размер базы данных: 1.5ГБ
  • Объём файлов с картинками 22 гигабайта

Содержание

Что делать для ускорения сайта?

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

При этом как показала практика, на стадии создания кеша, плагин Super Cache ещё сильней тормозит сайт. А после очистки кеша сайт вообще не загрузится.

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

Что же делать в данном случае?

1. Устанавливаем плагин для WordPress — Query Monitor. Данный плагин покажет медленные sql запросы. Если таковые есть, нужно либо их оптимизировать, либо устанавливать плагин объектного кеша. В моём случае такие запросы были.

2. Установка на хостинге Memcache. В моём случае интернет магазин лежит на хостинге beget. Цена данного сервиса 2р — 500Mb / сутки

3. Установка плагина Object Cache, который работает с Memcache

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

Query Monitor


И так начнём с этого плагина, в моём случае медленные sql запросы были в каталоге товаров Woocommerce с сортировкой по рейтингу. Что делать? В настройках плагина установить сортировку по умолчанию (Дата,id).

Дело в том, что сортировка по мета данным выполняется значительно дольше, а всё потому, что поле meta_key создан с типом «text», который не кэшируется на стороне mysql сервера.

Установка на хостинге Memcache


Если база данных большая, и на хостинге установлен memcache, результаты sql запросов можно записывать в кэш и брать их оттуда, тем самым сократить до минимума кол-во запросов, а так же отклик от сервера. Но для этого понадобится скрипт объектного кеша.

Установка объектного кеша


После установки на хостинге Memcache, необходимо в папку /wp-content/ загрузить файл object-cache. В файле wp-config.php прописать строчку — define(‘WP_CACHE’,true), а затем открыть сайт.

Если сайт загрузился без ошибок (например белого экрана), значит на хостинге установлен memcache, и мы можем увидеть результат в Query Monitor (509 sql запросов,время выполнения — 0.95сек).

При включённом кеширование кол-во sql запросов на главной странице упало до 23, вместо 509

 

Результаты оптимизации с Memcached + Object Cache:

Карточка товара — 15сек, после 6 секунд

Категория — 18 сек, после 10 секунд

Профайлинг (XHPROF)


После установки XHPROF я занялся диагностикой скриптов, и как показал отчёт, post_class — одна из тех злосчастных функций, которая тормозит сайт.

Что делает функция?

Функция post_class собирает все css классы, включая атрибуты, и добавляет их к тэгу, <li>.

В файле content-product.php выглядит это вот так:

<li <?php post_class(); ?>>

Так как в интернет магазине очень много атрибутов, функция собирает css атрибуты для каждого товара, тем самым нагружает сайт! Спрашивается, зачем для блока с товаром создавать классы атрибутов? Грамотный верстальщик может изменить внешний вид и без этих классов.

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

Для этого я вручную прописал все классы, которые необходимы для правильного отображения товара. Для архива одни классы, для карточки (похожие и просмотренные) другие. Файл с шаблоном content-product.php с ниже указанным кодом, был размешён в папке с темой wp-content/themes/Ваша тема/woocommerce/content-product.php, для того чтобы оставить копию начального шаблона, и при обновление Wooccomerce шаблон опять не слетел.

<li <?php if(!is_product()){?>class="post-<?php echo $product->get_id();?> product type-product status-publish has-post-thumbnail column-1_3 product-type-simple" <?php }else{ ?>class="post-<?php echo $product->get_id();?> product type-product status-publish has-post-thumbnail column-1_4 product-type-simple"<?php }?>>

Ещё один довольно важный момент, так как мы вручную прописали все классы, изменение кол-во товаров в административной панели, может вызывать неправильное отображение в категориях. Обрати внимание на класс column-1_3, если вдруг понадобится сменить кол-во товаров с 3 на 2, то нужно будет изменить название класса с column-1_3 на column-1_2.

Те же самые действия были сделаны с файлом content-single-product.php

Результы оптимизации

Карточка товара — 10 сек, после ~6 секунд

Категория — 14 сек, после ~6.5 секунд

Wp translitera

Xhprof показал, что плагин Wp translitera загружается 0.80 секунды, не совсем понятно зачем он вообще подгружается в fronted сайта?

Суть данного плагина заключается в том, чтобы сделать транслитерацию русских букв (url записи,товара, страницы) в латиницу, но зачем он запускает функционал везде совершено не ясно.

В самом плагине я нашёл следующие строки:

add_action('init', array('wp_translitera', 'init'));
//Редирект 404
add_action('wp',array('wp_translitera','init404'),(wp_translitera::wpforoactive())?11:10);
//Переименовываение загружаемых файлов
add_filter('sanitize_file_name',array('wp_translitera', 'rename_uploads_additional'),10,2);
//Установка плагина
register_activation_hook(__FILE__, array('wp_translitera','install'));

И заменил на :

if(is_admin()){
  add_action('init', array('wp_translitera', 'init'));
  //Редирект 404
  add_action('wp',array('wp_translitera','init404'),(wp_translitera::wpforoactive())?11:10);
  //Переименовываение загружаемых файлов
  add_filter('sanitize_file_name',array('wp_translitera', 'rename_uploads_additional'),10,2);
  //Установка плагина
  register_activation_hook(__FILE__, array('wp_translitera','install'));
}

Что я сделал? Всё очень просто, транслитерация будет выполняться только в админ панели. На этом пункте скорость увеличили ещё как минимум на 0.5 секунды. Не забываем о том, что плагины периодически обновляются, а это значит нужно установить запрет на его обновление.

Запрет обновления для плагина.

Для этого внутри плагина заменяем версию на самую новую , например — 999999999

Тормоза в админке


Как оказалось админка WordPress так же тормозила, и страница редактирования карточки товара открывалась около 15 секунд, 10 из которых приходилось на обработку sql запросов.

Начал смотреть Query Monitor, оказалось, что админку нагружается плагин Slider Revolution. Сразу появился вопрос, какого чёрта плагин подгружает загруженные элементы слайдера в админке на каждой странице?

Оптимизация Базы данных WordPress

Тут мне в голову пришло немного повозиться с БД WordPress, обратите внимание, что медленные sql запросы (0.5 сек) связаны с поиском по мета полям.

SELECT post_id
FROM wp_postmeta
WHERE meta_key = '_wp_attached_file'
AND meta_value = 'revslider/slider3/slider3_slide_1.jpg'

Так как в базе данных поле meta_value создан с типом «longtext», а mysql их не индексирует, принял решение изменить его на VARCHAR(10000).

Прежде чем менять тип поля,с помощью sql запроса была найдена самая длинная строка в ячейке, чтобы не обрезать данные.

Оказалось, что максимальная длинна по базе, не более 9436 символов, и это цифра приближается к 10 000. Увеличим VARCHAR до 15 000. Где-то на форуме читал, что это изменение типа на Varchar выше 255 не даст никаких результатов, проверим?

Как видно Query Monitor показал скорость загрузки 5 секунд вместо 10, увеличение производительности в 2 раза!

А что же сам sql запрос? 0.0004 сек, вместо 0.5, а всё потом что mysql индексирует поле VARCHAR, и не важно какой оно длинны!

SELECT length(meta_value) as length FROM `wp_postmeta` order by length desc

 

Дополнительная оптимизация БД

В базе данных wp_postmeta я сменил тип поля `meta_key` с TEXT на VARCHAR(255),  и применил индекс для данного поля. Данное поле на практике не использует больше 255 символов, соответственно можно сделать индекс, и тем самым ускорить время sql запроса.

Установка Wp Super cache

Теперь пришло время установки данного плагина и его активации. Почему именно сейчас? Мы максимально сократили время ответа от сервера, и теперь при очистке кеша сайт не будет грузиться 20 а то и 30 секунд. После активации плагина, просмотренная страница интернет магазина или записи попадает в кэш, и при обновления загрузка выполняется не более 1 секунды.

Стоит так же не забывать, что любые изменения в шаблоне сайта, будь это php, или html файл требует обязательной очистки кеша.Как правильно настроить Wp Super Cache я расскажу в другой статье.

Дополнительные рекомендации для тяжёлых сайтов

  • Не загружайте сайт различными плагинами. Если нужен простой скрипт попробуйте написать его самостоятельно, и внедрить в файл function.php вашей темы
  • Не создавайте для интернет магазина разработанного на Woocommerce много атрибутов. Если атрибуты нужны исключительно для описания, а не для фильтрации в каталоге, делайте их как «Индивидуальные». Множество атрибутов сильно нагружают ни только mysql сервер, но и apache.
  • Создание виджетов и сайдбаров так же нагружает mysql и процессор сервера, если сайт «тяжёлый», дополнительный код или виджет внедряйте в шаблон напрямую
  • Если в футере или header сайта есть дополнительное меню из 5-6 пунктов, будет проще прописать html код напрямую в шаблон, чем внедрять виджет «Категории» в сайдбар сайта
  • Если виджетов очень много, можно попробовать использование плагина Widget Cache Output

Итог

На данный момент время ответа от сервера колеблется от 2 до 6 секунд, вместо 20-30, конечно же на этом оптимизация не закончилась, и я продолжаю искать слабые места WordPress без использования глобального кеширования страниц. Хоть и время загрузки по прежнему большое, я очень доволен результатом, и ни капли не сожалею о потраченном времени.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*
*