api - 如何向 API 客户端提供 1,000,000 个数据库结果?

标签 api postgresql pagination distributed-computing

继我之前的问题之后:

Using "Cursors" for paging in PostgreSQL

为 API 客户端提供 1,000,000 个数据库结果的好方法是什么?

我们目前正在使用 PostgreSQL。一些建议的方法:

  • 使用 Cursors 进行分页
  • 使用随机数进行分页(在每个查询中添加“GREATER THAN ORDER BY”)
  • 使用 LIMIT 和 OFFSET 进行分页(对于非常大的数据集会分解)
  • 将信息保存到一个文件中,让客户端下载
  • 遍历结果,然后将数据 POST 到客户端服务器
  • 仅将 key 返回给客户端,然后让客户端从 Amazon S3 等云文件中请求对象(仍然可能需要分页才能获取文件名)。

有什么是我没有想到的,它比这些选项中的任何一个都简单得​​愚蠢而且好得多?

最佳答案

该表有一个主键。好好利用它。

代替 LIMITOFFSET,使用主键过滤器进行分页。您在评论中暗示了这一点:

Paging using random numbers ( Add "GREATER THAN ORDER BY " to each query )

但是您应该如何做并不是随机的。

SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2

允许客户端指定这两个参数,它看到的最后一个 ID 和要获取的记录数。您的 API 必须具有占位符、额外参数或替代调用以“获取 第一个 n 个 ID”,其中它从查询中省略了 WHERE 子句,但这是微不足道。

此方法将使用相当高效的索引扫描来按顺序获取记录,通常避免排序或需要遍历所有跳过的记录。客户端可以决定一次需要多少行。

此方法在一个关键方面不同于LIMITOFFSET 方法:并发修改。如果您INSERT 到表中的键低于 某个客户端已经看到的键,这种方法根本不会改变其结果,而OFFSET 方法将重复一行。类似地,如果您DELETE 具有低于已见 ID 的行,此方法的结果将不会改变,而 OFFSET 将跳过未见行。不过,对于具有生成键的仅追加表没有区别。

如果您事先知道客户需要整个结果集,那么最有效的做法就是将整个结果集发送给他们,而无需任何分页业务。这就是我使用游标的地方。从数据库中读取行,并以客户端接受它们的速度将它们发送给客户端。这个 API 需要限制客户端的速度,以避免后端负载过大;对于慢速客户端,我可能会切换到分页(如上所述)或将整个游标结果假脱机到一个临时文件并关闭数据库连接。

重要警告:

  • 需要UNIQUE 约束/UNIQUE 索引或PRIMARY KEY 才能可靠
  • 限制/偏移的不同并发修改行为,见上文

关于api - 如何向 API 客户端提供 1,000,000 个数据库结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13144005/

相关文章:

wordpress - 使用 wordpress jetpack json api

c++ - 从 c 函数在 qtextedit 上显示消息

php - 需要分页吗?

mysql - 如何在limit语句中使用用户定义变量?

iphone - 使用 Evernote API 创建笔记

Github,在不需要github用户帐户的情况下在存储库上创建问题

postgresql - 比较 PostgreSQL 中的文本值

sql - 如何从Postgres中的函数向另一个表中插入错误?

mysql - 我读到的关于 "that bad"的一致性/数据丢失/查询优化问题是什么?

带有约束的 Python 列表分块或分页