面试官灵魂一问:MySQL 深度分页如何优化?(修订版)
在线 Java 面试刷题持续更新https://www.quanxiaoha.com/java-interview面试考察点问题识别能力面试官不仅仅是想知道优化方案更是想看你能否识别出深度分页的性能瓶颈——为什么LIMIT 1000000, 10会慢MySQL 到底在做什么原理理解深度考察你是否理解 MySQL 的LIMIT offset, size执行机制——它需要扫描 offset size 条记录再丢弃前面的而不是直接跳到第 offset 条。方案选型思维深度分页有多种优化方案考察你能否根据业务场景是否允许用户跳页、是否有连续自增主键等选择最合适的方案。核心答案深度分页问题当使用LIMIT offset, size且offset值很大时MySQL 需要扫描offset size条记录后丢弃前面的offset条性能急剧下降。优化方案对比方案核心思路适用场景性能提升子查询优化先查主键 ID再回表查数据有自增主键索引⭐⭐⭐⭐INNER JOIN同上写法不同有自增主键索引⭐⭐⭐⭐游标分页记录上次最大 ID下次从该 ID 开始连续翻页、不支持跳页⭐⭐⭐⭐⭐BETWEEN 范围查询用 ID 范围替代 LIMIT offsetID 连续、无断层⭐⭐⭐⭐⭐业务限制限制最大页数禁止深度跳页搜索引擎类场景⭐⭐⭐一句话总结深度分页的本质是offset导致的全表扫描优化核心是 **利用索引直接定位起始点避免扫描后丢弃**。深度解析一、问题本质为什么深度分页会慢先看一个典型的深度分页 SQLSELECT * FROM orders ORDER BY id LIMIT 1000000, 10;很多人的误解MySQL 会直接跳到第 100 万条记录然后取 10 条。实际情况MySQL 的执行流程是img上图展示了LIMIT 1000000, 10的执行过程。关键问题在于扫描量大MySQL 需要扫描1000000 10 1000010条记录而不是只扫描 10 条丢弃浪费前 100 万条记录全部被扫描后丢弃做了无用功回表开销如果查询的是SELECT *每条记录都要回表获取完整数据代价更大时间复杂度O(offset size)offset 越大性能越差这就是为什么LIMIT 100, 10很快但LIMIT 1000000, 10会慢几个数量级。二、方案一子查询优化核心思想先通过子查询利用覆盖索引快速定位起始 ID再回表查数据避免大量无意义的回表操作。-- 原始慢查询假设执行时间5 秒 SELECT * FROM orders ORDERBYidLIMIT1000000, 10; -- 优化后假设执行时间0.1 秒 SELECT * FROM orders o INNERJOIN ( SELECTidFROM orders ORDERBYidLIMIT1000000, 10 ) t ON o.id t.id;为什么更快img上图展示了子查询优化的核心原理。关键优化点在于覆盖索引子查询只查id字段可以直接在索引上完成无需回表减少回表子查询阶段扫描 100 万条时不需要回表只有最终的 10 条才回表性能对比原始查询回表 100 万次优化后只回表 10 次三、方案二游标分页Cursor-based Pagination—— 性能最优核心思想记录上一页最后一条记录的 ID下次查询时直接从该 ID 之后开始完全避开offset。-- 第一页 SELECT * FROM orders ORDERBYidLIMIT10; -- 假设第一页最后一条记录的 id 10 -- 第二页传统方式LIMIT 10, 10 -- 第二页游标方式记住上一页最后的 id SELECT * FROM orders WHEREid 10ORDERBYidLIMIT10; -- 第 N 页假设上一页最后的 id 1000000 SELECT * FROM orders WHEREid 1000000ORDERBYidLIMIT10;img上图对比了传统分页和游标分页的性能差异。关键优势在于稳定性能无论翻到第几页每次都只扫描size条记录性能恒定索引定位WHERE id last_id可以直接利用主键索引定位到起始位置无丢弃浪费不存在扫描后丢弃的问题游标分页的局限性不支持跳页用户只能上一页/下一页不能直接跳到第 N 页需要连续 ID如果 ID 不连续或有删除可能导致某些记录被跳过或重复前端需要记住游标需要保存上一页最后的 ID 值四、方案三BETWEEN 范围查询如果 ID 连续且业务允许可以用 ID 范围替代LIMIT offset-- 假设每页 10 条要查第 100001 页 -- 起始 ID (100001 - 1) * 10 1 1000001 -- 结束 ID 1000001 9 1000010 SELECT * FROM orders WHERE id BETWEEN 1000001 AND 1000010;适用条件ID 必须连续没有断层需要知道 ID 的分布规律五、方案四业务层面限制 —— 最实用的方案很多大厂的做法直接限制用户只能翻到前 N 页。img实现方式// 后端校验 public PageResultOrder listOrders(int pageNum, int pageSize) { // 限制最大页数 int maxPage 100; if (pageNum maxPage) { throw new BusinessException(最多只能查看前 maxPage 页); } // 正常查询 return orderMapper.selectPage(pageNum, pageSize); }六、实际性能对比100 万条数据测试查询方式SQL执行时间原始查询SELECT * FROM orders LIMIT 1000000, 10~5s子查询优化SELECT * FROM orders o INNER JOIN (SELECT id FROM orders LIMIT 1000000, 10) t ON o.id t.id~0.1s游标分页SELECT * FROM orders WHERE id 1000000 LIMIT 10~0.01s面试高频追问追问一游标分页有什么缺点什么场景不适合用答不支持跳页、需要前端保存游标状态、ID 不连续时可能漏数据。电商搜索结果页适合但后台管理系统需要跳页就不适合。追问二如果排序字段不是主键 ID而是create_time怎么优化答可以用联合索引(create_time, id)子查询改为SELECT id FROM orders ORDER BY create_time, id LIMIT offset, size游标分页改为WHERE (create_time, id) (last_time, last_id)。追问三为什么子查询只查id就能提升性能答因为只查主键/索引列时MySQL 可以使用覆盖索引直接在索引树上获取数据不需要回表去聚簇索引查完整记录。常见面试变体为什么LIMIT 1000000, 10会很慢MySQL 分页查询怎么优化百万级数据分页怎么处理介绍几种分页优化方案及其适用场景记忆口诀深度分页优化三句话子查询先查 id覆盖索引省回表游标记住 last_id直接定位无扫描业务限制最大页性价比高最实用总结深度分页的性能问题本质是offset导致的大量无效扫描。优化核心是 **用索引直接定位避免扫描后丢弃**生产环境推荐子查询 JOIN兼容跳页或游标分页性能最优同时配合业务层限制最大页数这是最经济实用的方案。 欢迎加入小哈的星球你将获得:专属的项目实战多个项目 / 1v1 提问 /Java 学习路线 /学习打卡 / 每月赠书 / 社群讨论新项目《Spring AI 项目实战》正在更新中..., 基于 Spring AI Spring Boot 3.x JDK 21;《从零手撸仿小红书微服务架构》 已完结基于 Spring Cloud Alibaba Spring Boot 3.x JDK 17..., 点击查看项目介绍演示地址http://116.62.199.48:7070/《从零手撸前后端分离博客项目全栈开发》2期已完结,演示链接http://116.62.199.48/;专栏阅读地址https://www.quanxiaoha.com/column截止目前累计输出 100w 字讲解图 4013 张还在持续爆肝中..后续还会上新更多项目目标是将 Java 领域典型的项目都整一波如秒杀系统, 在线商城, IM 即时通讯Spring Cloud Alibaba 等等戳我加入学习解锁全部项目已有4500小伙伴加入1. 我的私密学习小圈子从0到1手撸企业实战项目~ 2. 阿里二面什么是 MySQL 回表查询如何避免修订版 3. Nacos 点了下线为什么流量还是打到了停机的机器上 4. 如何画出一张优秀的架构图老鸟必备最近面试BAT整理一份面试资料《Java面试BATJ通关手册》覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式点“在看”关注公众号并回复 Java 领取更多内容陆续奉上。PS因公众号平台更改了推送规则如果不想错过内容记得读完点一下“在看”加个“星标”这样每次新文章推送才会第一时间出现在你的订阅列表里。 点“在看”支持小哈呀谢谢啦
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2443506.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!