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

Ревизии записей, автосохранения, спам-комментарии, временные данные, остатки от удалённых плагинов — всё это постепенно накапливается в базе.

На своих WordPress-сайтах я предпочитаю заранее настроить несколько простых вещей, чтобы база не разрасталась без необходимости. Это не волшебная оптимизация, которая мгновенно ускорит сайт в десять раз, но вполне полезная профилактика.

Расскажу, какие настройки и фрагменты кода для этого подходят.

Ограничиваем количество ревизий WordPress

Начну с самого простого — ревизий записей.

Когда мы редактируем статью, WordPress сохраняет предыдущие версии. Это удобно: можно откатить изменения, если что-то случайно удалили.

Но если статью редактировать десятки раз, количество ревизий может стать довольно большим.

Я предпочитаю оставлять одну или несколько последних версий, а не хранить всю историю изменений.

Для этого открываем файл wp-config.php в корневой папке сайта и добавляем:

Если хочется оставить небольшой запас, можно установить три (цифра это количество ревизий, я как правило ставлю 1):

PHP
define( 'WP_POST_REVISIONS', 3 );

А если история изменений вообще не нужна, ревизии можно отключить:

PHP
define( 'WP_POST_REVISIONS', false );

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

И ещё: добавлять нужно только один из приведённых вариантов, а не все сразу.

Меняем интервал автосохранения

По умолчанию WordPress использует интервал автосохранения 60 секунд.

Если хочется немного сократить частоту таких операций, можно увеличить интервал до пяти минут.

В тот же wp-config.php добавляем:

PHP
define( 'AUTOSAVE_INTERVAL', 300 );

Число 300 — это секунды.

Правда, здесь есть нюанс. Автосохранение защищает от потери текста, поэтому слишком сильно увеличивать интервал я бы не рекомендовал. Кроме того, в редакторе Gutenberg есть собственные механизмы сохранения, и эта константа не обязательно управляет всеми запросами редактора.

Лично мне кажется, что ограничение ревизий полезнее, чем попытки полностью избавиться от автосохранений.

Настраиваем автоматическую очистку базы данных раз в неделю

Ограничение ревизий помогает контролировать новые записи, но что делать с мусором, который уже накопился?

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

Для этого подходит встроенный механизм WP-Cron.

Ниже пример, который раз в неделю:

  • Удаляет обычные ревизии записей старше 30 дней.
  • Не затрагивает автосохранения.
  • Удаляет спам-комментарии и комментарии из корзины старше 30 дней.
  • Очищает просроченные временные данные (transients).

Я специально не добавляю сюда удаление черновиков, заказов WooCommerce и произвольных метаданных. В них могут находиться нужные данные.

Код еженедельной очистки

Лучше разместить его в отдельном мини-плагине, а не в wp-config.php или functions.php.

Создаём файл:

wp-content/mu-plugins/my-db-cleanup.php

Если папки mu-plugins нет, создаём её. Такие плагины WordPress загружает автоматически.

PHP
<?php
/**
 * Plugin Name: My Weekly Database Cleanup
 * Description: Еженедельная очистка базы WordPress.
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

// Регистрируем еженедельную задачу.
add_action( 'init', function () {

    if ( ! wp_next_scheduled( 'my_weekly_db_cleanup' ) ) {
        wp_schedule_event(
            time() + HOUR_IN_SECONDS,
            'weekly',
            'my_weekly_db_cleanup'
        );
    }

} );

// Запускаем очистку.
add_action( 'my_weekly_db_cleanup', function () {

    global $wpdb;

    $cutoff = gmdate(
        'Y-m-d H:i:s',
        time() - 30 * DAY_IN_SECONDS
    );

    // 1. Удаляем старые обычные ревизии.
    // Автосохранения не трогаем.
    $revision_ids = $wpdb->get_col(
        $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts}
             WHERE post_type = 'revision'
             AND post_name NOT LIKE %s
             AND post_date_gmt < %s
             LIMIT 500",
            '%-autosave%',
            $cutoff
        )
    );

    foreach ( $revision_ids as $id ) {
        wp_delete_post_revision( (int) $id );
    }

    // 2. Удаляем старый спам и комментарии в корзине.
    $comment_ids = $wpdb->get_col(
        $wpdb->prepare(
            "SELECT comment_ID FROM {$wpdb->comments}
             WHERE comment_approved IN ('spam', 'trash')
             AND comment_date_gmt < %s
             LIMIT 500",
            $cutoff
        )
    );

    foreach ( $comment_ids as $id ) {
        wp_delete_comment( (int) $id, true );
    }

    // 3. Очищаем просроченные transients.
    if ( function_exists( 'delete_expired_transients' ) ) {
        delete_expired_transients( true );
    }

} );

В примере за один запуск обрабатывается не более 500 ревизий и 500 комментариев. Это сделано специально, чтобы не создавать чрезмерную нагрузку на сервер.

Если мусора накопилось очень много, очистка займёт несколько недель. Для большого сайта лучше использовать отдельную пакетную задачу с более частым запуском.

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

Ещё стоит учитывать, что WP-Cron не является настоящим системным планировщиком. Если на сайт никто не заходит, задача может выполниться позже запланированного времени.

Уменьшаем срок хранения корзины

Ещё одна настройка, которую я считаю полезной, — сокращение срока хранения удалённых материалов.

По умолчанию WordPress хранит содержимое корзины 30 дней. Для некоторых сайтов это слишком долго.

В wp-config.php можно добавить:

JavaScript
define( 'EMPTY_TRASH_DAYS', 7 );
Теперь WordPress будет удалять материалы из корзины примерно через семь дней.

Можно установить и другой срок, например 14 дней.

Я бы не ставил ноль: возможность восстановить случайно удалённую статью иногда очень выручает.

И обратите внимание: WordPress уже умеет автоматически очищать корзину. Для этого не требуется писать отдельный скрипт.

Удаляем просроченные transients

В WordPress существует механизм Transients API. Он используется для временного хранения данных: результатов запросов, кэша плагинов и другой информации.

Без постоянного объектного кэша эти данные обычно сохраняются в таблице wp_options.

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

Поэтому просроченные transients тоже стоит учитывать при обслуживании сайта.

В нашем еженедельном скрипте для этого уже предусмотрена команда:

PHP
delete_expired_transients( true );

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

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

Не забываем про WooCommerce и другие плагины

Если на сайте установлен WooCommerce, ситуация немного сложнее.

Интернет-магазин хранит заказы, служебные данные, фоновые задачи, сессии и другую информацию. Причём часть данных может находиться в отдельных таблицах.

Поэтому для магазина я бы не применял универсальные SQL-запросы, которые массово удаляют старые строки по дате.

Лучше использовать встроенные инструменты обслуживания WooCommerce и проверять, какие именно данные разрешено очищать.

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

Мой набор настроек для WordPress

Если собрать основные настройки в одном месте, получится такой блок для wp-config.php:

PHP
/**
 * Мои настройки обслуживания WordPress.
 */

// Храним максимум 3 обычные ревизии.
define( 'WP_POST_REVISIONS', 3 );

// Автосохранение каждые 5 минут.
define( 'AUTOSAVE_INTERVAL', 300 );

// Очищаем корзину через 7 дней.
define( 'EMPTY_TRASH_DAYS', 7 );

Размещать его нужно до строки:

/* That's all, stop editing! Happy publishing. */

И обязательно проверять, не объявлены ли эти константы ранее.

Для еженедельной очистки используется отдельный мини-плагин из третьего раздела.

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

Материал оказался полезным?
Поделитесь им с тем, кто сейчас решает похожую задачу. Это поддержит журнал.