当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL ORDER BY LIMIT 为什么有时不走过滤索引:排序索引、filesort 和核对方法

MySQL ORDER BY LIMIT 为什么有时不走过滤索引:排序索引、filesort 和核对方法

来源:17golang原创 2026-07-17 17:32:38 0浏览 收藏

订单列表只显示最近 20 条,接口却在高峰时偶尔变慢。EXPLAIN 里还出现了一个反直觉的现象:表上明明有按状态建的索引,优化器却选择按主键顺序读取,再边读边过滤。很多人看到这里就想强制索引,结果把一次局部波动改成了长期负担。先把问题拆开:这条 SQL 同时在争取更少的过滤行和更快的排序输出,LIMIT 会改变两者的成本权重。

实践要点

  • ORDER BY ... LIMIT 不能只看 WHERE 条件;排序索引与过滤索引可能给出不同的低成本路径。
  • 复合索引应围绕真实的等值条件和稳定排序字段设计,别为了一个列表页堆一串无用列。
  • EXPLAIN 用来读候选路径,受控的 EXPLAIN ANALYZE 才能看到实际读行和耗时;两者都要结合数据分布判断。

LIMIT 20 让“先过滤”与“先排序”发生竞争

看一个常见订单页:用户只看已支付订单,并要求按订单号倒序返回 20 条。过滤索引可以快速定位 status = 'PAID' 的范围,但若它无法同时满足 ORDER BY id DESC,服务器还要再排一次序。另一条路是沿着主键倒序读取,遇到已支付记录就收下,够 20 条就停;如果最近订单大多已支付,这条路可能更省。

反过来,若已支付记录在最近订单中很稀疏,按主键一路回扫会读过很多不匹配行,过滤索引加排序反而可能更合适。MySQL 官方文档说明,带 LIMIT 的排序查询会影响索引选择;可用有序索引时很快,若必须 filesort,则要先选出并排序匹配行。这里别急着给某一种路径贴“永远更快”的标签。

MySQL ORDER BY LIMIT 的原创工程证据截图,以低饱和执行计划对照展示排序索引边读边筛选与过滤索引后 filesort 的两条路径

先用 EXPLAIN 看清它准备怎样读取

先把线上真实条件缩成可复现的查询,再看 keyrowsExtra。下面的 SQL 只作为示意,订单状态、时间窗口和排序字段应替换成自己的业务条件。

EXPLAIN
SELECT id, status, created_at
FROM orders
WHERE status = 'PAID'
ORDER BY id DESC
LIMIT 20;
  • key 表示本次路径选择的索引,不等于“表上最好的索引”。
  • rows 是优化器预计要检查的行数;对 InnoDB 来说它是估算值,不能把它当成精确计数。
  • Extra 出现 Using filesort 说明排序没有直接由当前读取顺序解决,但它本身不是判定慢查询的结论。

把两条候选 SQL 的 keyrows、返回行数和响应时延放在一起看,才能知道瓶颈是筛选稀疏、排序量过大,还是回表读取的字段太宽。只盯着一个 Using filesort,很容易把原本读取很少的数据路径误判掉。

复合索引要同时服务筛选与稳定排序

如果产品定义是“某状态下按创建时间倒序,订单号做同时间的稳定次序”,索引和 SQL 的排序表达就应该一致。等值过滤列通常放在前面,随后才是排序列;把唯一的 id 放进排序,可以避免同一时间值下翻页顺序漂移。

CREATE INDEX idx_orders_status_created_id
ON orders (status, created_at, id);

SELECT id, created_at
FROM orders
WHERE status = 'PAID'
ORDER BY created_at DESC, id DESC
LIMIT 20;

这不是要求每个列表页都新增索引。它是一个待核对的候选结构:先确认 WHERE 与 ORDER BY 是否真是这个组合,再看写入成本、索引体积和已有索引能否复用。MySQL 官方文档也提醒,索引不是越多越好;每个额外索引都会占用空间,并增加插入、更新和删除的维护成本。

上面的查询只取 idcreated_at。若结果所需字段都在同一个索引里,就有机会作为覆盖索引读取,减少回到表数据页的需要。把 SELECT * 原样搬进来通常就失去这个条件,因此应先确认列表页真正渲染了哪些字段。

MySQL 复合索引与稳定排序的原创工程证据截图,低饱和查询窗口展示 status、created_at、id 对齐后由索引返回少量列表字段的核对结果

两个反例比“加索引”更值得先看

第一个反例是排序方向或列顺序和索引不一致。例如业务按 created_at DESC, id ASC 排序,索引却按另一种方向与顺序建立;不能凭肉眼认定它一定能复用排序。第二个反例是过滤条件本身范围很宽,或者一次查询需要取大量不在索引中的字段。此时即使索引名称看起来匹配,回表和读取量也可能抵消优势。

还有一种常见误区是只为一个低频后台页面加很宽的覆盖索引。读侧少了一点回表,写侧却让每次状态更新都多维护一份大索引。架构上的取舍不在“覆盖索引好不好”,而在这个读取模式是否足够高频、字段是否足够稳定、写入成本是否能接受。

把 prefer_ordering_index 当成对比开关,不当成长期答案

MySQL 针对带 ORDER BYLIMIT 的查询会偏向考虑有序索引。官方文档提供了 prefer_ordering_index 开关,便于比较另一条候选路径。更稳妥的做法是在隔离的会话或测试环境里做一次对比,不要直接把全局默认改掉。

SET SESSION optimizer_switch = 'prefer_ordering_index=off';

EXPLAIN
SELECT id, status, created_at
FROM orders
WHERE status = 'PAID'
ORDER BY id DESC
LIMIT 20;

这一步的价值是帮助理解“排序优先”和“过滤优先”各自会选什么,不是替业务定结论。需要实际度量时,EXPLAIN ANALYZE 会真正运行 SELECT 并报告测量数据,应该只对受控查询使用,避免把昂贵的生产读请求额外再跑一遍。

上线前按这张表收口

核对点应看到的结果异常时优先检查
排序稳定性ORDER BY 包含能打破并列的列同时间值或同状态值下是否有跳页、重复
索引形状等值条件与排序列和业务 SQL 对齐列顺序、方向、范围条件与现有索引
读取量实际检查行数与返回 20 行的目标相称过滤稀疏度、filesort、回表字段
写入代价新增索引没有明显拉高写入延迟索引宽度、更新频率、重复索引

相关问题

Using filesort 一出现就必须优化吗?

不一定。它说明当前排序没有直接按索引顺序完成,但还要看匹配行数、排序量和实际时延。少量数据上的 filesort 可能比沿着不合适的排序索引扫很多行更省。

为什么 ORDER BY 要加 id?

当主要排序列存在相同值时,加唯一列可以让返回顺序稳定。MySQL 文档也指出,只按非唯一排序列配合 LIMIT 时,并列行的相对次序不保证固定。

覆盖索引是不是越宽越好?

不是。只有高频读取确实需要的少量字段才值得考虑放进索引;宽索引会占空间,也会增加写入维护成本。

能直接在生产请求上跑 EXPLAIN ANALYZE 吗?

要谨慎。它会运行 SELECT 并收集测量结果。先在可控副本、低风险时间窗或等价测试数据上确认读取量,再决定是否需要线上抽样。

核对资料

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
RAG 知识库怎么防提示词注入:外部文档只能当资料,不能当指令RAG 知识库怎么防提示词注入:外部文档只能当资料,不能当指令
上一篇
RAG 知识库怎么防提示词注入:外部文档只能当资料,不能当指令
Java record 怎么防止可变集合从外部改进来:List.copyOf、数组克隆和构造器核对
下一篇
Java record 怎么防止可变集合从外部改进来:List.copyOf、数组克隆和构造器核对
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    43次使用
  • Gradio是什么?Python开源库快速构建机器学习Web演示界面
    Gradio
    Gradio是一个用于构建机器学习和数据科学Web应用的开源Python库。支持快速创建交互界面,获Google、Meta等大厂青睐,适合模型演示、部署反馈及调试。
    44次使用
  • AutoGPT是什么?开源AI Agent自动化工作流平台详解与使用教程
    AutoGPT
    AutoGPT是基于GPT-4的开源AI代理平台,拥有超10万GitHub星标。本文介绍其低代码界面、自动化工作流功能、系统配置要求及安装步骤,助您高效部署和管理AI Agent。
    46次使用
  • 腾讯扣叮官网:青少年编程教育平台,提供图形化编程、3D创作与虚拟仿真实验室
    腾讯扣叮
    腾讯扣叮是腾讯推出的6-18岁青少年编程学习平台,依托游戏与AI技术,提供图形化编程、3D创作、虚拟实验室及丰富赛事课程,助力培养计算思维与创新能力。
    42次使用
  • 堆友AI学习平台介绍:阿里认证课程与AIGC设计实战指南
    堆友AI学习
    堆友AI学习是堆友推出的专业AI设计教育平台,提供从基础到进阶的线上课程及线下实训营。结合阿里国际AITIC认证,通过视频教程、笔记分享和实战案例,帮助设计师掌握AIGC技能,提升职业竞争力。
    44次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码