解决 GraphQL 查询中防止 N+1 查询问题的最佳实践

· 约 9 分钟读完

GraphQL 是目前前端领域中非常热门的技术,它可以帮助开发人员更高效地查询及获取后端数据。然而,在 GraphQL 查询中,N+1 查询问题可能会成为一个难以避免的问题。N+1 查询问题是指在 GraphQL 查询中,当要查询多个相关对象时,会导致沿着关系链进行多次查询,因此,如果查询的对象很多,就会导致响应时间变慢,甚至可能导致系统崩溃。本文将介绍如何解决 GraphQL 查询中防止 N+1 查询问题的最佳实践。

什么是 N+1 查询问题?

N+1 查询问题可以简单地理解为一个常见的性能问题,当要查询多个相关对象时,会导致沿着关系链进行多次查询。例如,在查询一个作者的图书时,如果我们使用 GraphQL 查询语句:

如果 authors 是一个数组,那么对于每个作者,GraphQL 将会发送一个查询以获取对应图书的详细信息,这将导致由于查询数大于 1,填充关系可能需要进行 N+1 次查询。由于每个查询的成本都很高,并且只需要一个请求即可获取所有图书的详细信息,我们需要找到一种解决办法来避免这种 N+1 查询的性能问题。

如何避免 N+1 查询问题?

使用 DataLoader

由于 GraphQL 采用树形查询方式,解决 N+1 查询问题的好方法是使用 DataLoader。DataLoader 可以将需要加载的数据分组成一批批加载,直到满足 GraphQL 查询所需的性能要求。它是一个为 Node.js 和浏览器构建的延迟加载数据批处理库。我们可以使用 DataLoader 来解决 N+1 查询问题,节约资源,避免需要发送多个请求。

首先,需要安装 DataLoader。可以使用以下命令进行安装:

然后,我们可以创建一个 DataLoader 的对象,这个对象将会在加载需要的数据时起到关键的作用。接着,我们要实现一个函数,这个函数需要从数据源中查询数据,以满足 GraphQL 查询。最后,我们要提供 GraphQL 查询语句,这个语句需要告诉 DataLoader 要加载那个函数以及对应的参数。

下面是一个示例代码:

在这个示例中,当 GraphQL 服务器接收到查询时,会调用相应查询的 DataLoader,该 DataLoader 将每个连接的对象的 ID 一起传递给它,并一次查询期望返回的对象。

在内部,我们通过使用 map 函数来过滤所需的对象。例如,在 bookLoader 中,从 books 数组中筛选出 id 数组中包含的对象。

在 resolvers 中,我们定义了将要处理的 GraphQL 查询语句,由于书籍与作者之间具有一对多的关系,我们在定义查询语句时注意到这一点,books 查询将返回一个作者的一组图书,因此我们使用 books(id: ID!) 定义查询格式。

使用 DataLoader,我们可以轻松地解决 N+1 查询问题,同时提高查询响应时间,避免多次发送查询请求。因此,DataLoader 在解决 GraphQL 查询中的性能问题方面发挥着关键的作用。

使用 dataloader-sequelize

对于使用 Sequelize ORM 的 Node.js 应用程序,datayloader-sequelize 是一种非常流行和实用的 N+1 查询解决办法。它是基于 DataLoader 的插件,可以帮助我们轻松地解决 N+1 查询问题。

首先,需要安装 dataloader-sequelize。可以使用以下命令进行安装:

然后,我们可以创建一个 DataLoader 的对象来解决 N+1 查询问题。

下面是一个示例代码:

在这个示例中,我们定义了 authorLoader 和 bookLoader 两个 DataLoader 对象,在 resolvers 中使用这两个对象来查询所需数据。

此外,在 Author 和 Book 中,我们定义了模型之间的一对多关系,并为之定义了网络映射,取名为 books 和 author。我们在 Book 上使用 belongsTo 定义其所属关系,使用该方法可以方便的访问其相关关联对象数据。

在 Query 的中,我们定义了 author 和 book 的查询格式,并将 authorLoader 和 bookLoader 传递给了 author 和 book 的查询函数。

使用 dataloader-sequelize,我们可以避免发生 N+1 查询的问题,轻松地解决性能问题,以及更好地存储和操作数据。

小结

GraphQL 是一种优秀的前端技术,它可以帮助我们更快捷、高效地查询和获取后端数据。然而,在查询过程中, N+1 查询问题是一个非常严重的性能问题。本文提供了两种处理 N+1 查询问题的最佳实践,建议按照实际需求来选用 DataLoader 或 dataloader-sequelize。

在使用 GraphQL 进行查询时,除了考虑实现时间和查询结果以外,还要考虑性能问题,要使用一些方法来尽可能地减少查询次数,并减少网络延迟。这样可以更好的优化 GraphQL 查询性能。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d794bda941bf7134d8ed8f