表中有一个主键。利用它。
而不是LIMIT
和OFFSET
,使用主键上的过滤器做你的分页。你在暗示这与您的评论:
寻呼使用随机数(添加“大于ORDER BY”每个 查询)
但没有什么随机你应该怎么做。
SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2
允许客户端指定两个参数,它看到的最后一个ID和要获取的记录数。你的API必须有一个占位符,额外的参数或者替代呼叫来“获取第一个 n ID”,它在查询中省略了WHERE
子句,但这很简单。
此方法将使用相当有效的索引扫描来按顺序获取记录,通常避免排序或需要遍历所有跳过的记录。客户可以决定一次需要多少行。
这种方法不同于LIMIT
和OFFSET
方法中的一种关键方式:并发修改。如果INSERT
与之间的关键字低于而不是某个客户端已经看到的关键字,则此方法根本不会改变其结果,而OFFSET
方法将重复一行。同样,如果您的DELETE
行数低于已经看过的ID,则此方法的结果不会更改,而OFFSET
将跳过看不见的行。尽管如此,使用生成的关键字只能附加表格也没有区别。
如果您事先知道客户端需要整个结果集,那么最有效的方法就是将整个结果集都发送给它们,而不要使用这个分页业务。这就是我将使用游标的地方。读取数据库中的行并将其发送到客户端的速度与客户端接受它们的速度一样快。此API需要设置限制客户端被允许的速度以避免过多的后端负载;对于慢速客户端,我可能会切换到分页(如上所述)或将整个游标结果暂存到临时文件并关闭数据库连接。
重要注意事项:
- 需要一个
UNIQUE
约束/ UNIQUE
索引或PRIMARY KEY
可靠
- 不同并发修改行为来限制/偏移,参见上文
使用的问题OFFSET是它需要服务器在“LIMIT”之前迭代整个结果集,因此它会破坏非常大的数据集。我实际上使用了这样做的API,并且在大约100,000次结果后我们遇到了重大问题。 –