news 2026/6/10 23:00:40

SELECT * FROM table LIMIT 1000000, 10的庖丁解牛

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SELECT * FROM table LIMIT 1000000, 10的庖丁解牛

SELECT * FROM table LIMIT 1000000, 10是典型的深度分页查询,表面看是“跳过 100 万行取 10 行”,实则触发全表扫描 + 内存排序,导致磁盘 I/O 爆炸、响应时间飙升


一、执行机制:MySQL 如何处理LIMIT offset, size

▶ 1.执行流程

无索引

有索引

解析 SQL

生成执行计划

是否有索引?

全表扫描 1000010 行

索引扫描 1000010 行

D/E

丢弃前 1000000 行

返回后 10 行

▶ 2.关键问题
  • 必须扫描offset + size
    • 即使只需 10 行,也需读取 1,000,010 行
  • 无法跳过中间行
    • MySQL 不存储“第 N 行的物理位置”(除非聚簇索引)

💡核心认知
LIMIT offset, size的成本 = O(offset + size),而非 O(size)


二、性能陷阱:为什么深度分页如此昂贵?

▶ 1.磁盘 I/O 爆炸
  • 场景
    • 表数据未完全缓存到 Buffer Pool
    • 每读一行需 1 次磁盘随机读(HDD ≈ 10ms/次)
  • 计算
    • 1,000,010 行 × 10ms =2.78 小时(理论值,实际因缓存略低)
▶ 2.内存与 CPU 浪费
  • 排序开销
    • 若无合适索引,需filesort(磁盘临时文件)
  • 网络传输
    • 丢弃的 100 万行仍需从存储引擎传到 Server 层
▶ 3.锁竞争加剧
  • InnoDB 行锁
    • 扫描过程中持有行锁 → 阻塞其他写操作
  • MVCC 版本链
    • 大量历史版本堆积 → Undo Log 膨胀

三、工程优化:四种替代方案

▶ 方案 1:基于游标的分页(推荐)
  • 原理
    • 记录上一页最后一条记录的排序字段值
    • 下一页从该值开始查询
  • 示例
    -- 第一页SELECT*FROMordersWHEREid>0ORDERBYidLIMIT10;-- 第二页(假设上一页最大 id=100)SELECT*FROMordersWHEREid>100ORDERBYidLIMIT10;
  • 优势
    • 执行计划:range→ 直接定位起始点
    • 成本:O(size),与 offset 无关
▶ 方案 2:延迟关联(Deferred Join)
  • 原理
    • 先通过覆盖索引获取主键
    • 再回表查询完整数据
  • 示例
    SELECTt.*FROMorders tINNERJOIN(SELECTidFROMordersORDERBYidLIMIT1000000,10)tmpONt.id=tmp.id;
  • 适用场景
    • 主键为聚簇索引(InnoDB)
    • 覆盖索引可避免回表
▶ 方案 3:记录偏移量(适用于静态数据)
  • 原理
    • 预先计算每页的起始主键
    • 存储到缓存(如 Redis)
  • 示例
    // 缓存第 100000 页起始 ID$startId=Redis::get('page_100000_start_id');$rows=DB::select("SELECT * FROM orders WHERE id >= ? ORDER BY id LIMIT 10",[$startId]);
▶ 方案 4:禁止深度分页
  • 产品设计
    • Google 搜索仅显示前 10 页
    • 电商网站限制“跳转到第 N 页”
  • 技术实现
    if($page>100){thrownewException('超过最大页数');}

四、避坑指南

陷阱破局方案
盲目使用OFFSET深度分页必用游标方案
忽略排序字段选择游标字段必须是索引且唯一(如自增 ID)
宽表全字段查询SELECT必要字段,减少回表

五、终极心法

**“LIMIT 不是分页,
而是性能的悬崖——

  • 当你使用 OFFSET
    你在支付线性成本;
  • 当你切换游标
    你在享受常数时间;
  • 当你限制深度
    你在守护系统。

真正的查询优化,
始于对执行计划的敬畏,
成于对细节的精控。”


结语

从今天起:

  1. 深度分页必用游标方案(WHERE id > last_id
  2. EXPLAIN验证执行计划(避免Using filesort
  3. 产品层限制最大页数(如 ≤ 100 页)

因为最好的分页,
不是跳过百万行,
而是精准定位下一程。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 15:52:01

计算机毕业设计之springboot基于springboot的医院后台管理系统

相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低医院的运营人员成本,实现了医院后台的标准化、制度化、程序化的管理,有效地防止了医院后台的随意管理,提高了信息的处理速度和精确度,能够及时、准确地查询…

作者头像 李华
网站建设 2026/6/10 6:37:16

教育论文的“数据炼金术”:书匠策AI如何把数字变成学术黄金

在学术写作的江湖里,数据是论文的“血液”,但如何让冰冷的数据“开口说话”,却让无数研究者头疼。有人困在数据收集的“无米之炊”里,有人被SPSS的代码“加密语言”劝退,还有人对着满屏的数字发呆,不知如何…

作者头像 李华
网站建设 2026/6/10 12:32:09

大模型转型攻略:零基础入门到实战项目全指南

本文是一份大模型领域转型攻略,从明确目标方向到掌握基础知识,再到深入学习Transformer架构、预训练微调等技术,通过实践项目和参与开源社区提升能力,提供学习资源、职业发展建议及常见问题解答,帮助零基础学习者系统进…

作者头像 李华
网站建设 2026/6/10 12:34:21

LangChain 1.0+ LCEL 深度解析:从可选方案到生产级标准的进化

​ 【个人主页:玄同765】 大语言模型(LLM)开发工程师|中国传媒大学数字媒体技术(智能交互与游戏设计) 深耕领域:大语言模型开发 / RAG知识库 / AI Agent落地 / 模型微调 技术栈:Pyth…

作者头像 李华
网站建设 2026/6/10 12:24:18

【三端毕设源码分享】基于springboot+小程序的民宿预订系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/6/10 14:09:21

【三端毕设源码分享】基于springboot+小程序的餐厅点餐系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华