WordPress на VPS часто упирается не в «мощность сервера», а в то, как именно база данных исполняет запросы. Чем больше сайт растёт, тем заметнее становятся лишние записи в таблицах, неудачные индексы (или их отсутствие) и накопленная фрагментация после удалений. Результат обычно один: дольше грузятся страницы и проседают фоновые задачи.
Оптимизация базы WordPress на VPS обычно складывается из двух направлений. Первое — индексы: убедиться, что самые частые запросы получают доступ к данным без полного перебора строк. Второе — очистка: убрать мусор, который раздувает таблицы и увеличивает время поиска даже при наличии индексов.
Когда проблема в базе: симптомы и быстрая диагностика
Прежде чем добавлять индексы или чистить таблицы, важно понять, что узкое место действительно в MySQL/MariaDB, а не в PHP, кэше или внешнем API. Вот признаки, на которые обычно реагируют первыми.
- Растёт время генерации страниц, а CPU в PHP-процессе не выглядит перегруженным.
- Во время пиковых нагрузок MySQL начинает сильнее грузить диск и держать больше активных соединений.
- В логах приложения появляются таймауты и ошибки типа «Lock wait timeout exceeded» или долгие запросы.
- Статистика MySQL показывает заметный рост InnoDB-reads и медленные запросы в течение минут, а не секунд.
Дальше стоит собрать данные, а не угадывать. Самый практичный путь — включить slow query log и посмотреть, какие запросы срабатывают дольше порога. На VPS это обычно делается через конфиг MySQL/MariaDB или через параметры в панели управления хостинга.
Полезно также посмотреть текущую нагрузку:
- сколько активных запросов выполняется одновременно;
- какие таблицы «тянут» больше всего I/O;
- есть ли рост размеров файлов данных (особенно после массовых удалений).
Если slow query log уже включён, выпишите 10–30 самых медленных SQL-запросов за последние часы. Затем группируйте их по типу: выборка постов, выборка метаданных, термины таксономий, комментарии, опции. По этому разбиению станет понятно, какие индексы действительно нужны.
Индексы в WordPress: какие таблицы важны и как проверить текущие
В WordPress нагрузка на базу чаще всего концентрируется в нескольких таблицах:
- wpposts: списки постов, фильтры по posttype и post_status, сортировки по дате и ID.
- wppostmeta: метаданные постов, тяжёлые join’ы при любых metaquery.
- wp_options: настройки сайта, транзиенты (transients), автозагружаемые опции (autoload).
- wptermrelationships и wp_terms: связь объектов с терминами, таксономии.
- wp_commentmeta (если используется): метаданные комментариев.
- wp_comments: фильтрация комментариев по статусам.
- wpusers и wpusermeta: редко, но при авторизации/профилях и некоторых плагинах.
Чтобы понять, «не хватает индексов» или проблема в форме запроса, начинайте с проверки существующих индексов. Логика простая: если запрос в EXPLAIN показывает full scan или отсутствие подходящего ключа, тогда индексы действительно обсуждаются.
Проверка индексов делается командой уровня СУБД, например:
- SHOW INDEX FROM wp_posts;
- SHOW INDEX FROM wp_postmeta;
Дальше ключевое — EXPLAIN для конкретного запроса из slow query log. Не нужно брать абстрактные «примерные запросы» из интернета. Возьмите реальные SQL, которые реально тормозят, и прогоните их через EXPLAIN (или EXPLAIN ANALYZE, если поддерживается в вашей версии и доступно в окружении).
На что смотреть в EXPLAIN:
- key: используется ли индекс или значение NULL;
- rows: сколько строк предполагается просканировать;
- type: хуже всего обычно выглядит ALL (полный перебор);
- possible_keys: какие индексы вообще могли бы подойти.
Важно: индексы нельзя добавлять «наугад». Каждый индекс ускоряет одни запросы и замедляет другие (особенно вставки/обновления), плюс увеличивает объём диска. Поэтому работайте от конкретных запросов.
Добавление и настройка индексов: практический план
План действий стоит выстроить так, чтобы избежать двух типичных проблем: добавили не то и сломали производительность, или добавили и столкнулись с ошибками на этапе ALTER TABLE.
1) Подготовьте безопасную среду
Перед любыми ALTER TABLE:
- сделайте бэкап базы (на VPS обычно достаточно логического бэкапа или снимка диска);
- проверьте наличие места на диске (ALTER иногда требует временного пространства);
- если есть staging-среда, прогоните операции там.
Индексы — это изменения структуры. Они могут занять время и поставить блокировки, особенно на больших таблицах.
2) Выберите, какие запросы “лечить” индексами
Не пытайтесь ускорить всё сразу. Сначала возьмите топ-3–5 самых медленных запросов и определите, что у них общего.
Чаще всего для WordPress встречаются такие схемы:
- wpposts: запросы вида выборки по posttype, post_status с сортировкой.
- wppostmeta: выборка по metakey и привязка к postid или JOIN по postid.
- wpoptions: выборка по optionname (особенно autoload=’yes’).
- таксономии: JOIN через termrelationships по objectid и termtaxonomyid.
Если в EXPLAIN видно, что фильтры по нужным полям не используют индекс, это и есть кандидаты на добавление.
3) Сформируйте индекс под конкретный предикат
Правило простое: индекс должен соответствовать тому, как фильтруется и сортируется выборка.
Примеры логики:
- Если запрос почти всегда фильтрует по metakey и затем ограничивает результат, сначала нужен индекс по metakey.
- Если запрос сначала выбирает по postid, а затем читает мета-строки, индекс по postid будет полезен.
- Если запрос одновременно фильтрует по нескольким полям и сортирует, чаще помогает составной индекс, чем набор одиночных.
Но есть важное ограничение: составные индексы полезны только тогда, когда запрос реально попадает в левую часть индекса. В противном случае индекс формально присутствует, но запрос не использует его.
4) Не индексируйте текст бездумно
meta_value и похожие поля часто имеют тип TEXT/LONGTEXT. Полноценный индекс на текст может быть дорогим по размеру и может упереться в лимиты длины ключа.
Если вам нужен поиск по части значения, обычно рассматривают индекс по префиксу (например, первые N символов). Но это решение нужно проверять тестовыми запросами: что реально ускорится и как изменится выборка.
5) Как выполнять ALTER TABLE на больших таблицах
На крупных таблицах ALTER TABLE может выполняться долго. Планируйте окно обслуживания или делайте изменения по очереди.
Практический подход:
- сначала добавьте один индекс для одного семейства запросов;
- дождитесь завершения;
- снова прогоните EXPLAIN на проблемном запросе;
- только потом переходите к следующему кандидату.
Так вы поймаете эффекты без гаданий.
6) Проверка результата
После добавления индексов:
- сравните slow query log (хотя бы качественно);
- проверьте EXPLAIN: key должен появиться, а rows — уменьшиться;
- отслеживайте метрики приложения: время ответа, количество ошибок, загрузку MySQL.
Если EXPLAIN выглядит лучше, а пользовательские метрики не улучшаются, причина может быть в другом узком месте: кэш отсутствует, страница собирается другими запросами или есть проблемы с блокировками.
Как правильно чистить базу WordPress: что именно удалять
Очистка базы чаще всего даёт заметный эффект по двум причинам:
- уменьшаются размеры таблиц и индексов, а значит меньше данных нужно просматривать;
- пропадают устаревшие записи, которые стабильно участвуют в выборках.
Но чистка — зона риска. WordPress хранит в таблицах не только «мусор», а и данные, которые влияют на корректность сайта. Поэтому удаляйте по понятным критериям и всегда начинайте с бэкапа.
Самые распространённые источники раздувания:
- ревизии записей (wpposts с posttype=’revision’);
- транзиенты (wpoptions, optionname вида transient и sitetransient_), особенно если очищаются редко;
- автозагружаемые опции (wp_options, autoload=’yes’): слишком много таких записей может увеличивать время загрузки опций;
- спам-комментарии и ненужные записи из комментариев;
- неактуальные записи плагинов (история задач, неиспользуемые временные таблицы и т.д.).
Для старта обычно достаточно ревизий, транзиентов и спама. Это даёт максимальный эффект без сложной логики.
Очистка ревизий, транзиентов и спама: безопасные шаги
Ревизии постов (wp_posts)
Ревизии растут очень быстро на сайтах с активным редактированием. Самое частое решение — ограничить количество ревизий или удалять старые.
Варианты подхода:
- ограничить ревизии на уровне настроек (через конфигурацию WordPress);
- периодически удалять ревизии старше N дней.
Если вы удаляете ревизии вручную, ключевое условие — удалять только post_type=’revision’. Не трогайте обычные записи и страницы.
Коммерческая логика тут простая: если ревизий слишком много, то сайт начинает тяжелее работать не из-за одной большой таблицы, а из-за того, что часть запросов и фоновых операций начинает сталкиваться с огромным объёмом данных.
Транзиенты (wp_options)
Транзиенты — это кэш временных результатов. Когда истекает срок, данные должны исчезать. На практике они иногда копятся, если задачи очистки не успевают или плагин создаёт транзиенты слишком активно.
При ручной очистке важно не сломать сериализованные значения и не удалить действующие кэши. Самый надёжный путь — удалять транзиенты через инструмент, который понимает формат WordPress:
- через WP-CLI команды, связанные с транзиентами, если они доступны в вашей сборке;
- через специализированный инструмент/плагин, который работает с API WordPress.
Если же вы всё делаете SQL-операторами, нужно понимать структуру значения и то, где хранится время истечения. Это часто превращает очистку в «тонкую настройку» под конкретную версию/реализацию WordPress и плагинов, поэтому лучше выбрать способ, который следует ожиданиям ядра.
Практический критерий результата: после очистки уменьшается размер wp_options и падают некоторые доли нагрузки на запросы к опциям.
Спам и удалённые комментарии
Комментарии могут собираться в мусорных статусах. Удалённые и помеченные как спам записи могут участвовать в выборках, если не отфильтрованы корректно.
Безопасный подход:
- чистить только по статусу (spam/trash), а не по id «в целом»;
- не трогать модерацию, если у вас есть процесс ручного контроля.
Для больших сайтов лучше делать очистку поэтапно, чтобы не получить блокировки надолго.
Оптимизация таблиц: OPTIMIZE TABLE и ANALYZE TABLE
После массовых удалений таблицы на InnoDB могут разрастаться из-за освобождённых, но физически не возвращённых страниц. Отсюда появляется эффект: вы «удалили», а размер файлов почти не изменился, а скорость не так сильно выросла, как ожидалось.
В MySQL/MariaDB обычно используют два оператора:
- ANALYZE TABLE обновляет статистику для оптимизатора;
- OPTIMIZE TABLE пытается уплотнить таблицу и перестроить внутренности, что иногда возвращает место и снижает фрагментацию.
С практической точки зрения:
- ANALYZE TABLE можно запускать чаще, это обычно меньше влияет на простои.
- OPTIMIZE TABLE на больших таблицах может занять много времени и держать блокировки. Его разумно делать в окно с низкой нагрузкой.
Что именно запускать:
- после очистки ревизий и мусора обязательно имеет смысл прогнать ANALYZE для затронутых таблиц;
- OPTIMIZE — только для крупных таблиц, где вы видите явную фрагментацию или где оптимизация дала эффект в тесте.
Обязательно оценивайте результат через измеримые признаки: скорость проблемных запросов, запись в slow query log, активность блокировок.
Настройки WordPress, которые уменьшают нагрузку на базу
Индексы и очистка влияют на прямые запросы к MySQL, но не отменяют системных причин нагрузки. Несколько настроек и практик помогают снизить количество запросов к базе и уменьшить общий вес данных, с которым СУБД работает.
- Кэш объектов (например, через Redis/Memcached).
Это сокращает повторные запросы к wpoptions и wppostmeta. Особенно заметно на страницах с большим количеством метаданных.
- Ограничение частоты обновлений и фоновых операций.
Некоторые фоновые задачи создают нагрузку, которая не видна при одном просмотре страницы, но проявляется на интервалах.
- Контроль автозагружаемых опций.
Если autoload=’yes’ становится слишком большим, WordPress держит больше опций в памяти и дольше читает при старте запроса.
- Приведение кэширования и индексации терминов/таксономий к нормальному состоянию.
Иногда проблема появляется из-за комбинации плагинов: один влияет на запросы, другой добавляет новые условия фильтрации.
Всё это не заменяет индексы и очистку, но делает результат стабильнее.
Типичные ошибки при индексации и очистке базы WordPress
Ошибки обычно повторяются, и их лучше избежать заранее.
- Добавляют индексы «чтобы было».
Если индекс не связан с реальным медленным запросом, он может ухудшить вставки и не ускорить чтение. Делайте изменения через EXPLAIN, от конкретного запроса.
- Меняют структуру на рабочем сервере без плана блокировок.
ALTER TABLE может занимать время. Планируйте окно обслуживания, особенно на таблицах wpposts и wppostmeta.
- Чистят транзиенты SQL-ом без понимания формата значений.
Транзиенты сериализуются. Ошибка очистки может привести к невалидным значениям и странным эффектам в кэше.
- Удаляют автозагружаемые опции без проверки.
wp_options, где autoload=’yes’, часто критична для корректной работы. Удаление «наугад» ведёт к багам, которые сложно диагностировать.
- Запускают OPTIMIZE TABLE на пике нагрузки.
Даже если эффект есть, цена может быть высокой по времени и блокировкам.
- Делают очистку, но не обновляют статистику.
После удаления данных оптимизатор может работать с устаревшими оценками. Поэтому ANALYZE TABLE после крупных удалений — логичный шаг.
Чек-лист работ на VPS: индексы и очистка по шагам
Ниже — практичный порядок, который обычно быстрее приводит к улучшениям, чем хаотичные действия.
- Шаг 1. Соберите реальные данные: включите slow query log (если он выключен) и выпишите 10–30 самых медленных запросов.
- Шаг 2. Для топ-запросов прогоните EXPLAIN и определите, где отсутствует индекс (key=NULL) или идёт полный перебор (type=ALL).
- Шаг 3. Проверьте существующие индексы SHOW INDEX для затронутых таблиц (wpposts, wppostmeta, wpoptions, wpterm_relationships).
- Шаг 4. Сделайте бэкап и, по возможности, проверьте изменения в staging.
- Шаг 5. Добавляйте индексы по одному, под конкретные запросы. После каждого изменения проверьте EXPLAIN и повторите тестирование.
- Шаг 6. Почистите мусор: ревизии (только post_type=’revision’), транзиенты через инструменты, которые следуют логике WordPress, спам/треш комментариев по статусам.
- Шаг 7. Запустите ANALYZE TABLE на затронутых таблицах.
- Шаг 8. OPTIMIZE TABLE применяйте точечно и в окно обслуживания, если после очистки вы видите фрагментацию/эффект по статистике.
- Шаг 9. Сравните итоги: уменьшились ли время выполнения проблемных запросов и нагрузка на MySQL, улучшилось ли время ответа сайта.
- Шаг 10. Закрепите результат: настройте ограничение ревизий и подход к транзиентам, чтобы повторное накопление было менее вероятным.
Как понять, что оптимизация сработала
После индексов и очистки важно не ориентироваться только на «ощущения». Минимальный набор проверок:
- В slow query log меньше записей с теми же SQL или они стали короче по времени.
- EXPLAIN для проблемных запросов показывает использование индекса и снижение предполагаемого количества строк.
- В метриках MySQL уменьшается нагрузка по чтениям и время выполнения рабочих запросов.
- В приложении снижается p95/p99 время ответа (если вы смотрите перцентиль), и реже появляются таймауты.
Если этого нет, почти всегда причина в одном из трёх:
- индекс добавлен не к тому запросу или не к тем условиям фильтрации;
- запрос стал хуже из-за изменений плана или избыточных условий;
- осталась другая проблема (например, отсутствие кэша объектов или слишком тяжёлые выборки в PHP).
Итог: что делать на VPS, чтобы база WordPress работала быстрее
Оптимизация базы данных WordPress на VPS обычно даёт лучший эффект, когда вы делаете две вещи последовательно: приводите к делу индексы и убираете накопленный мусор. Индексы лечат причину медленных выборок, а очистка уменьшает объём данных, с которым СУБД вынуждена работать.
Если вы давно не трогали структуру базы и таблицы заметно разрослись, начинайте с диагностики медленных запросов и EXPLAIN. Затем выполняйте очистку ревизий, транзиентов и спама безопасными методами, а после — обновляйте статистику таблиц. После этого только точечно добавляйте индексы под реальные запросы и проверяйте эффект.
Сделайте один цикл «диагностика → тест индекса → очистка → анализ → повтор», и вы увидите улучшения не на уровне предположений, а в логах запросов и измеримых метриках.

