我正在通过HTTP创建一个API,该API通过分页从PostgreSQL中获取许多行。在通常情况下,我通常通过幼稚的OFFET
/ LIMIT
子句实现这种分页。但是,在这种情况下有一些特殊要求:
我如何完成任务?我准备为此更改整个数据库架构!
假设只是结果的顺序波动,而不是行中的数据波动,Fredrik的回答很有意义。但是,我建议添加以下内容:
使用array类型将id列表存储在postgresql表中,而不是存储在内存中。在内存中执行此操作,除非您小心地使用具有自动到期和内存限制的redis之类的东西,否则将使自己很容易受到DOS内存消耗的攻击。我想它看起来像这样:
create table foo_paging_cursor (
cursor_token ..., -- probably a uuid is best or timestamp (see below)
result_ids integer[], -- or text[] if you have non-integer ids
expiry_time TIMESTAMP
);
您需要确定是否可以在用户之间共享cursor_token和result_id,以减少存储需求以及每个用户运行初始查询所需的时间。如果可以共享它们,请选择一个缓存窗口,例如1或5分钟,然后在新请求时为该时间段创建cache_token,然后检查是否已经为该令牌计算了结果ID。如果没有,请为该令牌添加新行。您可能应该在检查/插入代码周围添加一个锁,以处理对新令牌的并发请求。
具有排定的后台作业,该作业将清除旧令牌/结果,并确保您的客户端代码可以处理与过期/无效令牌有关的任何错误。
甚至不考虑为此使用真正的数据库游标。
将结果ID保留在Redis列表中是另一种处理此问题的方法(请参见LRANGE命令),但是如果沿着该路径使用,请注意到期和内存使用情况。您的Redis键将是cursor_token,而ID将是列表的成员。
我对PostgreSQL完全不了解,但是我是一个相当不错的SQL Server开发人员,所以无论如何我都想尝试一下:)您希望用户每次会话最多浏览多少行/页?例如,如果您希望用户为每个会话(每个页面包含50行)最多翻阅10个页面,则可以使用该最大值,并设置网络服务,以便在用户请求第一页时缓存10 * 50行(或者仅是行的Id:s,取决于您获得多少内存/同时用户)。
这肯定会以多种方式帮助您加快Web服务的速度。而且很容易实现。因此:
我在实时网站上使用了类似的技术,当用户继续浏览第10页时,我只是切换到查询。我想另一个解决方案是继续扩展/填充数组。 (再次运行查询,但不包括已经包含的ID:S)。
无论如何,希望这会有所帮助!