基于偏移量的分页和基于游标的分页

发布时间 2024-01-09 02:00:12作者: FarewellTears

基于偏移量的分页和基于游标的分页

分页是为避免浏览器在单次请求处理大量数据时出现浏览器崩溃或影响用户使用体验(例如资源消耗过大减缓加载速度,超时与延迟等问题)而提出的解决方案,为此将原本一次请求就返回的大量数据进行特定规模的划分,请求时只返回特定数量的结果。

最常用的两种分页方式:基于偏移量的分页(offset-based pagination)和基于游标的分页(cursor-based pagination)。

差别

分页类型 工作原理 优点 Pros 缺点 Cons
基于偏移量的分页 客户端向服务器传递偏移量,从而返回一定量的数据,过程中需要确定限制大小(page_size)和偏移量(page),为确保在不同条件下检索的结果子集都一致,往往需要确保数据有序 ORDER BY 使得排序结果可预测 易于实现;适用于数据变化不大的数据集;可具体到指定页数的数据 因为数据库总是从头开始扫描,所以在到达目标对象前存在大量跳过的不必要开销,故性能问题不佳;容易引起弹性伸缩问题,若数据集时常变动则可能影响到分页结果,导致最终结果数据存在重复或缺失
基于游标的分页 以传入的一个基于时间的游标或唯一的连续可排序的标识符(例如时间戳UUIDPK)为起点,返回随后的定量数据 游标方便快速定位并返回结果,无需从头开始扫描;适合数据经常变动的场景(例如社交平台实时数据) 实现相对复杂;无法直接跳到指定页数的数据

实现

本例以 created_at 字段为参考,数据库执行带有 WHERE 条件和 ORDER BY 子句的 SELECT 语句进行初次读取

SELECT * FROM posts ORDER BY created_at DESC LIMIT 10;

基于偏移量的分页

后续读取使用 OFFSET 关键字跳过先前行并获取下一组数据

SELECT * FROM posts ORDER BY created_at DESC LIMIT 10 OFFSET 10;

基于游标的分页

后续读取可使用最后一个已知值的列值(如 last_known_created_at)作为下一次提取的游标,定位后获取下一组数据

SELECT * FROM posts WHERE created_at < 'last_known_created_at' ORDER BY created_at DESC LIMIT 10;

Reference

  1. Offset vs Cursor-Based Pagination: Which is the Right Choice for Your Project? | by Olga | Medium
  2. 游标分页较传统分页的优势以及详细实现
  3. 基于偏移量、游标分页的详解 - 掘金 (juejin.cn)
  4. 数据库系列(五)之 mysql的伸缩性 - alun-chen - 博客园 (cnblogs.com)