【问题标题】:I don't understand the GraphQL N+1 problem我不明白 GraphQL N+1 问题
【发布时间】:2020-07-05 00:05:06
【问题描述】:

所以就在昨天,我开始学习 graphql,它真的很有趣,而且实际上很容易学习和理解。我开始阅读一些文章,我发现了 N+1 问题。我在这里找到了这个例子

查询

# getting the top 100 reviews
{
  top100Reviews {
    body
    author {
      name
    }
  }
}

架构


const typeDefs = gql`
  type User {
    id: ID!
    name: String
  }
  type Review {
    id: ID!
    body: String
    author: User
    product: Product
  }
  type Query {
    top100Reviews: [Review]
  }
`;

最后是解析器

const resolver = {
  Query: {
    top100Reviews: () => get100Reviews(),
  },
  Review: {
    author: (review) => getUser(review.authorId),
  },
};

他在这篇文章中说

当我们执行以下查询以获取前 100 条评论和相应的作者姓名时,我们首先进行一次调用以从数据库中检索 100 条评论记录,然后对于每条评论,我们再次调用数据库以获取给定作者 ID 的用户详细信息。

我们不能只从解析器中删除 Review 并在 get100Reviews 方法中进行简单的 JOIN(如果我在 sql 中)

如果我们会遇到 N+1 问题,我不明白为什么要使用 Review 解析器,而我们可以在 Query 解析器中进行简单的 JOIN。

我理解 GraphQL 对吗??

请有人在这里阐明一下,然后告诉我。

谢谢!!

【问题讨论】:

  • 每种类型都可以单独询问 - 每个类型 [通常] 都有自己的解析器......在父解析器中,您不知道在当前对象旁边是否/应该读取/返回多少子 [字段] [水平] ...搜索dataloader项目

标签: express graphql apollo-server


【解决方案1】:

您是对的——使用连接可以让您进行单个数据库查询,而不是 101。

问题在于,在实践中,您不会只有一个连接 - 您的评论数据模型可能包含与任意数量的其他模型的关联,每个模型都需要自己的连接子句。不仅如此,这些模型可能与其他模型本身有关系。尝试编写一个 SQL 查询来解释所有可能的 GraphQL 查询不仅困难,而且成本高得令人望而却步。客户可能只请求没有关联模型的评论,但获取这些评论的查询现在包括 30 个额外的、不必要的视图。该查询可能用时不到一秒,但现在需要 10 秒。

还要考虑类型之间的关系可以是循环的:

{
  reviews {
    author {
      reviews {
        author
      }
    }
  }
}

在这种情况下,查询的深度是不确定的,不可能创建一个可以容纳任何可能的 GraphQL 查询的 SQL 查询。

使用像 dataloader 这样的库可以让我们通过批处理来缓解 N+1 问题,同时保持任何单个 SQL 查询尽可能精简。也就是说,您仍然会遇到多个查询。另一种方法是利用传递给解析器的 GraphQLResolveInfo 对象来确定首先请求了哪些字段。然后,如果您愿意,您可以只在查询中进行必要的联接。但是,解析info 对象并构建这种查询可能是一项艰巨的任务,尤其是在您开始处理深度嵌套的关联时。另一方面,dataloader 是一种更简单直观的解决方案。

【讨论】:

  • 这就是我想知道的,谢谢丹尼尔 :)
【解决方案2】:

我刚刚在 Nodejs 上的 GraphQL 上编写了一个包,我相信它可以在大多数情况下解决 N+1 个问题。 看看这个! https://github.com/oney/sequelize-proxy

它基本上使用数据加载器将多个查询批处理为单个查询,但它进一步利用了 sequelize 中的特性和关联定义,使其更加准确和高效。

【讨论】:

    猜你喜欢
    • 2018-10-08
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 2021-10-17
    • 2022-07-29
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多