在处理大型数据集的小型 Intranet 应用程序中,游标是分页的合理选择,但您需要准备好在超时后丢弃它们。用户喜欢闲逛、去吃午饭、去度假两周等,然后让他们的应用程序继续运行。如果它是一个基于网络的应用程序,甚至还有什么是“正在运行”以及如何判断用户是否还在附近的问题。
它们不适合具有大量客户端的大型应用程序以及几乎随机进出的客户端,例如基于 Web 的应用程序或 Web API。我不建议在您的应用程序中使用游标,除非您的客户端数量相当少且请求率非常高......在这种情况下发送小批量的行将非常低效,您应该考虑允许范围请求等。
光标有几个成本。如果光标不是WITH HOLD
,您必须保持事务打开。打开的事务可能会阻止 autovacuum 正常工作,从而导致表膨胀和其他问题。如果声明了游标WITH HOLD
并且事务未保持打开状态,则您必须支付实现和存储可能很大的结果集的成本——至少,我认为保持游标是这样工作的。另一种方法同样糟糕,保持事务隐式打开直到游标被破坏并防止行被清理。
此外,如果您使用游标,则无法将连接交回连接池。每个客户端需要一个连接。这意味着更多的后端资源仅用于维护会话状态,并为您可以使用基于游标的方法处理的客户端数量设置了一个非常真实的上限。
与具有限制和偏移的无状态连接池方法相比,管理有状态的、基于游标的设置也存在复杂性和开销。您需要让您的应用程序在超时后使游标过期,否则您将面临服务器上潜在的无限资源使用,并且您需要跟踪哪些连接具有哪些游标针对哪些结果集针对哪些用户......
一般来说,尽管它可能效率很低,但LIMIT
可能OFFSET
是更好的解决方案。不过,搜索主键通常比使用 更好OFFSET
。
顺便说一句,您正在查看 PL/pgSQL 中游标的文档。您需要此作业的普通 SQL 级游标。
游标是否要求数据库连接保持打开状态?
是的。
游标是否在事务中运行,锁定资源直到它们“关闭”?
是的,除非它们是WITH HOLD
,在这种情况下它们会消耗其他数据库资源。
还有其他我不知道的“陷阱”吗?
是的,正如上面应该解释的那样。