OFFSET
/LIMIT
子句来实现分页。但是,在这种情况下有一些特殊要求:
- 有很多行数据,我相信用户无法到达末尾(想象Twitter时间轴)。
- 页面不必是随机可访问的,而只能是顺序访问的。
- API将返回一个URL,其中包含一个游标令牌,该令牌指向连续块的页面。
- 游标令牌不必永久存在,只需存在一段时间即可。
- 其排序经常波动(如Reddit排名),但连续的光标应保持其一致的排序。
OFFSET
/LIMIT
子句来实现分页。但是,在这种情况下有一些特殊要求:
store the id list in a postgresql table using the array type rather than in memory. Doing it in memory, unless you carefully use something like redis with auto expiry and memory limits, is setting yourself up for a DOS memory consumption attack. I imagine it would look something like this:
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
);
You need to decide if the cursor_token and result_ids can be shared between users to reduce your storage needs and the time needed to run the initial query per user. If they can be shared, chose a cache window, say 1 or 5 minute(s), and then upon a new request create the cache_token for that time period and then check to see if the results ids have already been calculated for that token. If not, add a new row for that token. You should probably add a lock around the check/insert code to handle concurrent requests for a new token.
Have a scheduled background job that purges old tokens/results and make sure your client code can handle any errors related to expired/invalid tokens.
不要考虑使用真实的数据库游标来处理此问题。
将结果ID保存在Redis列表中是另一种处理方式(请参见LRANGE命令),但如果您选择这种方式,请注意到期时间和内存使用情况。您的Redis键将是cursor_token,而ids将是列表成员。
temp_buffers
的内容),当RAM不足时会写入磁盘。 - Erwin Brandstetter我对PostgreSQL一无所知,但我是一个相当不错的SQL Server开发人员,所以我想尝试一下 :)
您预计每个会话中用户最多会浏览多少行/页?例如,如果您希望用户在每个会话中最多翻阅10页[每页包含50行],则可以将该最大值设置为缓存10 * 50行(或仅为行的ID,这取决于您拥有多少内存/同时用户)。
这肯定会有助于加速您的Web服务,而且实现起来非常容易。所以:
你还可以增加数字,500个整数的数组只占用2K内存,但这也取决于你希望初始查询/响应有多快。
我在一个实时网站上使用了类似的技术,当用户继续翻到第10页时,我就转向查询。我想另一种解决方案是继续扩展/填充数组。(再次运行查询,但排除已包含的ID)。
无论如何,希望这能帮到你!