17370845950

mysql order by一定会用索引吗_mysql排序优化解析
MySQL的ORDER BY不一定用索引,仅当排序字段是同一联合索引的最左前缀连续部分且未被WHERE截断时才避免filesort;EXPLAIN中无Using filesort且key显示索引即表示走索引排序。

No,MySQL 的 ORDER BY 不一定会用索引 —— 它只在满足特定结构约束时才跳过 filesort,直接利用索引顺序返回结果。

什么时候 ORDER BY 能走索引?

核心就一条:排序字段必须是**同一个联合索引的最左前缀连续部分**,且该索引未被 WHERE 条件“截断”。

  • 表有索引 INDEX idx_name_age_pos (name, age, position)
  • SELECT * FROM users WHERE name = 'Ali

    ce' ORDER BY age
    ✅ 走索引(name 用于过滤,age 是紧接其后的排序字段)
  • SELECT * FROM users WHERE age = 25 ORDER BY name ❌ 不走索引(age 不是最左字段,无法定位 B+ 树起点)
  • SELECT * FROM users WHERE name = 'Alice' ORDER BY position ❌ 大概率 Using filesort(跳过了 age,破坏最左连续性)

EXPLAIN 中怎么一眼识别是否用了索引排序?

Extra 列:

  • 出现 Using filesort → MySQL 额外做了排序,没用上索引顺序
  • 没有 Using filesort,且 key 显示用了某个索引 → 排序由索引天然有序性完成
  • 额外提示:Using index 表示覆盖索引(不用回表),但和排序无关;它可能和排序共存,也可能不共存
EXPLAIN SELECT name, age FROM users WHERE name LIKE 'A%' ORDER BY age;

如果 keyidx_name_age_posExtra 是空(或只有 Using index),说明排序已由索引保障。

为什么加了单列索引,ORDER BY 还是 filesort

常见误解:给 ORDER BY 字段单独建索引就万事大吉。错 —— 单列索引只对「纯排序无条件」或「仅按该字段 WHERE」有效。

  • SELECT * FROM orders ORDER BY created_at DESC; → 单列索引 INDEX(created_at) ✅ 可用
  • SELECT * FROM orders WHERE user_id = 123 ORDER BY created_at DESC; → 单列 created_at 索引 ❌ 几乎一定 filesortuser_id 没索引,先全表扫描再排序)
  • 正确做法:建联合索引 INDEX(user_id, created_at),让过滤 + 排序共用一棵 B+ 树

升序/降序混合、多字段排序的坑

InnoDB 的 B+ 树索引默认按升序存储;若 ORDER BY a ASC, b DESC,而索引是 (a, b),则 b DESC 无法利用索引顺序(MySQL 8.0+ 支持降序索引定义,但老版本不行)。

  • MySQL 5.7 及更早:所有字段必须同向(都 ASC 或都 DESC)才可能走索引
  • MySQL 8.0+:可建 INDEX(a ASC, b DESC),但需显式声明,且优化器不一定选它
  • 避免写 ORDER BY id DESC LIMIT 20 却只在 id 上建了升序索引 —— 仍可能触发 filesort(尤其当 id 不是主键或聚簇顺序不匹配时)

真正决定是否用索引的,从来不是“有没有索引”,而是“查询条件 + 排序字段”能否对齐同一棵 B+ 树的遍历路径。哪怕索引存在,只要中间缺一环(比如 WHERE 断在中间、方向不一致、字段不在同一索引里),MySQL 就只能老老实实开 sort_bufferfilesort —— 这个细节,线上慢查里藏得最多。