was*_*mbj 13 express graphql apollo-server
所以就在昨天,我开始学习 graphql,它真的很有趣,而且实际上很容易学习和理解。我开始阅读一些文章,发现了 N+1 问题。我在这里找到了这个例子
询问
# getting the top 100 reviews
{
top100Reviews {
body
author {
name
}
}
}
Run Code Online (Sandbox Code Playgroud)
架构
const typeDefs = gql`
type User {
id: ID!
name: String
}
type Review {
id: ID!
body: String
author: User
product: Product
}
type Query {
top100Reviews: [Review]
}
`;
Run Code Online (Sandbox Code Playgroud)
最后是解析器
const resolver = {
Query: {
top100Reviews: () => get100Reviews(),
},
Review: {
author: (review) => getUser(review.authorId),
},
};
Run Code Online (Sandbox Code Playgroud)
在这篇文章中他说
当我们执行以下查询以获取前 100 条评论和相应的作者姓名时,我们首先调用从数据库中检索 100 条评论记录,然后对于每条评论,我们再次调用数据库以获取用户详细信息给定作者 ID。
我们不能Review从解析器中删除 ,然后在 get100Reviews 方法中进行简单的 JOIN(如果我在 sql 中)
我不明白为什么我们会遇到 N+1 问题,而我们可以在查询解析器中进行简单的 JOIN。
我理解 GraphQL 对吗??
请有人在这里阐明一些情况,并告诉我。
谢谢 !!
Dan*_*den 19
您是对的 - 使用连接可以让您进行单个数据库查询而不是 101。
问题是,在实践中,您不会只有一个联接——您的审查数据模型可能包括与任意数量的其他模型的关联,每个模型都需要自己的联接子句。不仅如此,这些模型本身可能与其他模型有关系。尝试编写一个 SQL 查询来处理所有可能的 GraphQL 查询不仅困难,而且成本高得令人望而却步。客户可能只请求没有关联模型的评论,但获取这些评论的查询现在包括 30 个额外的、不必要的视图。该查询可能只用了不到一秒,但现在需要 10 秒。
还要考虑类型之间的关系可以是循环的:
{
reviews {
author {
reviews {
author
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,查询的深度是不确定的,不可能创建一个 SQL 查询来容纳任何可能的 GraphQL 查询。
使用像dataloader这样的库可以让我们通过批处理来缓解 N+1 问题,同时保持任何单个 SQL 查询尽可能精简。也就是说,您仍然会得到多个查询。另一种方法是利用传递给解析器的 GraphQLResolveInfo 对象来确定首先请求哪些字段。然后,如果您愿意,您可以只在查询中进行必要的连接。但是,解析info对象并构建这种查询可能是一项艰巨的任务,尤其是在您开始处理深度嵌套的关联时。另一方面,dataloader是一种更简单直观的解决方案。
| 归档时间: |
|
| 查看次数: |
3986 次 |
| 最近记录: |