可能重复:
How to provide an API client with 1,000,000 database results?
想知道使用Cursors是使用PostgreSQL实现“分页”的好方法。
用例是我们有超过100,000行,我们希望为我们的API客户端提供这些行。我们认为实现这一目标的一个好方法是允许客户端批量(页面)请求信息。客户端可以一次请求100行。我们将返回100行以及一个游标,然后当客户端准备就绪时,他们可以使用我们发送给他们的游标请求接下来的100行。
但是,我对游标的工作方式以及如何以及何时应该使用游标有点模糊:
非常感谢!
答案 0 :(得分:27)
在使用大型数据集的较小Intranet应用程序中,游标是分页的合理选择,但您需要准备在超时后丢弃它们。用户喜欢闲逛,去吃午餐,去度假两周等,并让他们的应用程序继续运行。如果它是一个基于网络的应用程序,甚至还有“运行”是什么以及如何判断用户是否还在的问题。
它们不适用于具有高客户端数量的大型应用程序以及像基于Web的应用程序或Web API那样随机出现的客户端。我不建议在你的应用程序中使用游标,除非你有一个相当小的客户端数和非常高的请求率......在这种情况下,发送微小批量的行将是非常低效的,你应该考虑允许范围请求等。 / p>
游标有几个成本。如果光标不是WITH HOLD
,则必须保持事务处于打开状态。打开事务可以防止autovacuum正常工作,导致表膨胀和其他问题。如果光标被声明为WITH HOLD
并且事务未保持打开,则必须支付实现和存储可能较大的结果集的成本 - 至少,我认为这是保持游标的工作方式。替代方案同样糟糕,保持事务隐式打开,直到光标被销毁并阻止行被清除。
此外,如果您使用游标,则无法将连接传回连接池。每个客户端需要一个连接。这意味着更多的后端资源仅用于维护会话状态,并为使用基于游标的方法处理的客户端数量设置了非常实际的上限。
与具有限制和偏移的无状态连接池方法相比,管理有状态的基于游标的设置还存在复杂性和开销。您需要在超时后使应用程序到期游标,或者您在服务器上面临可能无限制的资源使用,并且您需要跟踪哪些连接具有哪些游标的哪些用户的游标....
一般而言,尽管效率非常低,LIMIT
和OFFSET
可能是更好的解决方案。 It can often be better to search the primary key rather than using OFFSET
, though
顺便说一句,您正在查看PL / pgSQL中游标的文档。你希望normal SQL-level cursors完成这项工作。
游标是否要求保持数据库连接处于打开状态?
是
游标是否在事务中运行,将资源锁定到它们之前 是“关闭”?
是,除非它们是WITH HOLD
,在这种情况下它们会消耗其他数据库资源。
还有其他我不知道的“陷阱”吗?
是的,正如上面应该解释的那样。
答案 1 :(得分:1)
对于HTTP客户端,请勿使用游标实现分页。对于可伸缩性,您不希望服务器资源在请求之间捆绑。
相反,在查询中使用LIMIT和OFFSET;见LIMIT
and OFFSET
in the Pg docs。
但请确保表格上的索引支持对此表单进行有效查询。
设计RESTful API,以便客户端可以调用“next_url”(也在响应中传递)以获取下一组行。