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

MySQL ORDER BY 原理与优化

ORDER BY 是 SQL 里最常见的子句之一,但用不好就是性能杀手。这篇说说 ORDER BY 的原理和优化方法。

ORDER BY 的执行原理

-- 简单 ORDER BYSELECT*FROMorderORDERBYcreated_atDESC;

MySQL 处理 ORDER BY 的过程:

  1. 全表扫描:读取所有数据
    1. 排序:内存排序 or 外部排序
    1. 返回结果:排序后的数据
      如果数据量小,MySQL 用内存排序(Filesort);如果数据量大,就要用磁盘排序,性能很差。

Filesort:MySQL 的排序算法

MySQL 用 Filesort 做排序,虽然名字带「file」,但不一定用磁盘——内存够用就在内存排。

两种模式

模式1:全字段排序(ROWID Sort)

-- 只返回排序字段 + 主键EXPLAINSELECTorder_id,created_atFROMorderORDERBYcreated_at;
排序时:order_id, created_at(2个字段) 排序后:按 created_at 排,用主键回表取完整数据

模式2:索引覆盖排序(Index Sort)

-- 如果 ORDER BY 字段有索引,直接用索引CREATEINDEXidx_created_atONorder(created_at);SELECT*FROMorderORDERBYcreated_at;

直接读索引树,有序,不用再排。

什么情况下用索引排序?

-- ✅ 能用索引排序ORDERBYcreated_at-- 有索引ORDERBYuser_id,created_at-- 符合最左前缀WHEREuser_id=1ORDERBYcreated_at-- 索引覆盖-- ❌ 不能用索引排序ORDERBYcreated_atDESC,idASC-- DESC/ASC 混用ORDERBYcreated_at,updated_at-- 没有复合索引 (created_at, updated_at)WHEREcreated_at>'2024-01-01'ORDERBYcreated_at-- 范围查询后面的字段

Using filesort:什么时候出现?

EXPLAINSELECT*FROMorderORDERBYcreated_at;

Extra 列出现Using filesort,说明要额外排序。

常见原因

  1. 没有 ORDER BY 的索引
    1. ORDER BY 用了函数
    1. 混用 ASC/DESC
    1. 排序字段不在同一个索引里

优化 ORDER BY

1. 覆盖索引

-- 只需要排序字段 + 主键,建联合索引CREATEINDEXidx_user_id_createdONorder(user_id,created_at);-- 排序语句SELECTid,created_atFROMorderWHEREuser_id=1ORDERBYcreated_atDESC;

2. 分页优化

-- 深分页排序很慢SELECT*FROMorderORDERBYcreated_atDESCLIMIT1000000,10;-- 优化:用主键范围SELECT*FROMorderWHEREid<1000000ORDERBYidDESCLIMIT10;

3. 减少排序数据量

-- ❌ 全表排序SELECT*FROMorderORDERBYcreated_atDESC;-- ✅ 加 WHERE 条件,减少排序范围SELECT*FROMorderWHEREstatus='completed'ORDERBYcreated_atDESC;

4. 避免在 ORDER BY 里用函数

-- ❌ 索引失效ORDERBYYEAR(created_at)-- ✅ 改用范围查询WHEREcreated_at>='2024-01-01'ANDcreated_at<'2025-01-01'ORDERBYcreated_at

实战:EXPLAIN 看排序

EXPLAINSELECT*FROMorderORDERBYcreated_atDESC;-- type: ALL(全表扫描)-- key: NULL(没走索引)-- Extra: Using filesort(需要排序)

优化后

CREATEINDEXidx_created_atONorder(created_atDESC);EXPLAINSELECT*FROMorderORDERBYcreated_atDESC;-- type: index(扫索引树)-- key: idx_created_at(走了索引)-- Extra: Using index(索引覆盖,不需要回表!)

小结

优化方法效果
覆盖索引⭐⭐⭐⭐⭐ 最优
加 WHERE 条件⭐⭐⭐⭐
避免函数⭐⭐⭐
避免混用 ASC/DESC⭐⭐⭐
分页用主键范围⭐⭐⭐⭐

ORDER BY 优化的核心:让 ORDER BY 字段有索引让查询走索引而不是 filesort


相关阅读:

  • [MySQL 索引底层 B+ 树原理]
    • [MySQL 索引失效的七种情况]
    • [MySQL 分页查询优化]
http://www.jsqmd.com/news/831262/

相关文章:

  • Open3D点云配准实战:registration_icp核心参数详解与调优
  • 基于ChatGPT与飞书开放平台构建企业级智能聊天机器人实践指南
  • Pearcleaner深度解析:如何构建macOS应用残留清理的专业级架构?
  • 在Unity中实现四旋翼飞行器的串级PID姿态控制
  • 2026上海浦东装修公司口碑排行榜(实测版直接选)別墅装修,办公室装修、新房装修、软装、工装 佘山大宅板块 - 品牌智鉴榜
  • 为什么你需要Markdown Viewer:浏览器中预览Markdown文件的终极解决方案
  • 手工打造柔性LED眼罩:从SMD焊接入门到可穿戴电路实践
  • 利用NXP ROM Bootloader为i.MX RT10xx安装TinyUF2引导程序
  • ​​​​CCF编程培训师资认证(PTA)真题解析
  • 3步掌握ADB驱动安装:Windows平台最简Android连接方案
  • 魔兽争霸3终极增强插件WarcraftHelper:让经典游戏焕发新生的完整指南
  • 从巨头并购看FPGA技术演进与国产破局之路
  • 航空发电机综合测试系统设计【附代码】
  • 组队作业
  • Windows Cleaner终极方案:5分钟告别C盘爆红,系统性能飙升200%
  • AUTOSAR网络唤醒时序详解:为什么你的首帧应用报文会唤醒失败?
  • 用Python从零搭建一个简易的自动驾驶小车仿真器(基于单车运动学模型)
  • Cursor Free VIP终极指南:如何一键突破AI编程助手使用限制
  • FreeRTOS信号量实战:从同步到互斥的嵌入式设计模式
  • Cadence Allegro铺铜实战:从动态避让到静态优化,我的多层板效率提升心得
  • 终极Photoshop图层批量导出指南:如何用免费脚本提升10倍工作效率
  • 嵌入式音乐创作:基于CircuitPython的交互式音频系统设计与实现
  • 从LED驱动到Arduino编程:电子入门实战指南与避坑技巧
  • 我的嵌入式项目踩坑记:用STM32的输入捕获功能给自制旋转编码器“把脉”
  • 当你的Android手机频繁闪退时,系统在后台悄悄做了什么?—— 深入Rescue Party机制
  • 2026京东E卡回收亲测:5个标准筛出最靠谱省心的平台:鼎鼎收 - 鼎鼎收礼品卡回收
  • J公司S车间布局优化【附代码】
  • KLOGG:专业开发者的海量日志分析利器
  • ElevenLabs尼泊尔文语音生成失效?5步快速诊断法:检测梵文字母连写(ligature)、声调标记缺失与音节切分异常
  • 【ElevenLabs阿拉伯文语音实战指南】:20年AI语音工程师亲授7大本地化陷阱与3步高保真合成法