order by 默认升序(asc),省略时行为一致;降序必须显式写desc;多字段按从左到右逐级排序;null默认升序排最前;字符串排序依赖校对规则;推荐用字段名或表达式而非位置序号;无索引时触发filesort影响性能。

ORDER BY 默认是升序还是降序?
默认是升序(ASC),但几乎没人写它——因为省略后行为完全一致。写 ORDER BY name 和 ORDER BY name ASC 效果一样。
降序必须显式写 DESC,否则不会倒排。常见错误是以为加个负号或改字段名就能降序,结果查出来还是正序。
-
ORDER BY created_at DESC→ 按时间从新到旧 -
ORDER BY score或ORDER BY score ASC→ 从小到大 - 混用时,
ASC和DESC要分别指定:ORDER BY status ASC, updated_at DESC
多个字段排序的执行顺序和常见陷阱
SQL 按 ORDER BY 后字段从左到右逐级排序:先按第一个字段分组,组内再按第二个字段排,以此类推。不是“同时比较所有字段”。
容易踩的坑是误以为 ORDER BY a, b 等价于 “按 a 和 b 的某种组合值排序”,其实它是两级稳定排序。
- 如果
a值相同,才看b;a不同,b再大也不会排到a小的前面 - NULL 值默认排在最前(升序)或最后(降序),不同数据库略有差异;PostgreSQL 可用
NULLS FIRST/NULLS LAST控制,MySQL 不支持该语法 - 字符串排序依赖字符集和校对规则(collation),比如
utf8mb4_0900_as_cs区分大小写,可能导致 'Z' 排在 'a' 前面
ORDER BY 能用表达式、别名或列位置吗?
可以,但兼容性和可读性差别很大。
表达式(如 ORDER BY LENGTH(name))各数据库基本都支持;列别名在 SELECT 中定义后,多数数据库(PostgreSQL、SQL Server)允许在 ORDER BY 中直接使用,MySQL 8.0+ 也支持;而用数字位置(ORDER BY 2)虽然简洁,但极易出错——只要调整 SELECT 字段顺序,排序就乱了。
- 推荐用字段名或表达式,避免用位置序号
- 别名可用,但要注意:MySQL 5.7 及更早版本不支持在
ORDER BY中使用 SELECT 别名(会报Unknown column错误) - 聚合函数需配合
GROUP BY,否则 MySQL 可能放行但结果不可靠,PostgreSQL 会直接报错
性能问题:ORDER BY 为什么慢?怎么加速?
没索引的 ORDER BY 会触发 filesort —— 数据库把结果集全读出来再内存/磁盘排序,数据量大时非常拖慢查询。
关键不是“有没有 ORDER BY”,而是“能不能走索引”。只有当排序字段有合适索引,且 WHERE 条件能利用该索引的左侧前缀时,才能避免 filesort。
- 例如
WHERE category = ? ORDER BY created_at DESC,适合建联合索引(category, created_at) - 如果写成
WHERE status IN (?, ?) ORDER BY name,多数情况下无法用上name索引排序,因为IN通常导致范围扫描中断索引有序性 -
SELECT *+ORDER BY容易让优化器放弃覆盖索引,尽量只查需要的字段
LIMIT OFFSET)叠加排序时,小数据没问题,一到百万级立刻暴露。











