当前位置: 首页 > 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.jsqmd.com/news/895465/

相关文章:

  • Lattice LFCPNX-100 HSB+Fpga开发详解: 2.1 MAC+PCS以太网SFP光口传输
  • GEE数据集:全球森林变化数据集Hansen Global Forest Change v1.13 (2000-2025)
  • WSL2 吃掉我 25GB C 盘空间:一次完整的排查与回收记录
  • 革命性AI视频字幕去除工具:Video-subtitle-remover一站式解决方案
  • video-subtitle-extractor:如何让AI看懂视频中的“隐形文字“并精准提取?
  • 向量数据库与RAG管道:从核心组件到系统工程的关键认知
  • Linux入门到实战·学习笔记系列——10.计算机网络基础概论
  • 如何快速掌握OBS多平台直播:obs-multi-rtmp插件完整教程
  • 用Unity和C#实现人群疏散模拟:手把手教你搭建社会力模型(附完整代码)
  • 终极指南:5分钟快速上手AzurLaneAutoScript,彻底解放你的碧蓝航线游戏时间
  • 2026杭州GEO优化公司深度横评:5家服务商避坑实测与选型指南 - 品牌报告
  • Windows 11 系统、MySQL 8.0.46 ZIP 解压版、自定义安装目录
  • 2026年4月推拉窗批发厂家推荐,吊趟门/断桥门窗/系统门窗/断桥窗沙一体外开窗/断桥铝合金门窗,推拉窗门店怎么选择 - 品牌推荐师
  • 解锁、截图、删文件都能换声音?macOS Sequoia 新系统太会玩了
  • 魔兽争霸3兼容性修复终极指南:5步解决现代系统运行问题
  • 2026靠谱的感应控制、动态、线光源楼宇外立面灯厂家推荐 - 工业品牌热点
  • API静默变更引发集成故障:防御性编码与监控策略实践
  • 保姆级教程:用博图V17搞定WINCC RT Advanced与S7-1200 PLC的通讯(含PG/PC接口设置避坑)
  • RV1126人脸识别项目实战:手把手教你搞定GC2053红外摄像头驱动配置(附完整DTS代码)
  • 基于广义加性模型的气候模型偶然不确定性量化实践
  • 深圳全屋定制避坑指南:如何甄选靠谱品牌? - 产品测评官
  • Neovim配置踩坑实录:从零搞定Python虚拟环境和C++的clangd语言服务器(Ubuntu 24.04亲测)
  • Unity独立游戏开发:如何用C#脚本在Windows平台强制锁定游戏窗口宽高比(含全屏适配)
  • 面试复盘7.0
  • 2026年全屋定制行业现状与品牌综合解析 - 产品测评官
  • 聊一聊AI - GEO搜索推广套餐性价比,尚棠科技值得选吗 - 工业品牌热点
  • 提取矩阵特定多列元素
  • Python初学者项目练习41--反转头尾并拼接字符串
  • 网页聊天室-测试报告
  • 构建股票分析AI智能体:三大设计模式解决数据幻觉与深度挖掘