2012-10-30 30 views
11

从我刚才的问题跟进:如何提供具有1,000,000个数据库结果的API客户端?

Using "Cursors" for paging in PostgreSQL

什么是提供一个API客户端包含1,000,000个数据库结果的好办法?

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

  • 使用随机数使用Cursors
  • 寻呼寻呼(添加“大于ORDER BY”每个查询)
  • 寻呼使用LIMIT和OFFSET(分解非常大的数据集)
  • 信息保存到一个文件,并让客户端下载
  • 通过迭代的结果,然后将POST数据到客户端服务器
  • 仅返回键到客户端,然后让客户端热曲从Amazon文件等云文件中获取对象(仍可能需要分页才能获取文件名)。

有什么我没有想到的是,这是愚蠢的简单和方式比这些任何选项更好?

回答

24

表中有一个主键。利用它。

而不是LIMITOFFSET,使用主键上的过滤器做你的分页。你在暗示这与您的评论:

寻呼使用随机数(添加“大于ORDER BY”每个 查询)

但没有什么随机你应该怎么做。

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可靠
  • 不同并发修改行为来限制/偏移,参见上文
1

API是否接受从开始的偏移量和要返回的记录数。这是一种分页,客户可以确定在一个页面请求中返回多少条记录。 API还应返回查询可能的记录总数,以便客户端知道有多少个“页面”,或者可选地,它可以在返回的记录数为零或小于要求的记录。您可以在您的SELECT语句中使用OFFSET子句(该记录开始检索)和LIMIT子句(返回的记录数)来控制PostgresSQL查询中的这一点。

+3

使用的问题OFFSET是它需要服务器在“LIMIT”之前迭代整个结果集,因此它会破坏非常大的数据集。我实际上使用了这样做的API,并且在大约100,000次结果后我们遇到了重大问题。 –

相关问题