ORDER BY 是唯一可靠的结果集排序方式;MySQL 不保证默认顺序,多字段排序按逗号顺序逐级生效,NULL 默认最小/最大但可覆盖,无索引的 ORDER BY 会触发 filesort 影响性能。

ORDER BY 是唯一可靠的结果集排序方式
MySQL 不保证查询结果的默认顺序——哪怕你刚插入完数据、没删没改,下次 SELECT * 也可能顺序不同。这不是 bug,是存储引擎(如 InnoDB)按聚簇索引物理存放、B+ 树分裂/合并导致的自然现象。想让结果稳定有序,必须显式写 ORDER BY,别依赖“看起来排好了”。
多字段排序:优先级从左到右,相同才往下走
当用多个字段排序时,MySQL 严格按逗号分隔的顺序逐级生效,不是“一起算权重”。比如:
SELECT * FROM orders ORDER BY status DESC, created_at ASC;
它的意思是:
- 先按
status降序排(比如 'shipped' > 'pending' > 'cancelled') - 只有
status完全相同时,才启用created_at升序(比如同为 'pending' 的订单,早创建的在前) - 如果所有
status值都唯一,created_at根本不会参与实际排序
常见错误是以为加了两个字段就“自动智能排序”,结果发现第二字段毫无影响——先检查第一字段是否真有重复值。
NULL 值默认排最前(升序)或最后(降序),但可被覆盖
在 MySQL 中,NULL 被视为“比所有非空值都小”,所以:
-
ORDER BY col ASC→NULL排最前面 -
ORDER BY col DESC→NULL排最后面
但业务中常需统一处理,比如把 NULL 当作“未知”排末尾(无论升序降序)。可用 IS NULL 配合布尔表达式“拉高优先级”:
SELECT * FROM users ORDER BY (age IS NULL) ASC, age ASC;
这行代码强制把非 NULL 的 age 全部排在前面,再按数值升序;NULL 统一落在最后。
排序性能:没索引的 ORDER BY 很可能拖垮查询
如果 ORDER BY 的字段没索引,MySQL 必须在内存或磁盘做 filesort —— 数据量稍大(比如 >10 万行)就会明显变慢,甚至触发 Using temporary; Using filesort 的告警。
- 单字段排序:给该字段建普通索引即可,如
ALTER TABLE t_message ADD INDEX idx_created_at(created_at); - 多字段排序:索引必须**左前缀匹配**排序顺序,例如
ORDER BY a ASC, b DESC,对应索引应为INDEX idx_a_b (a, b);注意:MySQL 8.0+ 支持混合方向索引((a ASC, b DESC)),但 5.7 及更早版本只认全部 ASC 或全部 DESC - 避免在函数或表达式上排序,如
ORDER BY UPPER(name),无法走索引
真正容易被忽略的是:即使加了索引,若 WHERE 条件用了范围查询(如 WHERE time > '2025-01-01'),后续的 ORDER BY 字段大概率也用不上索引——这是 B+ 树索引的天然限制,得靠覆盖索引或重写查询逻辑来绕过。










