在网络中使用PostgreSQL获取连续列表的最佳方法

min*_*hee 8 postgresql pagination http continuous cursor

我正在通过HTTP制作API,它通过分页从PostgreSQL中获取大行.在通常情况下,我通常通过naive OFFET/ LIMITclause 实现这样的分页.但是,在这种情况下有一些特殊要求:

  • 有很多行,但我相信用户无法达到目的(想象Twitter的时间表).
  • 页面不能随机访问,而是可以顺序访问.
  • API将返回一个URL,其中包含一个指向连续块页面的游标标记.
  • 游标代币不能永久存在,但有一段时间.
  • 它的排序频繁波动(如Reddit排名),但连续游标应保持一致的排序.

我怎样才能完成任务?我准备为它改变我的整个数据库架构!

Tav*_*udd 6

假设它只是结果的排序波动而不是行中的数据,Fredrik的答案是有道理的.但是,我建议添加以下内容:

  • 使用数组类型而不是在内存中将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
    );
    
    Run Code Online (Sandbox Code Playgroud)
  • 您需要确定是否可以在用户之间共享cursor_token和result_ids,以减少存储需求和每个用户运行初始查询所需的时间.如果可以共享它们,请选择一个缓存窗口,比如说1或5分钟,然后在新请求时创建该时间段的cache_token,然后检查是否已经为该令牌计算了结果ID.如果没有,请为该令牌添加新行.您应该在检查/插入代码周围添加一个锁来处理对新令牌的并发请求.

  • 拥有一个清除旧令牌/结果的预定后台作业,并确保您的客户端代码可以处理与过期/无效令牌相关的任何错误.

甚至不考虑使用真正的db游标.

将结果ID保存在Redis列表中是另一种处理此问题的方法(请参阅LRANGE命令),但如果沿着该路径走,请注意过期和内存使用情况.您的Redis键将是cursor_token,而ids将是列表的成员.