昆明网站建站平台,网站链轮内有死链,网上免费开店怎么开,注册公司费用流程图文章目录概述对比工作原理性能对比查询性能对比数据库负载对比代码示例传统分页示例请求响应SQL执行游标分页示例首次请求#xff08;无游标#xff09;响应后续请求#xff08;使用游标#xff09;SQL执行游标分页最佳实践总结选择建议概述
对比
特性传统分页游标分页定…文章目录概述对比工作原理性能对比查询性能对比数据库负载对比代码示例传统分页示例请求响应SQL执行游标分页示例首次请求无游标响应后续请求使用游标SQL执行游标分页最佳实践总结选择建议概述对比特性传统分页游标分页定义使用 OFFSET 和 LIMIT 参数通过跳过前面的记录来获取指定页的数据。使用一个游标cursor来标记当前位置基于游标位置获取后续数据。特点1. 需要知道总记录数COUNT查询2. 使用页码page和每页数量size3. 可以跳转到任意页面1. 不需要总记录数2. 使用游标cursor和每页数量size3.只能顺序翻页不能跳转优点1. 可以跳转页面用户可以直接跳转到第N页2. 显示总数可以显示总记录数和总页数3. 实现简单逻辑直观易于理解4. 兼容性好所有数据库都支持OFFSET和LIMIT1.性能优秀 不需要COUNT(*)查询 查询速度稳定不受数据量影响 使用索引高效定位2.数据一致性 基于游标位置查询不受数据变化影响 不会出现重复或遗漏数据3.资源消耗低 不需要统计总数 查询效率高缺点1.性能问题COUNT(*)查询在大数据量下很慢OFFSET越大查询越慢需要跳过更多记录2.数据一致性问题 在翻页过程中如果有数据新增或删除可能导致- 重复数据同一数据出现在两页- 遗漏数据某些数据永远不会被看到1. 不能跳转页面只能顺序翻页不能直接跳转到第N页2. 显示总数无法显示总记录数和总页数3. 实现复杂需要处理游标编码/解码4. 游标管理需要确保游标的唯一性和稳定性应用场景1.需要显示总数和总页数 商品列表需要显示共1000件商品 订单列表需要显示共50页2.需要跳转页面 用户可以输入页码跳转 需要显示页码导航1, 2, 3…3.数据量不大 数据量在10万以内 查询频率不高4.管理后台 管理员需要查看总数 需要跳转到指定页面1.大数据量场景 数据量超过10万条 需要高性能查询2.移动端列表 无限滚动加载 不需要显示总数3.实时性要求高 数据频繁变化 需要保证数据一致性4.C端应用 用户主要浏览最新数据 不需要跳转到历史页面5.时间线/动态流 微博、朋友圈等时间线 订单列表按时间排序工作原理-- 先查询总数SELECTCOUNT(*)FROMtrade_orderWHEREuser_idxxx;-- 第一页page1, size10SELECT*FROMtrade_orderWHEREuser_idxxxORDERBYcreate_timeDESCLIMIT10OFFSET0;-- 第二页page2, size10SELECT*FROMtrade_orderWHEREuser_idxxxORDERBYcreate_timeDESCLIMIT10OFFSET10;执行流程执行COUNT(*)查询获取总记录数根据页码计算OFFSET (page - 1) * size执行主查询跳过OFFSET条记录返回当前页数据和总数-- 第一页无游标SELECT*FROMtrade_orderWHEREuser_idxxxORDERBYcreate_timeDESC,idDESCLIMIT11;-- 查询11条用于判断是否有更多数据-- 第二页使用游标SELECT*FROMtrade_orderWHEREuser_idxxxAND(create_time2025-12-16 10:00:00OR(create_time2025-12-16 10:00:00ANDidxxx-uuid))ORDERBYcreate_timeDESC,idDESCLIMIT11;执行流程如果有游标解码游标获取createTime和id添加游标条件create_time cursor.createTime OR (create_time cursor.createTime AND id cursor.id)查询size 1条数据多查1条用于判断是否有更多数据如果返回size 1条说明还有更多数据返回前size条并生成下一个游标如果返回 ≤size条说明没有更多数据性能对比查询性能对比说明传统分页的COUNT(*)查询时间随数据量线性增长传统分页的OFFSET越大查询越慢游标分页性能稳定不受数据量和页码影响数据库负载对比操作传统分页游标分页每次查询SQL数量2条COUNT SELECT1条SELECTCOUNT查询需要全表扫描或索引扫描不需要OFFSET操作需要跳过N条记录不需要索引利用部分利用完全利用代码示例传统分页示例请求POST /api-portal/trade/order/page { page: 2, size: 10, status: 10, createTime: [2025-11-16 00:00:00, 2025-12-16 00:00:00] }响应{ code: 0, data: { list: [...], total: 1000, page: 2, size: 10, pages: 100 } }SQL执行-- 1. 查询总数 SELECT COUNT(*) FROM trade_order WHERE user_id xxx AND status 10 AND create_time BETWEEN 2025-11-16 AND 2025-12-16; -- 2. 查询数据 SELECT * FROM trade_order WHERE user_id xxx AND status 10 AND create_time BETWEEN 2025-11-16 AND 2025-12-16 ORDER BY create_time DESC LIMIT 10 OFFSET 10;游标分页示例首次请求无游标POST /api-portal/trade/order/cursor-page { size: 10, status: 10, createTime: [2025-11-16 00:00:00, 2025-12-16 00:00:00] }响应{ code: 0, data: { list: [...], nextCursor: MjAyNS0xMi0xNlQxMDowMDowMHw2ZTdhNTVlYi0zMzc0LTRjMDYtYmEzZi1mZGUwMmU5MGU5MWU, hasMore: true } }后续请求使用游标POST /api-portal/trade/order/cursor-page { cursor: MjAyNS0xMi0xNlQxMDowMDowMHw2ZTdhNTVlYi0zMzc0LTRjMDYtYmEzZi1mZGUwMmU5MGU5MWU, size: 10, status: 10, createTime: [2025-11-16 00:00:00, 2025-12-16 00:00:00] }SQL执行-- 查询 size 1 条数据 SELECT * FROM trade_order WHERE user_id xxx AND status 10 AND create_time BETWEEN 2025-11-16 AND 2025-12-16 AND (create_time 2025-12-16 10:00:00 OR (create_time 2025-12-16 10:00:00 AND id xxx-uuid)) ORDER BY create_time DESC, id DESC LIMIT 11;⚠️需要注意的问题游标设计游标必须唯一且稳定使用createTime id组合游标字段必须有索引使用 Base64 编码保护游标排序字段必须使用唯一字段作为排序依据如id避免使用可能重复的字段如createTime单独排序游标失效如果数据被删除游标可能失效需要处理游标解析失败的情况关键字查询JOIN 查询时需要注意性能使用DISTINCT去重游标分页最佳实践✅推荐做法游标格式// 使用 createTime|id 格式Base64编码 cursor Base64.encode(2025-12-16T10:00:00|uuid-string)排序规则ORDER BY create_time DESC, id DESC -- 确保排序的唯一性和稳定性游标条件WHERE (create_time cursor.createTime OR (create_time cursor.createTime AND id cursor.id))判断是否有更多数据// 查询 size 1 条 ListOrder orders query(size 1); boolean hasMore orders.size() size; if (hasMore) { orders orders.subList(0, size); nextCursor createCursor(orders.get(size - 1)); }总结选择建议场景推荐方案原因移动端列表无限滚动游标分页性能好数据一致管理后台需要总数传统分页需要显示总数和跳转大数据量10万游标分页性能优势明显小数据量10万传统分页实现简单实时数据流游标分页数据一致性好需要跳转页面传统分页游标分页不支持