Логотип seo-prodvizhenie-biznesa.ru
+7 (921) 333-77-45

База WordPress раздулась до двух гигабайт: что вычистить, а что тронешь — сломаешь сайт

База WordPress раздулась до двух гигабайт: что вычистить, а что тронешь — сломаешь сайт
Анатолий Кузнецов
Анатолий Кузнецов
SEO-оптимизатор с 20-летним стажем. Автор блога seo-prodvizhenie-biznesa.ru о продвижении и доработке сайтов.

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

Ниже — как увидеть, какие таблицы съели место; почему одна статья превращается в тридцать строк; чем опасна колонка автозагрузки и почему тормозит именно она, а не гигабайт ревизий; что оставляют после себя удалённые плагины; список неприкасаемого; и почему после чистки файл базы того же размера.

С чего начать: как за пять минут увидеть, какие таблицы съели гигабайты

Первое действие — замер, а не чистка. Пока не знаете, где лежит вес, чистилка работает наугад: снесёт двести мегабайт ревизий и не тронет полтора гигабайта журнала блокировок. Откройте phpMyAdmin и отсортируйте таблицы по размеру: первые три строки обычно и есть весь ваш «гигабайт». В консоли то же даёт команда wp db size --tables.

Таблицы ядра известны заранее: wp_posts, wp_postmeta, wp_options, wp_comments, wp_commentmeta, wp_terms, wp_termmeta, wp_term_taxonomy, wp_term_relationships, wp_users, wp_usermeta, wp_links. Всё остальное добавили плагины. Префикс wp_ у большинства сайтов свой — его задаёт переменная $table_prefix в wp-config.php, так что в конфиг надо заглянуть прежде, чем копировать чужие запросы. Тяжелее всего почти всегда wp_postmeta и wp_options.

Что растёт Где лежит Чем чистить Можно ли удалять
Ревизии и автосохранения wp_posts и их мета WP-CLI, чистилка, константа на будущее да, теряете историю правок
Истёкшие transients wp_options, парами строк wp transient delete --expired да, это кэш
Опции с автозагрузкой колонка autoload разбор списка руками только опознав владельца ключа
Таблицы удалённых плагинов таблицы с чужим именем вручную, после опознания да, если плагин точно снесён
Вёрстка конструктора страниц _elementor_data ничем нет, страница станет пустой

Ревизии и автосохранения: почему одна статья превращается в тридцать строк

При каждом сохранении записи WordPress добавляет в wp_posts строку с post_type='revision', где в post_parent стоит ID записи. Текст копируется целиком — не разница с прошлой версией, а весь контент: статья на сорок тысяч знаков, сохранённая двадцать раз, лежит в базе двадцать один раз. Автосохранения — те же ревизии с именем вида <ID>-autosave-v1 в поле post_name; они перезаписываются, поэтому объём дают ручные нажатия «Обновить».

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

Как ограничить ревизии на будущее и что делать с накопленными

Ограничение задаёт документированная константа в wp-config.php выше строки подключения wp-settings.php: define( 'WP_POST_REVISIONS', 3 );. Число — сколько последних ревизий оставлять у записи, false отключает механизм, true — поведение по умолчанию, без ограничения. Оговорка, о которой молчат: константа работает только вперёд, накопленные две тысячи ревизий сами не исчезнут.

Сценарий Значение константы Следствие
Блог, который пишет и правит один человек 3 откат на пару шагов есть, объём под контролем
Магазин с массовой правкой карточек 2 или false правки описаний почти не добавляют объёма
База уже упёрлась в лимит хостинга 3 плюс удаление накопленных место освобождается сразу, дальше рост ограничен

Накопленное удаляют тремя путями. WP-CLI — выборкой ID по типу и передачей в wp post delete: работает штатная функция, которая подчищает связанную мета. Плагин-чистилка — быстро, но с оглядкой на то, что она предложит заодно. Прямой запрос в phpMyAdmin опаснее всего: DELETE из wp_posts оставит мета-строки ревизий сиротами.

При десятках тысяч ревизий удаляйте партиями по одной-две тысячи строк. Большой DELETE на медленном хостинге упирается в лимит времени, обрывается на середине и держит блокировки — тот случай, когда из-за чистки приходится возвращать сайт после критической ошибки, хотя кода никто не трогал.

Transients: кэш, который никто не убирает

Transients — кэш со сроком жизни, который WordPress по умолчанию держит в wp_options. На каждый элемент пишутся две строки: _transient_<имя> со значением и _transient_timeout_<имя> со временем истечения; у сетевых установок — _site_transient_….

Дальше неприятное. Истёкший transient удаляется не по таймеру, а в момент обращения к нему. А к тому, к чему больше никто не обращается, никто и не обращается: плагин снесли, разовая задача выполнилась, функция переписана и спрашивает другой ключ. Строки остаются навсегда, и в wp_options набегают сотни тысяч пар от кэша, чей владелец давно удалён. Чистится это командой wp transient delete --expired.

Отдельно о больших значениях: иногда в кэш кладут сериализованный массив на несколько мегабайт — ответ сервиса, список товаров, карту редиректов. Такая строка весит больше тысячи ревизий, а с автозагрузкой даёт проблему следующего раздела.

Autoload — единственная часть базы, которая тормозит каждую страницу

В wp_options есть колонка autoload. Всё, что в ней помечено, читается из базы при каждом запросе к сайту — на главной, в карточке товара, на статье блога, в админке. Не по необходимости, а всегда, одним запросом на старте.

Арифметика тут обратная интуиции. Гигабайт ревизий на время ответа почти не влияет, а четыре мегабайта в автозагружаемых опциях влияют прямо: их надо вытащить из базы, передать в PHP и распаковать — и так на каждый хит. Именно здесь база превращается в проблему скорости, а не в строчку статистики у хостера. Как это складывается с остальными задержками, я разбирал в материале про скорость WordPress и то, что на самом деле тормозит сайт.

Смотреть автозагрузку удобнее запросом, который сортирует опции по размеру значения: сразу видно десяток ключей, составляющих почти весь объём. Владельца опознаёте по префиксу в имени. Снимать флаг стоит с того, что нужно редко: настройки административного экрана, кэш разового отчёта.

С WordPress 6.6 ядро само не ставит автозагрузку новым и изменяемым опциям, размер значения которых превышает порог: за это отвечает функция wp_filter_default_autoload_value_via_option_size(), порог меняется фильтром wp_max_autoloaded_option_size. Оговорка: защита работает только вперёд, обновление ядра тяжёлую опцию не разгрузит. Перед такими работами полезно перечитать, как обновлять WordPress и не сломать сайт.

Таблицы и опции, которые оставили после себя удалённые плагины

Главное: удалённый плагин почти никогда не удаляет свои таблицы и опции. Механизм есть — файл uninstall.php или хук деактивации, — но авторы им пользуются редко и осознанно, чтобы при повторной установке не потерялись настройки. Следствие — база с таблицами от плагинов, снесённых три года назад.

Плагин Его таблицы Что копится Остаётся после удаления
Action Scheduler (идёт с WooCommerce и рядом плагинов) wp_actionscheduler_actions, wp_actionscheduler_logs очередь задач и логи выполненных, тысячами строк да
Redirection wp_redirection_404, wp_redirection_logs журнал обращений к несуществующим адресам, лог редиректов да
Wordfence wp_wfhits, wp_wffilemods и другие wp_wf* журнал обращений и слепки файлов да
WooCommerce wp_wc_*, wp_woocommerce_sessions, wp_woocommerce_order_items справочники, сессии покупателей, состав заказов да

Опознание простое: отрежьте префикс сайта и поищите остаток имени в каталоге wp-content/plugins. Нашли — таблица рабочая. Не нашли — ищите имя в поиске: плагины из каталога wordpress.org документируют свои схемы, владелец находится за минуту.

Опции удалённых плагинов обычно мелкие, охотиться на них ради объёма смысла нет. Смысл появляется, когда такая опция помечена на автозагрузку и весит мегабайты: сайт читает её на каждом запросе в пустоту. Вывод тот же, к которому я прихожу в разговоре о том, сколько плагинов нужно на самом деле: каждый плагин оставляет след в базе, и след переживает сам плагин.

Логи, журналы 404 и очереди задач: как перестать писать историю в базу

Это самый недооценённый источник роста. Ревизии растут пропорционально вашей работе, а журнал 404 — пропорционально работе ботов, то есть непрерывно. Приходит сканер, перебирает тысячи адресов — и таблица прибавляет по строке на каждый запрос, а за год выходит тяжелее всего контента при нулевой пользе. Так же ведут себя логи очереди задач и журнал охранного плагина. Лечится настройкой, а не чисткой:

  • Откройте настройки каждого плагина со своей таблицей и найдите раздел про журнал.
  • Выставьте срок хранения записей: для журнала 404 недели хватает с запасом.
  • Где журнал не нужен совсем — выключите. Он полезен неделю после переноса сайта, а не постоянно.
  • Накопленное почистите кнопкой внутри плагина: он знает про свои связанные таблицы, а вы можете о них не знать.

Сироты в мета-таблицах, спам и корзина комментариев

Сирота — мета-строка без родителя: запись в wp_postmeta с post_id, которого в wp_posts уже нет; мета удалённого комментария; связь рубрики с несуществующей записью в wp_term_relationships. Берутся они из удаления записей прямыми запросами мимо функций WordPress, кривого импорта с обрывом по таймауту и сноса плагинов со своими типами записей. Сюда же — уборка после взлома: когда с сайта выметают тысячи сгенерированных страниц, мета от них остаётся почти всегда, об этом я писал, разбирая, как убирать спам-страницы из индекса после взлома.

Считают сирот запросом с проверкой существования родителя: сначала SELECT COUNT(*), чтобы увидеть масштаб, потом удаление, при десятках тысяч — партиями. Это единственная категория, где «безопасно» держится на точности запроса: лишний NOT или перепутанный префикс удалят живую мета вместо мёртвой. Родственник сирот — _oembed_ с хэшем в имени, кэш превью вставленных видео; его и метки _edit_lock, _edit_last удалять можно без последствий.

Спам живёт в wp_comments со значением comment_approved='spam', удалённое — со 'trash', и само не исчезает. Убирать надо кнопками «Очистить спам» и «Очистить корзину»: антиспам дописывает служебные поля к каждому проверенному комментарию, и прямое удаление через базу их оставит.

Что тронешь — сломаешь сайт: список неприкасаемого

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

Ключ или таблица Что это Что отвалится, если удалить
wp_users, wp_usermeta пользователи и их настройки вход в админку, авторы записей, роли и права
wp_terms, wp_term_taxonomy, wp_term_relationships рубрики, метки и связи с записями у записей отвалятся рубрики, рассыплются разделы и адреса категорий
_wp_attached_file, _wp_attachment_metadata путь к файлу вложения и его размеры картинки перестанут отдаваться, пропадут превью
_thumbnail_id привязка миниатюры к записи у статей и товаров пропадут обложки в списках и в соцсетях
_elementor_data, _elementor_css вёрстка страницы в конструкторе страница станет пустой, вернуть можно только из копии
Записи с post_type='attachment' медиабиблиотека картинки отвяжутся от записей, файлы останутся сиротами на диске

Две ловушки. Первая: post_status='auto-draft' удалять можно, это пустые черновики от нажатия «Добавить запись». А post_type='attachment' удалять нельзя, хотя в списке типов он стоит рядом и чистилки иногда предлагают его как мусор.

Вторая: _elementor_data на большой странице — сотни килобайт сериализованного кода, идеальная на вид цель. Но это и есть сама страница. Хотите уменьшить вес здесь — сокращайте число страниц, собранных конструктором, а не чистите их мета.

Почему после чистки база того же размера и как вернуть место на диске

Удалили миллион строк, а размер базы в панели не изменился — это не ошибка чистки. В InnoDB, а это движок таблиц у современного WordPress, удаление строк освобождает место внутри файла таблицы, помечая его доступным для новых записей. Сам файл не сжимается, и система по-прежнему видит те же гигабайты.

Значит, база перестанет расти, но занятое на диске вернётся только после пересоздания таблицы. Делает это команда OPTIMIZE TABLE, которая для InnoDB выполняется как ALTER TABLE … FORCE: таблица перестраивается, файл получается компактным. Операция блокирующая, требует места на диске под обе копии таблицы и делается только после проверенной копии и в низкий трафик. Регулярно гонять её смысла нет.

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

Как это связано с позициями в поиске и чем чистить

Здесь важно не преувеличивать, потому что вокруг размера базы много запугивания. Поисковику размер не виден — ни Яндекс, ни Google не знают, сколько у вас гигабайт в wp_postmeta. Виден результат: время ответа сервера. Автозагружаемые опции и медленные запросы к мета-таблицам растягивают генерацию страницы, и эта цепочка реальна. Остальные её звенья — в материале про технические причины, по которым сайт не растёт в Яндексе.

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

Из каталога wordpress.org задачу решают три инструмента: WP-Optimize умеет чистку и пересоздание таблиц, Advanced Database Cleaner опознаёт таблицы неизвестного происхождения, WP Sweep чистит штатными функциями и не оставляет сирот. Но чистилка — тоже плагин: комбайн сам добавляет опции и задачи в планировщик. Мой порядок — включить, почистить, выключить и удалить.

Готовые наборы «почистить базу одним запросом» запускать не стоит: половина написана под старые версии, часть удаляет то, что вам удалять нельзя, и почти все молчат про префикс. Когда разбираться самому не хочется, есть доработка сайта отдельной услугой; на том же принципе — сначала техническое состояние, потом рост — построено и всё остальное SEO-продвижение сайта на WordPress с чисткой базы.

Порядок работ на один вечер: чеклист с резервной копией

  1. Дамп базы. mysqldump или «Экспорт» в phpMyAdmin. Откройте файл и убедитесь, что он не обрезан на середине INSERT.
  2. Замер. Список таблиц по размеру, три-пять верхних строк выпишите с числами.
  3. Автозагрузка. Десяток самых тяжёлых опций: флаг снять или удалить остатки снесённых плагинов.
  4. Истёкшие transients. Одна команда или одна кнопка.
  5. Ревизии. Константа в wp-config.php, затем удаление накопленных партиями.
  6. Спам и корзина комментариев. Штатными кнопками, не запросом.
  7. Журналы плагинов. Срок хранения в настройках, чистка средствами плагина.
  8. Чужие таблицы. Только те, чей владелец точно снесён с сайта.
  9. Сироты. Сначала COUNT, потом удаление, партиями.
  10. Пересоздание таблиц. По самым крупным, в низкий трафик.
  11. Проверка сайта. Главная, карточка товара, страница конструктора, редактор: обложки на месте, рубрики не отвалились.
  12. Запись в календарь. Что чистили и какие были числа до и после.

Коротко

  • Начинайте с замера: таблицы по размеру. Вес почти всегда в wp_postmeta и wp_options, префикс — в wp-config.php.
  • Ревизии копируют текст записи целиком: бьют по дампу и лимиту хостинга, а не по скорости.
  • Константа WP_POST_REVISIONS действует только вперёд, накопленное удаляйте отдельно и партиями.
  • Истёкшие transients не удаляются по таймеру: если к ключу никто не обращается, строки остаются.
  • Автозагружаемые опции читаются на каждый запрос; защита ядра 6.6 работает только для новых и изменяемых.
  • Удалённый плагин почти никогда не удаляет свои таблицы: опознайте владельца до удаления.
  • Журналы 404 и логи очередей лечатся сроком хранения, а не чисткой.
  • Сирот сначала считайте, потом удаляйте; спам убирайте штатными кнопками.
  • Неприкасаемое: пользователи, таксономии, мета вложений, _thumbnail_id, поля конструкторов и ACF, заказы магазина, вложения.
  • После DELETE файл InnoDB не сжимается: место вернёт OPTIMIZE TABLE или заливка дампа в новую базу.
  • Поисковику виден не размер базы, а время ответа сервера; позиции чистка сама не поднимает.
  • Порядок на вечер: дамп, замер, автозагрузка, кэш, ревизии, комментарии, журналы, чужие таблицы, сироты, проверка.

Увеличьте позиции и продажи вашего сайта

Профессиональное SEO-продвижение с гарантией результата. Выберите подходящую услугу:

Анатолий Кузнецов — SEO-оптимизатор

Остались вопросы по продвижению?

Меня зовут Анатолий Кузнецов, я SEO-оптимизатор с 20-летним стажем. Разберу ваш сайт, отвечу на вопросы и подскажу, что улучшить для роста позиций в Яндексе и Google.

Связаться со мной →

Комментарии

Сергей

Отсортировал таблицы по размеру и обалдел: postmeta почти семьсот мегабайт, большая часть — строки с oembed и хэшем. В статьях было много вставленных видео, которые я потом вынес в другой формат.

Марина

У нас хостинг ограничивает базу, и мы уже в потолок. Хочу просто удалить все ревизии одним запросом через phpMyAdmin, там же ничего сложного. Это правда опасно или вы перестраховываетесь?

Анатолий Кузнецов автор

Опасность не в запросе, а в двух его последствиях. Первое: мета удаляемых ревизий останется в postmeta сиротами, и вы создадите себе вторую задачу. Второе: при десятках тысяч строк заход упрётся в лимит времени и оборвётся на середине. Делайте партиями, а лучше штатной функцией — она подчищает связанное.

Дмитрий

У меня магазин, и самой тяжёлой оказалась таблица логов планировщика задач, пришла с товарным плагином. Выставил срок хранения — рост прекратился. А до этого чистил ревизии и удивлялся, почему база распухает.

Ольга

Не соглашусь с советом про оптимизацию таблиц. Читала на форумах, что для InnoDB эта команда бесполезна и оставлена только для совместимости, а место всё равно не вернётся. Зачем тогда блокировать сайт непонятно на сколько?

Анатолий Кузнецов автор

Форумы путают две вещи. Гонять команду регулярно «для ускорения» действительно бесполезно. Но для InnoDB она выполняется как перестройка таблицы: файл создаётся заново, и занятое на диске возвращается. Это единственная причина её запускать — ради места, один раз после чистки. Не хотите блокировки — залейте дамп в новую базу.

Виталий

Страницы у меня собраны конструктором, и чистилка в разделе мета-полей предложила удалить записи с подозрительно большим объёмом. Прочитал статью вовремя, не нажал: проверил ключи — это была вёрстка главной.

Ксения

В десятке статей советуют сразу выставить ревизии в false и забыть про них навсегда. Есть причина этого не делать, кроме «а вдруг понадобится откатить»?

Анатолий Кузнецов автор

Причина как раз эта, и она не теоретическая. Ревизии выручают в двух ситуациях: редактор снёс полстраницы и сохранил, и второе — плагин при обновлении переписал контент записи. Без них остаётся только копия всей базы, а разворачивать её из-за одной страницы никто не станет. Три штуки лучше, чем ноль.

Роман

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

Анатолий Кузнецов автор

Нет, это самое частое заблуждение про эту защиту. Порог применяется к новым опциям и к тем, что меняются после обновления. Всё, что уже лежит с включённой автозагрузкой, читается на каждом запросе независимо от размера. Откройте список опций по объёму значения и увидите своих тяжеловесов: разгружать их надо руками.

Наталья

Дополню список: стояла статистика посещений прямо в движке, и таблицы с визитами разрослись больше всего контента. Плагин сняла, а таблицы остались — как раз тот случай. Нашла по имени и удалила.

Артём

Вопрос по комментариям. Спам вычистил кнопкой, а мета в commentmeta всё равно огромная: антиспам дописывал служебные поля к каждому проверенному комментарию за несколько лет. Считать сирот по comment_id тем же способом, что и по записям?

Людмила

Меня смущает сама постановка. Специалисты годами пугают размером базы, а по факту поиск её не видит, вы сами это пишете. Получается, вся чистка — работа ради работы и красивого отчёта заказчику?

Анатолий Кузнецов автор

Частично соглашусь: как способ поднять позиции чистка базы продаётся нечестно. Но две вещи реальны. Первая — автозагружаемые опции, они бьют по времени ответа сервера и видны в любом измерении скорости. Вторая — аварийность: база у лимита роняет сохранение записей, а тяжёлый дамп мешает откатиться. Если в отчёте «почистили базу, ждём роста трафика» — да, это отчёт ради отчёта.

Егор

Отдельное спасибо за абзац про префикс. Скопировал готовый запрос из статьи в интернете, он выдал ошибку — и правда, префикс у меня не стандартный, его ставил тот, кто делал сайт.

Тимур

А если установка сетевая, несколько сайтов в одной базе? Там кэш с истечением называется по-другому, и таблицы у каждого сайта свои с номером в префиксе. Чистилки такое корректно понимают или лучше вручную?

Оставьте комментарий

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

 Нажимая «оставить комментарий» вы принимаетеправила конфиденциальности 

Прокрутить вверх