Как повысить эффективность моего сервера WordPress GraphQL для статического веб-сайта

Я недавно построенный инструмент создания схемы graphql, который проверяет представление JSON набора расширенных настраиваемых полей WordPress для создания схемы graphql. Представление JSON основано на настраиваемых типах сообщений и расширенных настраиваемых полях, имеющихся в базе данных SQL.

Например, определение настраиваемого типа сообщения с именем Office Location с настраиваемыми полями city и street_address приводит к схеме graphql, которую можно запросить следующим образом:

officeLocations {
    post_title
    locationInformation {
        city
        streetAddress
    }
}

Это приводит к базовым SQL-запросам формы

SELECT
`meta_id`, `post_id`, `meta_key`, `meta_value`
FROM `wp_postmeta` AS `wp_postmeta`
WHERE `wp_postmeta`.`meta_key` = 'street_address'
AND `wp_postmeta`.`post_id` = 176
LIMIT 1;

а также

SELECT
`id`, `post_author`, `post_title`, `post_content`,
`post_excerpt`, `post_status`, `post_type`, `post_name`,
`post_date`, `post_parent`, `menu_order`, `guid`
FROM `wp_posts` AS `wp_posts`
WHERE (`wp_posts`.`id` = 176 OR `wp_posts`.`post_name` = NULL)
AND `wp_posts`.`post_status` = 'publish'
LIMIT 1;

которые извлекают расширенную информацию о пользовательских публикациях из таблицы wp_postmeta, сначала просматривая таблицу wp_posts.

Использование этого инструмента генерации схемы на целевой странице скромного веб-сайта приводит к 4035 отдельным SQL-запросам к базе данных. Я не уверен, что это необычно, но это приводит к медленному времени выполнения (~ 4 с на моем MacBook Pro 2015 года).

Я хочу повысить эффективность этих запросов graphql для веб-сайта, данные которого редко меняются (по сути, статический веб-сайт). Исходя из исследований, мои четыре основных направления:

  1. Пакетные запросы с использованием Загрузчик данных Facebook. Я почерпнул из этот источник и изучил возможности пакетирования загрузчика данных для SQL, что может быть сложно пакетировать SQL-запросы, сгенерированные наивными преобразователями graphql.
  2. Создавайте менее наивные резолверы graphql, используя что-то вроде присоединиться к монстру
  3. Реализуйте кеширование ключей / значений с помощью Redis или Memcached, которое помещает кеш уровня ответа перед сервером GraphQL
  4. Скомпилируйте веб-сайт с динамическими запросами graphql в чисто статический веб-сайт, который затем развертывается как статический веб-сайт (удаляя graphql из уравнения)

Меня интересуют относительные достоинства этих проспектов так же, как и любых других.

Я имею в виду, вы упомянули здесь много вещей, и я не знаю, в чем именно заключается вопрос. Использование таких методов, как загрузчик данных, должно иметь логарифмический эффект на количество отправленных запросов. Проблема, с которой вы столкнулись, похоже, связана с тем, что «автоматически генерируемые» и «производительность» - это две вещи, объединение которых требует больших усилий. На самом деле есть несколько компаний, которые пытаются решить эту проблему, например Prisma или Хасура.

Herku 22.07.2018 18:18

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

jsindos 23.07.2018 05:41

Почему бы не использовать плагин wp-graphql? Клиент Apollo может быть лучше в (нормализованном) кешировании запросов, пакетной обработке и т. д.

xadm 03.08.2018 16:47
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
3
682
1

Ответы 1

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

Запрос 1 (постмета проблема)

Стандартный wp_postmeta имеет неэффективную схему. Это лучше:

CREATE TABLE wp_postmeta (
    post_id BIGINT UNSIGNED NOT NULL,
    meta_key VARCHAR(255) NOT NULL,
    meta_value LONGTEXT NOT NULL,
    PRIMARY KEY(post_id, meta_key),
    INDEX(meta_key)
    ) ENGINE=InnoDB;

См. здесь для объяснения, что делать, если у вас 767 проблем, и как справиться с требованием для meta_id (что в большинстве случаев бесполезно).

Эти советы помогут ускорить большинство запросов, связанных с wp_postmeta.

Запрос 2 (плохая формулировка)

  • wp_posts.post_name = NULL всегда выходит из строя; вместо этого скажите wp_posts.post_name IS NULL.
  • Без ORDER BYLIMIT доставит произвольную строку.
  • OR плохо оптимизируется ...

Перепишем так:

SELECT * FROM 
    ( ( SELECT ...
            FROM `wp_posts` AS `wp_posts`
            WHERE `wp_posts`.`id` = 176
              AND `wp_posts`.`post_status` = 'publish'
            LIMIT 1 )
      UNION DISTINCT
      ( SELECT ...
            FROM `wp_posts` AS `wp_posts`
            WHERE `wp_posts`.`post_name` IS NULL
              AND `wp_posts`.`post_status` = 'publish'
            LIMIT 1 )
    ) LIMIT 1

И тогда это было бы полезно:

INDEX(post_status, post_id)
INDEX(post_status, post_name)

Если вы добавите ORDER BY, его нужно будет добавить в 3-х местах; непосредственно перед каждым LIMIT.

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

Кэширование на уровне ответа значительно ускоряет работу, но это не универсальное решение. Я хотел бы разработать что-то на уровне DB или ORM, так что это отличное начало. Я также имею дело с неэффективностью, связанной с обходом двойной таблицы для доступа к категориям WordPress, а также с обработкой ORM для доступа к полям повторителя ACF, как описано здесь.

jsindos 24.07.2018 04:04

Другие вопросы по теме