在不使用索引的情况下查询一个字段的最大值强烈建议使用 MAX()绝对不要使用 ORDER BY … LIMIT 1。这两种方式在有无索引时的执行效率差异巨大尤其在数据量稍大时如几十万行以上性能差距会是几十倍甚至上百倍。下面是详细的原因分析和执行原理对比。核心结论速览场景 使用 MAX() 使用 ORDER BY … LIMIT 1有索引 极快直接取索引最后一页 极快直接取索引最后一页无索引小表 快全表扫描内存比较 较慢全表扫描 文件排序无索引大表 快全表扫描内存比较 非常慢全表扫描 磁盘文件排序原因详解MAX() 的执行逻辑无索引时过程MySQL会对该字段所在的整个表进行一次全表扫描。在扫描过程中内存里只保留当前遇到的最大值。扫描完所有行后直接返回结果。复杂度时间复杂度为 O(N)其中N是表的行数。资源消耗仅需要很少的内存一个暂存变量不需要使用临时表更不需要磁盘文件排序。I/O 操作是顺序读取数据页。ORDER BY … LIMIT 1 的执行逻辑无索引时过程为了找出最大值并返回第一行MySQL必须对所有行进行排序。由于没有索引MySQL会自己执行一个 filesort文件排序操作。filesort的步骤根据 sort_buffer_size 的大小尝试在内存中进行排序。如果内存不够会将数据分成多个块排序后写入临时文件磁盘。最后将这些临时文件合并成一个有序的结果集。完成后再返回第一条记录。复杂度时间复杂度为 O(N log N)因为需要完整排序。资源消耗大量内存sort_buffer可能大量磁盘I/O临时文件读写这是性能最大的杀手。额外的CPU时间用于比较和排序。一个直观的比喻MAX()就像你在一个大操场上找最高的同学。你只需走一圈每次看到一个更高的就记住他的身高。走完一圈你就知道答案了。ORDER BY … LIMIT 1就像在同个操场上找最高的同学但你的做法是让全体同学从低到高排队。等大家排好队你再让排在第一位的同学出列。仅仅是找一个人却让所有人参与了排序这显然非常低效。实际测试验证简单概念你可以用一个有50万行、无索引的表做测试执行下面两个SQL并观察耗时例如使用 SET profiling1;SQL 1 推荐sqlSELECT MAX(age) FROM employees;SQL 2 避免sqlSELECT age FROM employees ORDER BY age DESC LIMIT 1;你会看到 SQL 2 的 Duration / Fetch 时间会远大于 SQL 1。特别提醒只有一种情况例外当你不仅需要最大值还需要该最大值所在行的其他字段时例如找出年龄最大的员工的完整信息姓名、部门、年龄这时 MAX() 只能返回年龄无能为力。你需要方案A如果只有这一个需求且表不大或可接受偶尔慢sqlSELECT * FROM employees ORDER BY age DESC LIMIT 1;注意无索引时依然很慢只适合一次性查询。方案B最优但需要建索引sql– 先建索引ALTER TABLE employees ADD INDEX (age);– 再查询SELECT * FROM employees ORDER BY age DESC LIMIT 1;总结与最终建议只要目的仅仅是获取某个字段的最大/最小值即使在无索引的表上也毫不犹豫地使用 MAX() 或 MIN()。永远不要为了取最大/最小值在无索引的字段上使用 ORDER BY … LIMIT 1。这是一种非常糟糕的性能习惯随着数据量增长查询可能会从毫秒级变成分钟级。如果需要同时获取最大值对应的其他字段且此查询是高频操作唯一的正确做法是给该字段创建索引。没有索引MySQL 无法避免排序性能必然很差。