Вопрос или проблема
Я работаю над проектом, где мне нужно загружать события (кастомный тип поста) и большое количество метаданных для каждого события. Проблема в том, что время загрузки страницы становится все дольше, когда добавляется все больше и больше событий.
На начальном этапе, когда было всего несколько событий, это не было проблемой, но сейчас, когда в системе более 100 событий, время загрузки страниц увеличивается до 6 секунд, что слишком долго.
Пример того, что я делаю: показываю все события в системе
(все ниже выполняется внутри плагина)
Я загружаю все события с помощью get_posts и указываю кастомный тип поста.
Я перебираю все посты и получаю все метаданные с помощью get_post_meta
за один вызов.
При тестировании, где было узкое место, я обнаружил, что когда я убираю get_post_meta
, время выполнения уменьшается с 4.5 секунд до 14 мс.
Я также протестировал, что произойдет, если я загружу каждое метаданные отдельно, вот так: get_post_meta($post->ID, "meta_value", true);
Если у меня есть представление, где мне нужно только несколько мета-значений, это ускоряет процесс, и я мог бы сократить время загрузки на 20%, но когда мне нужно почти все, изменений во времени загрузки не произошло.
Я также заметил, что использование get_post_custom
на самом деле не помогает в этом случае.
После того как я посмотрел информацию в интернете (здесь, блоги и т.д.), люди отметили, что когда вы вызываете get_posts
, все метаданные автоматически извлекаются и кэшируются. Но, похоже, это не так, когда я смотрю на время выполнения и количество обрабатываемых запросов.
Есть ли способ ускорить это еще больше через php/mysql?
Я думал о том, есть ли способ получить все посты и метаданные для каждого поста за один вызов. Но мне не удалось найти что-то подходящее в интернете, что помогло бы мне это осуществить.
Вам следует использовать объектный кэш, это определенно ускорит запросы get_post_meta, так как они будут кэшироваться при первоначальном WP_Query (get_posts).
Я рекомендую протестировать с кэшем APC, используя APC Object Cache Backend: https://wordpress.org/plugins/apc/
Просто разместите файл в вашей папке wp-content и убедитесь, что у вас доступно расширение APC.
Ответ или решение
Проблема с замедлением загрузки страниц при использовании функции get_post_meta
в вашем плагине, связанная с увеличением количества событий, безусловно, может оказаться значительной. Когда вы обрабатываете 100+ записей, это может добавить значительную нагрузку на ваш сервер, особенно если каждый пост требует загрузки большого объема метаданных.
Вот несколько предложений, которые помогут оптимизировать скорость загрузки:
-
Использование объектного кэширования: Как вы и упомянули, использование объектного кэширования может значительно ускорить выполнение запросов. Я рекомендую использовать плагин APC (или другой аналогичный), который позволит кэшировать результаты
get_post_meta
во время первоначального запроса WP_Query (илиget_posts
). Объектное кэширование сократит количество обращений к базе данных при повторных запросах к метаданных.- Установите APC Cache и убедитесь, что у вас активировано расширение APC на сервере.
-
Оптимизация запросов к базе данных: Вместо использования
get_post_meta
в цикле, можно оптимизировать запросы к базе данных. Вот один из подходов:- Используйте стандартный WP_Query для получения метаданных вместе с постами:
$args = array( 'post_type' => 'event', 'posts_per_page' => -1, ); $query = new WP_Query($args); $posts = $query->posts; foreach ($posts as $post) { setup_postdata($post); $meta_data = get_post_meta($post->ID); // Получение всех метаданных за один раз // Используйте $meta_data } wp_reset_postdata();
Однако, если вам нужны только определенные мета-поля, вы можете заранее выполнить SQL-запрос, который объединит значения из таблицы постов и таблицы метаданных.
-
Кастомные SQL-запросы: Если вы хотите получить все записи и их метаданные за один запрос, вы можете написать кастомный SQL-запрос:
global $wpdb; $sql = "SELECT p.*, pm.meta_key, pm.meta_value FROM {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = 'event' AND p.post_status = 'publish'"; $results = $wpdb->get_results($sql); $events = array(); foreach ($results as $result) { $events[$result->ID]['post'] = $result; $events[$result->ID]['meta'][$result->meta_key] = $result->meta_value; }
-
Использование WP REST API: Если ваша структура проекта позволяет, вы можете рассмотреть возможность создания API на базе WP REST API, чтобы загружать данные асинхронно.
-
Профилирование и мониторинг: Запуск профилирования с помощью таких инструментов, как Query Monitor, может помочь обнаружить узкие места и дать точки для дальнейшей оптимизации.
Эти меры помогут вам оптимизировать загрузку страниц и улучшить общую производительность вашего плагина, особенно при увеличении объема данных.