【问题标题】:How do I improve the efficiency of my WordPress GraphQL server for a static website如何提高静态网站的 WordPress GraphQL 服务器的效率
【发布时间】:2018-07-24 05:56:37
【问题描述】:

recently built 是一个 graphql 模式生成工具,它检查一组 WordPress 高级自定义字段的 JSON 表示以生成一个 graphql 模式。 JSON 表示基于 SQL 数据库中存在的自定义帖子类型和高级自定义字段。

例如,使用自定义字段 citystreet_address 定义名为 Office Location 的自定义帖子类型会生成一个可以通过以下方式查询的 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_posts 表从wp_postmeta 表中提取高级自定义帖子信息。

在普通网站的着陆页上使用此架构生成工具会导致对数据库进行 4035 次单独的 SQL 查询。我不确定这是否异常,但它会导致执行时间变慢(在我的 2015 MacBook Pro 上约为 4 秒)。

我希望为数据很少变化的网站(本质上是静态网站)提高这些 graphql 查询的效率。根据研究,我的四个主要途径是

  1. 使用Facebook's dataloader 进行批量查询。我从this source 收集到并查看batching capabilities of dataloader for SQL 可能很难批处理由天真的graphql 解析器生成的SQL 查询。
  2. 使用 join-monster 之类的东西创建不那么简单的 graphql 解析器
  3. 使用 Redis 或 Memcached 实现键/值缓存,该缓存放置 response-level cache in front of the GraphQL server
  4. 将具有动态 graphql 请求的网站编译为纯静态网站,然后将其部署为静态网站(从等式中删除 graphql)

我对这些途径以及其他途径的相对优点感兴趣。

【问题讨论】:

  • 我的意思是,你在这里提到了很多东西,我不知道到底是什么问题。使用数据加载器之类的技术应该对发送的查询量产生对数影响。您面临的问题似乎源于“自动生成”和“性能”是需要付出巨大努力才能结合起来的两件事。事实上,有多家公司试图解决这个问题,比如 Prisma 或Hasura
  • 我想我没有一个明确的问题,但是我对不同解决方案的相对优点感兴趣。与简单地在查询级别缓存结果相比,数据加载器似乎是一个“更难”的问题,但不会遭受缓存使用量激增的风险。我认为对于我的特定用例,由于数据本质上是静态的并且查询是不变的,我将在查询级别进行缓存。我会在实施后报告我的结果。
  • 为什么不使用'wp-graphql'插件? Apollo 客户端在(标准化)查询缓存、批处理等方面可能会更好。

标签: mysql sql performance graphql gatsby


【解决方案1】:

在开始使用缓存和其他耗能的“解决方案”之前,让我们做一些事情来加速查询本身。

查询 1(postmeta 问题)

标准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;

here的解释,遇到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 的全表扫描。根据我的建议:两次非常有效的单行提取,以及确定 2 行中的哪一行确实交付。

【讨论】:

  • 响应级别的缓存确实大大加快了速度,但这不是一个通用的解决方案。我想在 DB 或 ORM 级别设计一些东西,所以这是一个很好的开始。我还在处理涉及双表遍历以访问 WordPress 类别以及 ORM 处理以访问 ACF 转发器字段的低效率问题,如here 所述。
猜你喜欢
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 2021-09-28
  • 1970-01-01
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
相关资源
最近更新 更多