当 Relay 游标分页总是获取整个数据集时,它如何处理大数据集?

Posted

技术标签:

【中文标题】当 Relay 游标分页总是获取整个数据集时,它如何处理大数据集?【英文标题】:How does Relay cursor pagination handle big datasets when it always fetches the whole dataset? 【发布时间】:2020-01-27 19:41:16 【问题描述】:

我目前正在开发一个使用 Apollo Server/PostgresQL 和 Knex/Objection 的 GraphQL 项目。

我正在使用的数据集可以很容易地增加到 10 万个项目。

所以分页的问题出现了,我试图找到一种方法来使用基于光标的分页,因为这似乎是这些天的标准。

但是在检查了几个实现之后,例如:

https://facebook.github.io/relay/graphql/connections.htm#sec-Pagination-algorithm https://github.com/Terminal-Systems/apollo-cursor-pagination

我觉得对于所有这些实现,在基于光标进行切片之前,会获取整个数据集。这让我感到困惑,因为当您使用更大的数据集时,这似乎是一个巨大的性能问题?

即使在我链接的 Relay 规范中,它也声明您在根据 before 或 after 参数进行切片之前以 allEdges 开头。

有什么我遗漏的吗?因为我看不出这会是比基于偏移的分页更好的方法,但我希望被证明是错误的,并表明我的推理不正确。

干杯,周五快乐!

【问题讨论】:

【参考方案1】:

中继规范确实指定获取满足提供的beforeafter 参数的所有边,然后根据firstlast 参数对数据进行切片。在处理较大的表时,这样做确实会明显变慢并且占用更多内存。

使用基于游标的分页优于基于偏移的主要好处是它更适用于经常添加或删除行的表。分页时可能会添加或删除边缘 - 这可能导致在使用基于偏移的分页时跳过边缘或获得重复的边缘。

基于光标的分页可以以不需要获取所有行的方式实现。有像 this one 这样的库可以做到这一点。我不能说这样做是否会在技术上使您的服务器不“符合规范”,但我想只要结果相同,您的服务器仍然会与 Relay 客户端兼容。也就是说,如果您不担心在前端支持 Relay 客户端,则没有必要实现 Relay 样式的连接或 Relay 规范的任何其他部分。您可以在符合 Relay 的服务器之外进行基于光标的分页。

【讨论】:

以上是关于当 Relay 游标分页总是获取整个数据集时,它如何处理大数据集?的主要内容,如果未能解决你的问题,请参考以下文章

如何从数据库中获取 Graphql 中的分页游标?

从 Netezza 数据库创建 SAS 数据集时,SAS“CLI 游标扩展提取错误:数值超出范围”

elasticsearch获取大批量数据时 深度分页(from&size) VS scroll游标查询

solr研磨之游标分页

MySQL 存储过程,获取使用游标查询的结果集

您如何为 ORM 的分页定义中继连接?