当前位置: 首页 > news >正文

游标分页(Cursor-based Pagination)

游标分页是一种基于游标(通常是唯一标识或时间戳)的分页技术,相比传统的LIMIT offset, size分页有显著的性能优势。

传统分页的问题

-- 传统分页:性能随offset增大而下降 SELECT * FROM orders ORDER BY created_time DESC, id DESC LIMIT 100000, 20; -- 需要扫描100020行

游标分页的原理

基本思想

使用唯一的、有序的游标来标记分页位置,而不是使用页码。

实现方式

1. 基于自增主键的游标分页

- 第一页 SELECT * FROM orders ORDER BY id DESC LIMIT 20; -- 第二页:使用上一页最后一条的id作为游标 SELECT * FROM orders WHERE id < 上一页最后一条的id -- 游标条件 ORDER BY id DESC LIMIT 20;

2. 基于时间戳的游标分页

-- 第一页 SELECT * FROM orders ORDER BY created_time DESC, id DESC LIMIT 20; -- 第二页 SELECT * FROM orders WHERE (created_time < 上一页最后时间) OR (created_time = 上一页最后时间 AND id < 上一页最后ID) ORDER BY created_time DESC, id DESC LIMIT 20;

3. 复合游标分页(推荐)

-- 使用(时间戳, ID)作为复合游标 -- 第一页请求 SELECT id, content, created_time FROM posts ORDER BY created_time DESC, id DESC LIMIT 10; -- 第二页请求(客户端记住上一页最后一条的created_time和id) SELECT id, content, created_time FROM posts WHERE (created_time < '2023-01-01 12:00:00') OR (created_time = '2023-01-01 12:00:00' AND id < 1000) ORDER BY created_time DESC, id DESC LIMIT 10;

实际应用示例

API设计示例

// 第一页请求 GET /api/posts?limit=20 // 响应 { "data": [...], "next_cursor": "2023-01-01T10:00:00Z_1000", // 最后一条的游标 "has_more": true } // 第二页请求 GET /api/posts?limit=20&cursor=2023-01-01T10:00:00Z_1000

完整SQL实现

-- 创建适合游标分页的索引 CREATE INDEX idx_posts_cursor ON posts(created_time DESC, id DESC); -- 分页查询函数 CREATE FUNCTION get_posts_by_cursor( p_cursor_time TIMESTAMP DEFAULT NULL, p_cursor_id BIGINT DEFAULT NULL, p_limit INT DEFAULT 20 ) RETURNS TABLE AS $$ BEGIN IF p_cursor_time IS NULL THEN -- 第一页 RETURN QUERY SELECT * FROM posts ORDER BY created_time DESC, id DESC LIMIT p_limit; ELSE -- 后续分页 RETURN QUERY SELECT * FROM posts WHERE (created_time < p_cursor_time) OR (created_time = p_cursor_time AND id < p_cursor_id) ORDER BY created_time DESC, id DESC LIMIT p_limit; END IF; END; $$ LANGUAGE plpgsql;

游标分页的优势

性能对比

分页方式

第1页

第100页

第10000页

LIMIT OFFSET

非常慢

游标分页

具体优势

  1. 恒定性能:无论翻到第几页,性能基本一致

  2. 无数据跳过:不需要OFFSET,避免扫描和跳过大量数据

  3. 实时性更好:适合频繁更新的数据流

  4. 无重复数据:避免传统分页在数据更新时出现的重复或丢失

适用场景

推荐使用游标分页的场景

  • ✅ 社交媒体时间线(Twitter、微博)

  • ✅ 消息列表、聊天记录

  • ✅ 实时数据流(日志、监控数据)

  • ✅ 无限滚动页面

传统分页仍适用的场景

  • ✅ 数据基本不变的列表(商品分类、用户列表)

  • ✅ 需要跳转到特定页码的场景

  • ✅ 数据量不大且offset较小的情况

注意事项

1. 游标必须唯一且有序

-- 错误:只使用时间戳,可能重复 WHERE created_time < '2023-01-01' -- 正确:使用(时间戳, ID)保证唯一性 WHERE (created_time < '2023-01-01') OR (created_time = '2023-01-01' AND id < 1000)

2. 客户端实现

lass CursorPager { constructor() { this.currentCursor = null; this.hasMore = true; } async loadNextPage() { if (!this.hasMore) return; const params = { limit: 20 }; if (this.currentCursor) { params.cursor = this.currentCursor; } const response = await api.get('/items', { params }); this.currentCursor = response.next_cursor; this.hasMore = response.has_more; return response.data; } }

3. 边界情况处理

-- 处理游标不存在的情况 SELECT * FROM posts WHERE (created_time < COALESCE(:cursor_time, NOW())) AND (id < COALESCE(:cursor_id, 2^62)) -- 很大的数作为默认值 ORDER BY created_time DESC, id DESC LIMIT :limit;

总结

游标分页是现代应用中处理大量数据分页的最佳实践,特别适合:

  • 高性能要求的实时应用

  • 大数据量的分页场景

  • 需要良好用户体验的无限滚动

虽然实现比传统分页稍复杂,但带来的性能优势是巨大的。

http://www.zskr.cn/news/1400496.html

相关文章:

  • Lattice LFCPNX-100 HSB+Fpga开发详解: 2.1 MAC+PCS以太网SFP光口传输
  • PlantUML编辑器:用文本快速绘制专业UML图的终极指南
  • 构建极简研究档案库:基于本地文件系统的学术知识聚合与检索方案
  • 基于MCP协议构建智能求职助手:从架构设计到工程实践
  • 不用专业知识 OpenClaw 普通人也能轻松部署
  • 告别手动拷贝!Qt Creator远程调试嵌入式Linux应用的保姆级配置流程(基于Qt 5.15+)
  • GitHub中文界面终极指南:3分钟告别英文困扰
  • 向量数据库与RAG管道:从核心组件到系统工程的关键认知
  • 如何快速掌握OBS多平台直播:obs-multi-rtmp插件完整教程
  • Linux入门到实战·学习笔记系列——10.计算机网络基础概论
  • 5Why分析方法和鱼骨图分析方法
  • 【Claude Code的Harness Engineering实现】:12-状态持久化与Checkpoint(State Persistence)
  • 【测试】之自动化测试概念篇
  • 2026年企业营销必知:揭秘GEO——比SEO更重要的下一代流量密码
  • UniversalUnityDemosaics:终极Unity游戏视觉恢复工具完整指南
  • 读工业软件简史01工厂设计
  • 猫抓插件终极教程:三步轻松下载网页视频资源
  • 【大模型篇】谈谈A2A协议(Agent-to-Agent)
  • 5分钟快速上手:微软官方XML编辑器XML Notepad完全指南
  • 别再只会显示数字了!用TM1637四位数码管做个简易时钟/计数器(附Arduino和STM32代码)
  • 基于保形预测的校准检索:为智能体系统注入统计可靠性
  • AI Agent项目失败率高达80%?深度解析Agent避坑指南
  • 3分钟快速上手:GitHub中文化插件终极指南,让GitHub界面说中文
  • 基于广义加性模型的气候模型偶然不确定性量化实践
  • Unity独立游戏开发:如何用C#脚本在Windows平台强制锁定游戏窗口宽高比(含全屏适配)
  • 5分钟掌握Mermaid Live Editor:免费在线图表编辑器的终极指南
  • 2026年全屋定制行业现状与品牌综合解析 - 产品测评官
  • 聊一聊AI - GEO搜索推广套餐性价比,尚棠科技值得选吗 - 工业品牌热点
  • 从调参到调系统:LangSmith如何重塑LLM应用调试与优化方法论
  • 2026黄金回收价格及靠谱公司,快速黄金回收联系方式推荐 - 工业品牌热点