Чистка базы данных WordPress
Чистка базы данных WordPress: замеры на трёх живых сайтах
Хостинговые инструкции по оптимизации WordPress почти всегда содержат пункт «почистите базу»: ревизии, спам-комментарии, протухшие транзиенты. Обещают лёгкость и скорость. Я прогнал такую чистку на трёх своих живых сайтах (один VPS, WordPress, MySQL 8.4, от 68 до 315 МБ на базу) с замерами до и после — и результаты оказались показательными, хотя и не такими, как ждёшь.
Что чистится
Стандартный набор «мусора» WordPress:
- Ревизии — копии записей, создаваемые при каждом сохранении. Живут в той же таблице
wp_posts, что и контент. - Спам-комментарии — Akismet их помечает, но держит в базе.
- Пингбеки/трекбеки — за годы набирается пара десятков.
- Осиротевший postmeta — мета-данные от давно удалённых записей.
- Протухшие транзиенты и старые логи планировщика (Action Scheduler).
Перед любыми действиями — полный дамп базы (mysqldump ... | gzip). Откат чистки иначе невозможен.
Что было и что стало
Три сайта на одном VPS, чистка одним и тем же набором команд (ревизии, спам, просроченные транзиенты, сироты, старые логи, затем OPTIMIZE TABLE).
| Сайт | База | Мусор до чистки | После чистки | Размер базы | TTFB |
|---|---|---|---|---|---|
| №1 — блог, 2 300+ записей | 315 МБ | 2 907 ревизий, 10 спама | 0 | 315 МБ → 315 МБ | не изменился |
| №2 — 9 000+ записей | 145 МБ | 14 спама, 130 тыс. строк логов планировщика | спам 0, логи почти не убыли | 145 МБ → 145 МБ | не изменился |
| №3 — небольшой журнал | 68 МБ | 244 ревизии, 8 спама, 25 пингбеков, 1 044 осиротевших postmeta | 0 | 68 МБ → 68 МБ | не изменился (сайт и так кэшируется) |
Скорость страниц не изменилась ни на одном сайте — ни в плюс, ни в минус. Размер баз не сдвинулся на мегабайт: основной объём — живой контент, а удалённые ревизии занимали единицы мегабайт.
Это не повод чистку не делать. Это повод понимать, что она даёт: меньше строк в таблицах (быстрее работают запросы в админке по post_type), ноль спама, свежие логи. Скорость фронтенда решают кэширование и тяжёлые плагины, а не «мусор» в таблицах.
Команды
Бэкап:
mysqldump --single-transaction --quick -uUSER -pPASS DB | gzip > backup.sql.gz
Ревизии батчами по 300 ID на вызов (xargs -n 300 разрезает поток на отдельные аргументы сам; -r не даёт запустить wp-cli на пустом списке):
wp post list --post_type=revision --format=ids --path=/путь/к/сайту | \
xargs -r -n 300 wp post delete --force --path=/путь/к/сайту
Ловушка: не собирайте ID в одну строку для xargs -I{} — пакет 101 102 103 придёт в wp-cli одним аргументом, приведётся к первому числу, и из трёхсот ревизий удалится одна.
Спам, просроченные транзиенты:
wp comment delete $(wp comment list --status=spam --format=ids --path=/путь/к/сайту) --force --path=/путь/к/сайту
wp transient delete --expired --path=/путь/к/сайту
Осиротевший postmeta:
DELETE pm FROM wp_postmeta pm LEFT JOIN wp_posts p ON p.ID = pm.post_id WHERE p.ID IS NULL;
Старые логи планировщика (только через обёртку-подзапрос, см. грабли):
DELETE FROM wp_actionscheduler_logs
WHERE log_id IN (
SELECT log_id FROM (
SELECT l.log_id FROM wp_actionscheduler_logs l
JOIN wp_actionscheduler_actions a ON a.action_id = l.action_id
WHERE a.last_attempt_gmt < NOW() - INTERVAL 30 DAY
) x
);
Грабли
- MySQL 8.4 отказывается OPTIMIZE-ить старые таблицы. Таблицы, приехавшие с MySQL 5.x, имеют нулевые дефолты дат (
0000-00-00 00:00:00), и пересборка в строгом режиме падает с «Invalid default value». Лечится ослаблением режима в той же сессии, без изменения схемы:SET SESSION sql_mode=''; OPTIMIZE TABLE wp_posts; - ERROR 1093 «can't specify target table for update» — MySQL не позволяет в DELETE выбирать из той же таблицы в подзапросе. Оборачиваем подзапрос в ещё один
SELECT ... FROM (...) x. - wp-cli и опции-JSON.
wp option update NAME '...' --format=jsonсохраняет значение как массив; плагины, ожидающие JSON-строку, на PHP 8.5 падают с TypeError — а падение в плагине кэша кладёт весь сайт. Лечится деактивацией черезwp plugin deactivate X --skip-plugins(обычная деактивация тоже падает — плагин грузится до команды). - Не удаляйте черновики (
post_status = 'draft') — это не мусор, это незаконченные тексты автора. В моём случае на одном сайте их было 63. - Сайт №3 уже был под кэшем WP-Optimize — страницы отдавались за 2–20 мс, поэтому эффект чистки на TTFB был бы незаметен в любом случае. Замеряйте скорость до и после на некэшируемых страницах.
Выводы
- Чистка базы — гигиена, а не оптимизация скорости. На трёх сайтах ни размер баз, ни скорость страниц не изменились.
- Реальную пользу видно в админке (меньше строк — шустрее фильтры и поиск) и в порядке (ноль спама).
- Перед чисткой — дамп; после — OPTIMIZE с учётом строгого режима MySQL 8.4.
- Если база действительно распухла от мусора, это видно сразу в аудите: таблицы-логи на десятки мегабайт, тысячи сирот. У меня максимумом оказалась таблица логов планировщика на 16 МБ.
Сравнение кэширования на тех же сайтах — в статье Кеширование WordPress: Breeze, Varnish и WP Fastest Cache, настройка Varnish — в Varnish для WordPress.
