mysql游标分页详解:让分页又快又稳的终极方案

一、什么是游标分页?

游标分页是一种更高效的分页方式,它通过"记住当前位置"而不是"数页码"来实现分页。就像看书时夹书签一样,游标分页会记住你看到哪里了,下次直接从那里继续。

传统分页 vs 游标分页

传统分页(LIMIT-OFFSET)

  • 工作原理:每次都要从头开始数
  • 类似场景:老师点名,“从第21号同学开始,叫10个人”

游标分页

  • 工作原理:记住最后一条的位置
  • 类似场景:看书时夹书签,“从第128页继续看”

二、为什么需要游标分页?

传统分页有三个大问题:

  1. :越往后翻页越慢

    • 查第1页:LIMIT 10 OFFSET 0 → 快
    • 查第100页:LIMIT 10 OFFSET 1000 → 慢
  2. 不稳定:数据变化会导致重复或遗漏

    • 新增数据:可能导致重复显示
    • 删除数据:可能导致记录丢失
  3. 浪费资源:每次都要处理所有数据

三、游标分页怎么用?

基础用法(使用ID)

-- 第一页
SELECT * FROM products ORDER BY id DESC LIMIT 10;

-- 下一页(记住最后一条id=123)
SELECT * FROM products 
WHERE id < 123  -- 关键在这里
ORDER BY id DESC 
LIMIT 10;

高级用法(多字段排序)

-- 按价格排序,价格相同按ID排序
SELECT * FROM products 
WHERE (price < 上一页最后价格) 
   OR (price = 上一页最后价格 AND id < 上一页最后ID)
ORDER BY price DESC, id DESC
LIMIT 10;

四、游标分页的三大优势

  1. 速度快:不管翻到第几页,速度都一样快
  2. 稳定性好:数据变化影响小
  3. 节省资源:数据库不用处理不需要的数据

五、实际应用中的问题与解决方案

问题1:删除数据导致页面变化

场景

  • 第一页:id 1-10
  • 删除id=5
  • 第二页本应从11开始,但现在id=11变成了第10条

解决方案

// 记录已经看过的ID
Set<Long> viewedIds = new HashSet<>();

// 查询时排除已读
String sql = "SELECT * FROM products " +
             "WHERE id < ? AND id NOT IN (" + viewedIds + ") " +
             "ORDER BY id DESC LIMIT 10";

问题2:新增数据导致顺序变化

解决方案

-- 添加时间字段辅助判断
SELECT * FROM products
WHERE (created_at < ?last_time OR 
      (created_at = ?last_time AND id < ?last_id))
ORDER BY created_at DESC, id DESC
LIMIT 10;

六、最佳实践建议

  1. 简单场景:只用ID游标

    SELECT * FROM table WHERE id > ?last_id ORDER BY id LIMIT 10;
    
  2. 复杂排序:用组合游标

    SELECT * FROM products 
    WHERE (price < ? OR (price = ? AND id < ?)) 
    ORDER BY price DESC, id DESC 
    LIMIT 10;
    
  3. 高并发系统:缓存游标位置

    # 用Redis记录每页的最后位置
    cursor = redis.get(f"page:{page_num}")
    

七、不同数据库的实现

数据库推荐写法
MySQLWHERE id < ?last_id
PostgreSQLWHERE (price,id) < (?,?)
MongoDBfind({$or: [{price:{$lt:lastPrice}}, {price:lastPrice, _id:{$lt:lastId}}]})

八、常见问题解答

Q:游标分页能跳页吗?
A:原生不支持,但可以通过缓存页码到游标的映射关系实现

Q:数据经常变动怎么办?
A:使用"创建时间+ID"组合游标,或者接受最终一致性

Q:游标需要加密吗?
A:建议加密,防止用户篡改游标参数

总结

游标分页是处理大数据分页的最佳选择,它解决了传统分页的三个痛点:速度慢、不稳定、资源浪费。实现时要记住三个要点:

  1. 选择稳定的游标字段(如ID、时间戳)
  2. 确保排序规则明确(多字段组合排序)
  3. 合理设计索引(与ORDER BY保持一致)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hi星尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值