CMS: WordPress, Битрикс, Tilda и другие

WordPress тормозит после трёх лет работы: как реанимировать

Что чинить в первую очередь, если WordPress стал медленным после нескольких лет: база, плагины, кэш, ревизии, картинки и тема.

обновлено 9 минут чтения 0 Дмитрий Акиндинов
Содержание
  1. Почему WordPress становится медленным со временем
  2. Чек-лист первых проверок
  3. Что чистить безопасно: ревизии, transient, осиротевшие записи
  4. Какие плагины меняем на нативные функции и какие убираем
  5. Кэш, картинки и шрифты
  6. Когда дешевле сделать чистую установку
  7. С чего начать прямо сегодня
  8. Частые вопросы

За три года сайт обрастает ревизиями, временными записями и следами удалённых плагинов. Норма для трёхлетнего сайта на тысячу публикаций это 200-500 МБ базы. Три гигабайта при полутора тысячах записей означают, что чистить есть что, и переезд на дорогой тариф проблему не решит.

Сайт открывался за секунду в год запуска. Сейчас, спустя три года, главная грузится семь, а админка иногда висит и отдаёт 504. Хостинг тот же, контент почти не растёт, посещаемость стабильная. Кажется, надо переезжать на более дорогой тариф или даже на VPS. На практике в восьми случаях из десяти WordPress тормозит не из-за хостинга, а из-за того, что внутри накопилось пять лет цифрового ила. Разберём, что чистить в первую очередь и какие приёмы дают эффект, который заметен сразу.

Черепаха рядом с буквой W в стиле WordPress

Почему WordPress становится медленным со временем

WordPress изначально не самая лёгкая CMS. На стандартной установке без оптимизации главная страница отдаёт 25-40 запросов к базе и 10-20 загружаемых ресурсов. С активным сайтом цифры быстро уезжают.

Основные причины замедления, которые я встречаю на аудите:

  1. База раздулась. Таблицы wp_posts, wp_postmeta, wp_options копят ревизии, transient-ы, осиротевший meta от удалённых плагинов. На сайте трёх лет от роду нормально иметь 200-500 МБ базы при 1000 публикаций. Если у вас 3 ГБ при 1500 постов, что-то не так.
  2. Плагинов накопилось 30-50. Половина не используется, но грузится на каждый запрос. Каждый плагин это +5-15 запросов к базе, +1-3 файла CSS и JS, иногда +внешние HTTP-запросы к серверу автора.
  3. Тема обросла кастомизациями. В functions.php через год появляются 200-300 строк хуков, добавленных по разным поводам. Каждый хук срабатывает на init, wp_loaded или template_redirect и тормозит ответ.
  4. Кэш умер или не настроен. Был WP Super Cache, перестал писать файлы после обновления. W3 Total Cache конфликтует с CloudFlare. Object cache не подключен, потому что хостер не даёт Redis.
  5. Картинки в полном размере. Камера фотографа выдаёт 8 МБ JPEG, в посте используется превью 600 пикселей, но srcset не подключен или браузер качает оригинал.

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

Чек-лист первых проверок

Прежде чем что-то менять, замеряем текущее состояние. Без цифр на старте через неделю не получится сказать, помогло или нет.

TTFB и время до первого байта

Открываем сайт в режиме инкогнито (чтобы не врал кэш браузера) и смотрим во вкладке Network в Chrome DevTools первый запрос к HTML. Поле Waiting (TTFB) на главной должно быть до 600 мс на shared-хостинге и до 300 мс на VPS. Если 1500-3000 мс, проблема на стороне сервера или PHP, а не во фронтенде.

Альтернативно через консоль:

curl -o /dev/null -s -w "TTFB: %{time_starttransfer}snTotal: %{time_total}sn" https://example.com/

Размер базы и крупнейшие таблицы

Заходим в phpMyAdmin или подключаемся через SSH. Запрос, который покажет топ-10 самых больших таблиц:

SELECT table_name AS "Таблица",
       ROUND(((data_length + index_length) / 1024 / 1024), 2) AS "Размер МБ",
       table_rows AS "Строк"
FROM information_schema.tables
WHERE table_schema = "имя_базы"
ORDER BY (data_length + index_length) DESC
LIMIT 10;

Подставьте имя базы вместо имя_базы. На здоровом сайте до 5 тысяч публикаций обычно сверху видим wp_options (5-30 МБ), wp_postmeta (10-100 МБ), wp_posts (10-50 МБ). Если wp_options раздут до 200 МБ, это transient-катастрофа. Если wp_postmeta под гигабайт, плагин типа Yoast или Elementor оставил мусор.

Профилировщик запросов

Самый быстрый способ увидеть, какие плагины тормозят: поставить Query Monitor на час. Плагин показывает количество запросов к БД, время каждого, кто из плагинов какой запрос сгенерировал, какие хуки сработали. После замеров отключить и удалить, в продакшне он сам по себе тормозит.

Альтернатива для тех, кто не хочет ставить плагин: включить SAVEQUERIES в wp-config.php:

define('SAVEQUERIES', true);

И в шаблоне футера временно вывести $wpdb->queries. Минус: это правит файл темы, легко забыть выключить.

Что чистить безопасно: ревизии, transient, осиротевшие записи

После замеров переходим к чистке. Эти операции почти всегда безопасны, но бэкап БД сделать обязательно. Один раз я удалил всё wp_postmeta без префикса плагина и положил магазин на сутки.

Чистка ревизий

WordPress по умолчанию хранит все версии правок поста. На сайте, где статью редактировали 50 раз, в базе 50 записей в wp_posts со статусом revision.

Удаление через SQL:

DELETE FROM wp_posts WHERE post_type = "revision";

После этого в wp_postmeta останутся ссылки на удалённые ревизии. Чистим:

DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts wp ON wp.ID = pm.post_id
WHERE wp.ID IS NULL;

Чтобы ревизии не копились дальше, в wp-config.php:

define('WP_POST_REVISIONS', 5);

Пять последних правок более чем достаточно.

Чистка transient

Transient это временный кэш в wp_options. WordPress должен сам удалять просроченные, но при сбоях этого не происходит. Бывают случаи, когда wp_options раздут до 500 МБ из transient-ов, оставленных мёртвыми плагинами.

DELETE FROM wp_options WHERE option_name LIKE "_transient_%";
DELETE FROM wp_options WHERE option_name LIKE "_site_transient_%";

Сайт сам пересоздаст актуальные transient при следующем запросе. Старые исчезнут навсегда.

Чистка спам-комментариев

Если включены комментарии и Akismet или другой антиспам, в wp_comments могут сидеть десятки тысяч записей со статусом spam или trash.

DELETE FROM wp_comments WHERE comment_approved = "spam";
DELETE FROM wp_comments WHERE comment_approved = "trash";
DELETE FROM wp_commentmeta WHERE comment_id NOT IN (SELECT comment_ID FROM wp_comments);

После всех чисток обязательно OPTIMIZE TABLE по основным таблицам, чтобы место реально освободилось:

OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options, wp_comments, wp_commentmeta;

На InnoDB OPTIMIZE TABLE по факту делает ALTER TABLE, поэтому таблица будет временно недоступна. Для большой базы лучше делать в окне минимальной нагрузки.

База данных и метла

Какие плагины меняем на нативные функции и какие убираем

После чистки БД смотрим в список плагинов. Заходим в Плагины → Установленные и идём по списку с одним вопросом: «Что сломается, если я это выключу прямо сейчас?». Если ответ «ничего» или «не знаю», плагин кандидат на удаление.

Категории плагинов, которые почти всегда лишние

КатегорияЧто обычно стоитЧем заменить
Контактные формыContact Form 7, WPFormsСвоя форма + WP REST API, либо Fluent Forms (легче)
SEOYoast SEO, RankMathОдин из двух, а не оба. Часто хватает SEO Framework
БезопасностьWordfence + iThemes + SucuriОдин Wordfence, остальные удалить
КэшWP Super Cache + W3 + AutoptimizeОдин: WP Rocket или LiteSpeed Cache
СлайдерыSlider Revolution, Smart SliderЧаще всего не нужны вообще, заменить статичной картинкой
Социальные кнопкиSassy Social Share, MonarchСвой HTML на 10 строк без JS
АналитикаMonsterInsights, Site KitПрямая вставка кода Метрики и GA через functions.php

Каждый плагин из левой колонки добавляет 50-200 мс к TTFB. Замена на правую колонку обычно даёт минус 1-2 секунды на главной.

Конкретные подмены через код

Например, плагин «Disable Comments» просто убирает поддержку комментариев. Тоже самое делает добавление в functions.php:

add_action('admin_init', function () {
    remove_post_type_support('post', 'comments');
    remove_post_type_support('page', 'comments');
});
add_action('admin_menu', function () {
    remove_menu_page('edit-comments.php');
});

Плагин «WP Disable Auto Update» заменяется одной строкой в wp-config.php:

define('AUTOMATIC_UPDATER_DISABLED', true);

Плагин «Limit Login Attempts» во многом дублируется одной директивой в .htaccess плюс добавлением application password для API. Хотя для админки лучше реальный антибрут, тут не экономьте.

Удаление плагина правильно

Просто отключить и удалить через админку недостаточно. Многие плагины оставляют свои таблицы в БД, опции в wp_options, файлы в wp-content/uploads/<plugin-name>/ и cron-задачи. После удаления:

SELECT option_name FROM wp_options WHERE option_name LIKE "%plugin-prefix%";
SHOW TABLES LIKE "wp_pluginprefix_%";

Удалите вручную всё, что нашлось. Cron-задачи смотрите через WP Crontrol или прямо в wp_options в cron-опции.

Кэш, картинки и шрифты

После того как вычистили лишнее, подключаем то, без чего быстрый WordPress не бывает.

Page cache

Один плагин уровня LiteSpeed Cache (если хостинг на LiteSpeed-сервере), WP Rocket (платный, лучший по соотношению «поставил-забыл-работает») или WP Super Cache (бесплатный, без излишков). Настройки минимально-разумные:

  • Кэшировать страницы для незалогиненных посетителей.
  • Не кэшировать корзину, чекаут, личный кабинет.
  • Минифицировать CSS и JS, но без агрессивного объединения (часто ломает темы).
  • Включить gzip на стороне сервера, не плагином.
  • Прелоадер кэша включить, но не агрессивно (раз в сутки, не каждый час).

После настройки замерить главную: TTFB должен упасть до 200-400 мс на shared, до 50-150 мс на VPS.

Картинки

Прогоняем все существующие через batch-конвертер в WebP. Плагины: ShortPixel, Imagify, EWWW Image Optimizer. У всех бесплатный тариф на первые 100-300 картинок, дальше платный.

Альтернатива через консоль, если есть SSH:

cd wp-content/uploads
find . -type f ( -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" ) 
  -exec cwebp -q 80 {} -o {}.webp ;

Дальше нужно, чтобы тема отдавала WebP браузерам, которые их понимают. Это либо плагин (Cache Enabler умеет), либо picture-теги в шаблонах, либо переписывание через .htaccess:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} .(jpe?g|png)$
RewriteCond %{REQUEST_FILENAME}.webp -f
RewriteRule (.+).(jpe?g|png)$ $1.$2.webp [T=image/webp,E=accept:1]
</IfModule>

Картинка размером 1200 пикселей в JPG обычно весит 250-400 КБ. В WebP та же картинка с тем же визуальным качеством 80-120 КБ. На странице с 15 картинками это минус 3-4 МБ загрузки.

Шрифты

Если тема грузит Google Fonts с CDN, в России это рулетка. Часть посетителей увидит белый экран на 2-3 секунды, пока Chrome пытается достучаться до fonts.googleapis.com. Решение: скачать нужные шрифты, положить в wp-content/themes/<theme>/fonts/, подключить через @font-face локально.

Бонус: уберите неиспользуемые начертания. Тема обычно подключает 4-6 наборов жирности и стиля, реально на сайте используется 2.

Спидометр от красного к зелёному над макетом сайта

Когда дешевле сделать чистую установку

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

  • 5+ старых тем в папке wp-content/themes/, и непонятно, какая используется.
  • 60+ плагинов, из которых половина не работает.
  • Несколько лет правок в functions.php без комментариев и истории.
  • В wp-content/uploads/ лежат архивы, бэкапы, файлы клиента, забытые тестовые папки.
  • База 5+ ГБ при 2000 публикаций.

Алгоритм чистого переноса:

  1. Поднять чистый WordPress на тестовом домене или в подпапке.
  2. Поставить нужную тему (новую или дочернюю от существующей, без ваших правок).
  3. Поставить минимальный набор плагинов: SEO, кэш, форма.
  4. Импортировать только посты, страницы, медиа через WordPress Importer (wp-admin/import.php). Не переносить плагин-настройки.
  5. Перенести меню вручную, обычно их 2-4.
  6. Перенести виджеты вручную.
  7. Сравнить страницы попарно: если важная функциональность отсутствует, добавить точечно.

Сроки: 8-16 часов работы для среднего корпоративного сайта. Магазин с 1000 SKU и интеграциями переносить так не стоит, там лучше последовательная чистка.

С чего начать прямо сегодня

Если читать это в обед, то к вечеру можно сделать минимум:

  1. Снять полный бэкап файлов и базы.
  2. Запустить запрос топ-10 таблиц в phpMyAdmin, посмотреть размеры.
  3. Удалить ревизии и transient через SQL.
  4. Сделать OPTIMIZE TABLE.
  5. Замерить TTFB до и после.

Этого хватает, чтобы сбросить 1-2 секунды загрузки на половине запущенных WordPress. Дальше идёт более тонкая работа: ревизия плагинов, чистка темы, настройка кэша, конвертация картинок. На это в среднем уходит 10-20 часов работы для трёхлетнего сайта с 30 плагинами.

Если самому копаться неохота или страшно сломать продакшн, напишите через форму на /#contact. Сделаю аудит за час, по результатам покажу, что вычистить безопасно, а что трогать нельзя. Стоимость разовой реанимации и ежемесячной поддержки, в которую такая чистка входит как профилактика, есть на странице тарифов. Другие материалы про WordPress и скорость собраны в рубрике CMS.

Частые вопросы

Почему WordPress со временем тормозит

Растёт база: ревизии записей, временные значения, логи плагинов, таблицы от удалённого софта. Плюс накапливаются плагины, каждый со своими запросами на каждой странице.

Что чистить безопасно

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

Какой размер базы считать нормальным

200-500 МБ для сайта трёх лет с тысячей публикаций. Заметно больше при том же объёме контента это повод искать, что именно раздулось.

Когда проще переустановить с нуля

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

Передайте техническую часть в надёжные руки.

Слежу за хостингом, бэкапами и обновлениями. Когда что-то пойдёт не так – звоните мне, не своему программисту, не в спортзал и не маме.

Короткие вопросы по теме

Все вопросы по теме "CMS: WordPress, Битрикс, Tilda и другие"

Заявка

Обсудим задачу

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

Куда удобнее ответить?