Вопрос или проблема
Какой будет лучший способ разделить большую базу данных на одном сайте, а не на мультисайтовой установке WordPress? HyperDB может быть для этого (но, менее 10 веб-мастеров смогли понять, как его установить, судя по активным установкам).
В настоящее время на сайте около 350 тысяч постов, он находится на хорошем VPS. Сайт работает довольно быстро на фронтенде, открывает страницы, просматривает… Но он замедляется на бэкенде при публикации новых постов, каждый день добавляется много новых постов.
Сайт имеет такую структуру постоянных ссылок:
sitename.com/year/month/day/postid/post-name
Практически только новые посты редактируются, и после публикации посты не изменяются.
Есть идеи, как ускорить запись в базу данных или лучше, чтобы опубликованные посты находились в одной базе данных, а новые посты в другой базе данных?
Обновление:
Первая установка: Установка в корневой директории сайта с новой базой данных, без старых опубликованных постов, только для будущих постов. Структура постоянных ссылок осталась такой же:
sitename.com/year/month/day/postid/post-name
Вторая установка:
Создал папку “2015” в корневой директории сайта и установил WordPress в эту папку с SQL-базой данных оригинальной установки WordPress из корня, со всеми постами до конца сентября, только структура постоянных ссылок изменена на:
sitename.com/month/day/postid/post-name
и она даст ту же структуру URL, что и была (потому что WordPress находится в подпапке “2015”):
sitename.com/year/month/day/postid/post-name
Этот подход работает, когда мне нужно разделить базу данных раз в год (например, за 2014 год). Для каждого прошедшего года я могу иметь одну папку, названную по прошедшему году, и установку WordPress в этой папке с базой данных постов того прошедшего года.
Таким образом, когда посетитель пытается открыть URL, например:
sitename.com/2014/01/01/post-name-here
сервер сначала смотрит в подпапку /2014/, и там есть установка WordPress, которая вернет этот пост.
Проблема:
Когда база данных слишком велика для текущего года, я попытался разделить посты текущего года на две базы данных: одна содержит все опубликованные посты с начала года до конца сентября, а другая будет содержать будущие посты.
У меня есть это:
В корне сайта у меня есть папка “2015” с установкой WordPress и структурой постоянных ссылок:
sitename.com/month/day/postid/post-name
И в корневой установке WordPress со структурой постоянных ссылок:
sitename.com/year/month/day/postid/post-name
Если я пытаюсь открыть URL:
sitename.com/2015/09/01/post-name-here
сервер проверит в папке “2015”, и установка WordPress из этой папки вернет пост от 1 сентября, и это работает хорошо.
Если я опубликую новый пост сегодня в установке WordPress в корне сайта, он будет иметь URL, например:
sitename.com/2015/10/29/post-name-here
И если я попытаюсь открыть его, сервер будет искать в установке WordPress внутри папки “2015”, но эта установка имеет посты только до конца сентября, и я получаю 404. После этого сервер не будет искать внутри установки WordPress в корне сайта, где находится этот пост.
Вопрос:
Как заставить сервер искать в установке WordPress внутри подпапки “2015”, а если в этой установке нет поста, искать этот пост внутри установки WordPress в корне сайта?
У меня была похожая проблема на сайте с ~100k строк в wp_posts и ~500k в wp_postmeta.
Правда в том, что WordPress имеет действительно медленные запросы в админке, когда у вас становится много постов.
Лучший способ найти узкое место – использовать плагин Debug Bar.
Вы, вероятно, обнаружите какие-то безумно медленные запросы, такие как следующие:
SELECT DISTINCT meta_key
FROM lc_postmeta
WHERE meta_key NOT BETWEEN '_' AND '_z'
HAVING meta_key NOT LIKE '\\_%'
ORDER BY meta_key
LIMIT 30
или
SELECT ID
FROM lc_posts
WHERE post_type="attachment"
AND post_mime_type LIKE 'audio%'
LIMIT 1
и
SELECT ID
FROM lc_posts
WHERE post_type="attachment"
AND post_mime_type LIKE 'video%'
LIMIT 1
К сожалению, это известные проблемы, но вы можете их настроить, чтобы они загружались быстрее.
Например, я просто удалил метабокс пользовательских полей, который не использовал, и это дало мне 50% времени загрузки.
add_action( 'admin_menu' , 'pu_remove_post_custom_fields' );
function pu_remove_post_custom_fields() {
remove_meta_box( 'postcustom' , 'post' , 'normal' );
}
Я не уверен, поможет ли разделение вашей базы данных на несколько экземпляров чтения.
Вы не можете разделить базу данных, не потеряв функциональность, такую как поиск, rss, теги, категории. Если вам это не важно, тогда вам нужно переключить ваш сайт в сеть, имея один сайт на год или, возможно, даже на месяц.
Как только вы настроите сеть, есть всевозможные способы агрегировать контент со всех сайтов сети, которые вы можете реализовать для нужных вам функций.
Ответ или решение
Разделение базы данных на крупном сайте WordPress, особенно когда вы работаете с большим количеством постов (350 000 и более), может быть сложной задачей. Однако, когда вас беспокоит замедление работы сайта при публикации новых постов, вы можете использовать несколько стратегий, чтобы ускорить процесс. Давайте рассмотрим решение этой проблемы поэтапно.
1. Анализ текущей ситуации
Прежде всего, рекомендуется проанализировать производительность вашей базы данных с помощью плагинов, таких как Debug Bar. Этот плагин позволит вам выявить медленные SQL-запросы и другие узкие места в производительности. Изучите результаты и посмотрите, какие запросы занимают наибольшее время, чтобы понять, где можно оптимизировать.
2. Оптимизация существующей базы данных
Прежде чем переходить к более сложным решениям, рассмотрите возможность оптимизации вашей текущей базы данных:
- Удаление ненужных метаполей и метабоксов: Если у вас есть метаполя, которые вы не используете, удалите метабокс с пользовательскими полями в админке. Это может значительно улучшить скорость загрузки.
add_action( 'admin_menu', 'pu_remove_post_custom_fields' );
function pu_remove_post_custom_fields() {
remove_meta_box( 'postcustom', 'post', 'normal' );
}
- Оптимизация таблиц базы данных: Используйте команды
OPTIMIZE TABLE
иANALYZE TABLE
в MySQL для оптимизации таблицwp_posts
иwp_postmeta
. Это поможет ускорить выполнение запросов.
3. Разделение базы данных
Если ваш сайт все еще испытывает замедление, вам может подойти решение с разделением базы данных по годам, как вы уже начали делать. Организация нескольких установок WordPress позволяет уменьшить объем данных, с которыми работает каждая установка.
Подход с установками WordPress по годам:
-
Создание установок по годам: Как вы уже сделали, создайте отдельные установки WordPress для каждого года, в которых будут храниться посты за этот год.
-
Построение системы маршрутизации: Вам необходимо реализовать систему маршрутизации, которая будет проверять, существует ли пост в одной из установок. Если он не найден в установленной базе, направьте запрос к корневой базе.
Вот пример кода, который можно использовать для этого:
add_action('template_redirect', 'redirect_to_correct_post');
function redirect_to_correct_post() {
$requested_post = get_query_var('name');
$requested_year = get_query_var('year');
$post_id = url_to_postid($requested_year . '/' . $requested_post);
if (!$post_id) {
// Проверяем, есть ли пост в папке годовой установки
if (file_exists('/path/to/your/2015/wp-load.php')) {
require_once('/path/to/your/2015/wp-load.php');
$post_id = url_to_postid('/2015/' . $requested_post);
}
}
if ($post_id) {
wp_redirect(get_permalink($post_id));
exit;
}
}
4. Рассмотрение использования мультисайта
Если вышеуказанные методы не помогают, вы можете рассмотреть возможность перехода на сеть сайтов (мультисайт). Это позволяет создать отдельные сайты для каждого года или месяца, что даст вам больше гибкости в управлении контентом. Мультисайтовая установка также предоставляет возможность настраивать общие плагины и темы.
Заключение
Разделение базы данных на несколько установок WordPress может оказаться наиболее эффективным решением в вашем случае. Важно помнить о необходимости настроить правильную маршрутизацию и учитывать влияние на функциональность вашего сайта, включая таксономию и поиск.
Не забывайте, что перед тем как вносить серьезные изменения, обязательно делайте резервные копии вашей базы данных, чтобы избежать потери данных.