当前位置 博文首页 > weixin_ccjz9527的博客:高性能体系结构graphql到sql
Hasura GraphQL引擎提供了一个超文本传输协议应用编程接口,以一种权限安全的方式使用GraphQL查询Postgres。
您可以利用Postgres中的外键约束在单个请求中查询分层数据。 例如,您可以运行此查询来获取“唱片集”及其所有“曲目”(前提是“曲目”表具有指向“唱片集”表的外键):
正如您可能已经猜到的,查询可以遍历表到任意深度。 这个与权限相结合的查询接口允许前端应用程序查询Postgres,而无需编写任何后端代码。
该应用编程接口旨在快速(响应时间)和处理大吞吐量(每秒请求数),同时节省资源(低CPU和内存使用率)。 我们讨论了使我们能够实现这一目标的架构决策。
对数据微服务的查询经历以下几个阶段:
要求大致如下:
以下是获取GraphQL查询所需数据的各种方法:
GraphQL查询执行通常包括为每个字段执行一个解析器。 在示例查询中,我们将调用一个函数来获取2018年发行的专辑,然后对于这些专辑中的每一张,我们将调用一个函数来获取曲目,这是经典的N+1查询问题。 查询的数量随着查询的深度呈指数增长。
在Postgres上执行的查询如下:
这将是获取所有所需数据的N + 1个查询的总和。
像数据加载器这样的项目旨在通过批处理查询来解决N + 1查询问题。 请求的数量不再依赖于结果集的大小,而是依赖于GraphQL查询中的节点数量。 在这种情况下,示例查询需要对Postgres进行两次查询来获取所需的数据。
在Postgres上执行的查询如下:
这给了我们所有的专辑。 要获取所有所需专辑的曲目:
这总共是2个查询。 我们避免了发出查询来获取每个专辑的曲目信息,而是使用where子句在一个查询中获取所有所需专辑的曲目。
数据加载器旨在跨不同数据源工作,不能利用单个数据源的功能。 在我们的例子中,我们唯一的数据源是Postgres,Postgres像所有关系数据库一样,提供了一种在单个查询中从几个表中收集数据的方法k.a连接。 我们可以确定一个GraphQL查询所需要的表,并使用连接生成一个单独的查询来获取所有的数据。 因此,任何GraphQL查询所需的数据都可以从单个查询中获取。 在发送给客户端之前,必须对这些数据进行适当的转换。
查询如下:
这将为我们提供如下数据:
相册id(_ d) | 相册标题(_ t) | 轨道id | 轨道标题(_ t) |
1 | 白蛋白1 | 1 | track1 |
1 | 白蛋白1 | 2 | track2 |
2 | 白蛋白m2 | 空 | 空 |
该数据必须转换为具有以下结构的JSON响应:
我们发现处理请求的大部分时间都花在了转换函数上(它将SQL结果转换成JSON响应)。 在尝试了一些优化转换函数的方法后,我们决定通过将转换推入Postgres来删除这个函数。 Postgres 9。4(大约在第一个数据微服务发布时发布)添加了JSON聚合函数,这帮助我们将转换推进到Postgres。 生成的SQL将变成类似于:
该查询的结果将有一列和一行,并且该值被发送到客户端,无需任何进一步的转换。 从我们的基准测试来看,这种方法大约比哈斯克尔的转换函数快3-6倍。
根据查询的嵌套级别和使用的条件,生成的SQL语句可能非常大而且复杂。 通常,任何前端应用程序都有一组用不同参数重复的查询。 例如,上述查询可以针对2017年而不是2018年执行。 准备好的语句最适合这些用例。当你有复杂的SQL语句时,这些语句会随着一些参数的改变而重复。
因此,第一次执行这个GraphQL查询时:
我们准备了SQL语句,而不是直接执行它,所以生成的SQL将是(注意$1):
接下来执行这个准备好的语句:
当GraphQL查询更改为2017年时,我们只需直接执行准备好的语句:
根据GraphQL查询的复杂程度,这大致可以使我们提高10-20% .
Haskell非常适合各种原因:
高效能的HTTP堆栈(翘曲,翘曲的体系结构(
这是Hasura的建筑与Prisma和Postgraphile的比较。
数据库实时同步
cs