GraphQL和嵌套资源会进行不必要的调用吗?

时间:2017-03-17 11:08:21

标签: graphql

我读过GraphQL规范,找不到避免1 + N * number_of_nested电话的方法,我错过了什么?

即。查询有一个类型客户端,它有嵌套的订单和地址,如果有10个客户端,它将为10个客户端执行1次调用,为每个客户端执行10次调用。每个client.addresses执行10次调用。

有没有办法避免这种情况?并不是说它与缓存UUID的东西不一样,那些都是不同的值,如果你的GraphQL指向一个可以连接的数据库,它就会非常糟糕,因为你可以对任意数量的客户端进行3次查询

我问这个是因为我想将GraphQL与可以有效获取嵌套资源的API集成,并且如果有一种方法可以在解析之前解决整个图形,那么尝试将一些嵌套的东西放入其中会很不错一个电话。

或者我弄错了,GraphQL只能用于微服务?

2 个答案:

答案 0 :(得分:1)

我认为,您正在谈论将GraphQL与SQL数据库后端一起使用。标准本身是数据库不可知的,它并不关心,你如何解决代码中可能出现的N + 1 SELECT问题。话虽这么说,GraphQL服务器的特定服务器端实现引入了许多不同的方法来缓解这个问题:

  • AFAIK,Ruby实现能够利用Active Record和gems(例如bullet)来应用已执行数据库调用的水平批处理。
  • JavaScript实现可以使用DataLoader库,它具有将一系列执行的承诺一起批处理的类似技术。您可以在行动here中看到它。
  • Elixir和Python实现具有关于已执行子查询的运行时信息的概念,可用于确定执行GraphQL查询将进一步需要哪些数据,并可能预取它。
  • F#实现与Elixir类似,但插件本身可以对执行树进行实时分析,以便更好地描述哪些字段可以在代码中使用,从而可以更轻松地从数据库模型中拆分GraphQL域模型。
  • 许多实现(即PostGraph)将底层数据库模型直接绑定到GraphQL架构中。在这种情况下,GQL查询通常直接转换为数据库查询语言。

答案 1 :(得分:1)

这是GraphQL"解析器架构"的难点之一。您必须通过在每个解析器中执行大量I / O来避免产生大量网络延迟。使用SQL DBMS的应用程序通常会首先解决N + 1问题。您需要使用一些批处理和/或缓存技术来解决这个问题。

如果您在服务器上使用Node.js,我有两个建议的工具:

  • DataLoader - 一个与数据库无关的工具,用于为每个字段批处理解析器并缓存单个记录。

  • Join Monster - 一个SQL定制的工具,可以读取每个查询和您的架构并为您编译SQL查询。它利用JOIN和DataLoader样式的批处理在几个(或单个)SQL查询中从表中获取数据。