Cursor 分页

Cursor 分页(最简单解释版)

一句话理解

Cursor 分页就是:不使用“第几页”,而是记住“上一页最后一条数据的位置”,从那里继续查询。


为什么要用 Cursor 分页?

传统分页通常这样用:

?page=1&pageSize=20
?page=1000&pageSize=20

底层数据库一般是:

OFFSET 19980 ROWS FETCH NEXT 20 ROWS

当页码很大时会出现问题:

  • 查询越来越慢
  • 新数据插入后可能重复或漏数据

Cursor 分页的核心思想

Cursor 分页关注的不是「页码」,而是:

“从哪一条数据之后开始查?”

这个“位置”就叫 Cursor(游标)


直观理解(生活类比)

Offset 分页

你说:我要第 100 页
系统:从第 1 页翻到第 100 页

Cursor 分页

你说:我上次看到第 345 条
系统:直接从第 345 条后面开始

✅ Cursor 分页更快、更稳定


Cursor 分页的请求示例

第一次请求(没有 cursor)

GET /api/orders?limit=20

返回:
{
"items": [ ...20 条数据... ],
"nextCursor": "abc123",
"hasMore": true
}


第二次请求(带 cursor)

GET /api/orders?limit=20&cursor=abc123

cursor 表示:上一页最后一条数据的位置


Cursor 里一般存什么?

通常是 排序字段,例如:

  • CreatedAt(创建时间)
  • Id(唯一 ID,用来防止时间相同)

逻辑结构示例:
{
"CreatedAt": "2026-03-05T10:30:00Z",
"Id": 123456
}

实际对外一般会:

  • JSON 序列化
  • Base64 编码
  • 最终只暴露一个字符串

Cursor 分页的 SQL 思想(重点)

假设排序规则是:

ORDER BY CreatedAt DESC, Id DESC


第一页

SELECT TOP 20 *
FROM Orders
ORDER BY CreatedAt DESC, Id DESC;


下一页(使用 Cursor)

假设 cursor 记录的是:

  • CreatedAt = 2026-03-05 10:30:00
  • Id = 123456

SELECT TOP 20 *
FROM Orders
WHERE
CreatedAt < @CreatedAt
OR (CreatedAt = @CreatedAt AND Id < @Id)
ORDER BY CreatedAt DESC, Id DESC;

✅ 这种查询方式叫 Seek(定位查询)
✅ 数据库可以直接利用索引定位,不需要跳过大量数据


Cursor 分页的优点

  • 性能稳定(不受页码影响)
  • 不容易重复或漏数据
  • 适合大数据量(订单、日志、流水)

Cursor 分页的缺点

  • 不能直接跳到某一页(比如第 100 页)
  • 不适合传统“页码跳转”UI
  • 非常适合「加载更多 / 无限滚动」

什么时候适合用 Cursor 分页?

适合:

  • 时间线 / 日志 / 订单列表
  • 数据量大
  • 按时间或 ID 排序

不适合:

  • 报表类、强依赖页码跳转的页面

总结

Cursor 分页不是“翻页”,而是“接着上次继续查”。
它用“位置”代替“页码”,换来更好的性能和数据稳定性。

posted @ 2026-03-05 14:30  vvull  阅读(0)  评论(0)    收藏  举报