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

浙公网安备 33010602011771号