Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Http 在web中使用PostgreSQL获取连续列表的最佳方法_Http_Postgresql_Pagination_Cursor_Continuous - Fatal编程技术网

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

Http 在web中使用PostgreSQL获取连续列表的最佳方法,http,postgresql,pagination,cursor,continuous,Http,Postgresql,Pagination,Cursor,Continuous,我正在通过HTTP制作一个API,它通过分页从PostgreSQL获取许多行。在一般情况下,我通常通过naiveOFFET/LIMIT子句实现这种分页。但是,在这种情况下有一些特殊要求: 有很多行,所以我相信用户无法到达终点(想象一下Twitter的时间线) 页面不必随机访问,只需按顺序访问即可 API将返回一个URL,其中包含指向连续块页面的游标标记 光标标记不必永久存在,而必须存在一段时间 它的排序经常波动(如Reddit排名),但是连续的游标应该保持其一致的排序 我怎样才能完成任务?我

我正在通过HTTP制作一个API,它通过分页从PostgreSQL获取许多行。在一般情况下,我通常通过naive
OFFET
/
LIMIT
子句实现这种分页。但是,在这种情况下有一些特殊要求:

  • 有很多行,所以我相信用户无法到达终点(想象一下Twitter的时间线)
  • 页面不必随机访问,只需按顺序访问即可
  • API将返回一个URL,其中包含指向连续块页面的游标标记
  • 光标标记不必永久存在,而必须存在一段时间
  • 它的排序经常波动(如Reddit排名),但是连续的游标应该保持其一致的排序
我怎样才能完成任务?我已经准备好为它更改整个数据库模式

我对PostgreSQL一无所知,但我是一个相当不错的SQL Server开发人员,所以我想尝试一下:)

您希望用户在每个会话中最多浏览多少行/页?例如,如果您希望用户在每个会话中最多翻页10页[每页包含50行],您可以设置该最大值,并设置Web服务,以便当用户请求第一页时,缓存10*50行(或仅缓存行的Id:s,取决于您拥有的内存/同时用户的数量)

这肯定有助于加快您的Web服务的速度,其方式不止一种。而且它很容易实现。因此:

  • 当用户从第1页请求数据时。运行一个查询(包括order by、join checks等),将所有id存储到一个数组中(但最多500个id)。返回与数组中位于位置0-9的id:s对应的数据行
  • 当用户请求第2-10页时。返回与位置处数组中id:s对应的数据行(第1页)*50-(第50页)*50-1页)
您还可以增加数字,一个500 int:s的数组只会占用2K的内存,但这也取决于您希望初始查询/响应的速度

我在一个实时网站上使用了类似的技术,当用户继续浏览第10页时,我只是切换到查询。我想另一个解决方案是继续扩展/填充阵列。(再次运行查询,但不包括已包含的id:s)


无论如何,希望这有帮助

假设只有结果的顺序波动,而不是行中的数据,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
    );
    
  • 您需要决定是否可以在用户之间共享游标标记和结果ID,以减少存储需求和每个用户运行初始查询所需的时间。如果它们可以共享,请选择一个缓存窗口,例如1或5分钟,然后根据新请求创建该时间段的缓存令牌,然后检查是否已计算该令牌的结果ID。如果不是,则为该令牌添加新行。您可能应该在check/insert代码周围添加一个锁,以处理对新令牌的并发请求

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

<>不要考虑使用真正的DB游标。
将结果ID保存在Redis列表中是处理此问题的另一种方法(请参阅命令),但如果您使用此方法,请小心过期和内存使用。您的Redis键将是游标标记,ID将是列表的成员。

只是为了确定您的要求。你是说很多行还是很宽的行,或者两者都有?@StarShip3000谢谢。很多行。这只需要使用游标吗?因为还有其他方法不需要更好地管理游标,所以将其设置为临时表。更快,更少的磁盘负载。无需担心DOS攻击,临时表只能使用有限的RAM(当RAM不足时,读取并写入磁盘。临时表是会话本地表,在会话终止时会被删除。因此,在db连接池或http api端点分布在多个节点上并使用不同连接的情况下,这将不起作用。在安装appserver时,也会导致问题。)重新启动,必须重新连接到数据库。也就是说,将表放入内存支持的(通过tmpfs)表空间也可以获得同样的好处。请参阅,谢谢您的建议。我决定使用memcached,并将逗号分隔的ID存储到过期的键(光标标记)中。谢谢!