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

mysql_page pagesize 如何实现游标分页?

这是一种基于排序字段值而不是偏移量的分页方法。

核心思想

记住上一页最后一条记录的位置,然后从这个位置开始查询下一页

逐步分解

第一页查询(基础查询)

SELECT * FROM loc_common_info 
WHERE id NOT IN (1,2,3)  -- 假设用户去过场地1,2,3
AND status = 'ACTIVE'
ORDER BY popularity_score DESC, id DESC
LIMIT 3;  -- 假设每页3条

假设返回结果:

idnamepopularity_score
10场地A95
8场地B95
5场地C90

关键点:我们记录最后一条记录的值:

  • lastScore = 90 (id=5的popularity_score)
  • lastId = 5 (最后一条记录的id)

第二页查询(使用游标)

SELECT * FROM loc_common_info 
WHERE id NOT IN (1,2,3) 
AND status = 'ACTIVE'
-- 关键条件:找到排在"最后一条记录"之后的所有记录
AND (popularity_score < #{lastScore} OR (popularity_score = #{lastScore} AND id < #{lastId}))
ORDER BY popularity_score DESC, id DESC
LIMIT 3;

条件逻辑详解

条件分解:

AND (popularity_score < 90 OR (popularity_score = 90 AND id < 5)
)

这个条件的意思是:

  1. popularity_score < 90

    • 找到所有评分严格小于90的记录
    • 这些记录自然排在评分90的记录后面
  2. popularity_score = 90 AND id < 5

    • 找到评分等于90,但id更小的记录
    • 因为排序是 popularity_score DESC, id DESC,所以id小的排在后面

实际数据示例

假设数据库中有这些数据:

idpopularity_score
1095
895
590
390
785
285
480

第二页查询条件(score < 90) OR (score = 90 AND id < 5)

符合条件的记录:

  • id=3:满足 score = 90 AND id < 5
  • id=7:满足 score < 90
  • id=2:满足 score < 90
  • id=4:满足 score < 90

排序后第二页结果:

idpopularity_score
390
785
285

为什么需要复合排序 ORDER BY score DESC, id DESC

如果只按 popularity_score DESC 排序:

问题场景:多个记录有相同的popularity_score

第一页:id=10(95), id=8(95), id=5(90)  ← 最后一条id=5, score=90
第二页应该显示:id=3(90), id=7(85), id=2(85)

但如果只按score排序,数据库不保证相同score的记录顺序稳定,可能导致:

  • 第一次查询:id=10(95), id=8(95), id=5(90)
  • 第二次查询:id=10(95), id=8(95), id=3(90) ← 顺序变了!

复合排序确保:

  • 主要按popularity_score降序
  • score相同时,按id降序,保证顺序绝对稳定

前端-后端交互流程

// 第一页请求
PageRequest request1 = new PageRequest(0, 3, null); // 没有游标
PageResult result1 = service.getRecommendations(request1);// 返回结果包含下一页游标
String nextCursor = result1.getNextCursor(); // 编码为: "90_5"// 第二页请求
PageRequest request2 = new PageRequest(0, 3, "90_5"); // 使用游标
PageResult result2 = service.getRecommendations(request2);

与传统OFFSET分页对比

OFFSET分页(有问题):

-- 第一页
SELECT ... LIMIT 0, 3;  -- 返回记录1,2,3-- 第二页  
SELECT ... LIMIT 3, 3;  -- 返回记录4,5,6

问题:如果第一页和第二页之间有新数据插入,会导致:

  • 重复记录(新数据挤占了位置)
  • 丢失记录(原有记录被挤到后面)

游标分页(稳定):

-- 第一页:返回id=10,8,5,记住lastScore=90, lastId=5
-- 第二页:查询score<90 OR (score=90 AND id<5)的记录

优势

  • 不受数据增删影响
  • 性能更好(不需要计算OFFSET)
  • 顺序绝对稳定

总结

游标分页的核心就是:记住上一页的终点,从终点开始找下一页,通过复合排序和精确的条件定位,确保分页的准确性和稳定性。

游标对象设计

@Data
public class RecommendationCursor {private String type;        // "new", "rotate", "retain"private Double lastScore;   // 上一页最后一条的popularity_scoreprivate Long lastId;        // 上一页最后一条的IDprivate Integer page;       // 当前页码private String randomSeed;  // 随机种子public static RecommendationCursor parseCursor(String cursorStr, String type) {if (cursorStr == null) {return new RecommendationCursor(type, null, null, 0, generateRandomSeed());}// 解析游标逻辑...}public String toCursorString() {// 生成游标字符串逻辑...}
}

关键要点

  • 不要使用 OFFSET:LIMIT offset, count 在数据量大时性能差且不稳定
  • 游标分页:适合主内容区,保证稳定性和性能
  • 随机分页:适合轮换区,增加多样性
  • 复合排序:ORDER BY score DESC, id DESC 确保排序稳定
  • 状态保持:通过游标或种子保持分页状态

这样设计后,每次分页查询都能返回不同的内容,同时保证性能和稳定性。

http://www.dtcms.com/a/477875.html

相关文章:

  • Hive 拉链表
  • 集宁网站建设SEO优化安卓开发基础教程
  • C++友元函数和友元类!
  • Java面向对象编程深度解析:从对象思维到系统架构的艺术
  • 多制式基站综合测试线的架构与验证实践(4)
  • 洛阳制作网站ihanshi汉口网站建设制作
  • 2025年 Varjo XR-4 升级新品发布!首款专为陆、海、空领域战备训练打造的XR头显
  • 【XR硬件系列】AR眼镜的终极形态会是“普通眼镜”吗?技术瓶颈还有哪些?
  • 发布自己的 jar 包到 Maven 中央仓库 ( mvnrepository.com )
  • 页表 vs. 组相联缓存:内存管理与性能优化的殊途同归
  • 泉州专业建站品牌校园门户网站开发需求分析
  • 版本控制器之Git理论与实战
  • 注册网站时应注意什么域名注册后 免费自建网站
  • wpf passwordbox控件 光标移到最后
  • Linux wlan网络协议栈-路由框架详解
  • 廊坊安次区网站建设公司上海高登联合建设网站
  • 凡科网站手机投票怎么做wordpress vr主题
  • 【ElasticSearch】text 和 keyword 类型区分
  • vue3的组件通信方式汇总
  • PortSwigger靶场之将 XSS 存储到onclick带有尖括号和双引号 HTML 编码以及单引号和反斜杠转义的事件中通关秘籍
  • 哪些方法可以建设网站后台网站模板下载
  • 根据PID获取K8S-Pod名称-反之POD名称获取PID
  • 做网站三年3万块钱论坛搭建一键
  • C#进阶技巧掌握外部进程的启动与控制(一):进程基础与基本操作
  • 昂瑞微:实现精准突破,攻坚射频“卡脖子”难题
  • 延安做网站的公司电话如何用云服务器搭建个人网站
  • shellSort
  • idea一直卡在build不动(Writing class)
  • LSTM自然语言处理情感分析项目(四)整合调用各类与方法形成主程序
  • MySQL为什么选择B+tree索引作为核心索引结构?