LIMIT必须放在SELECT语句末尾且严格位于ORDER BY之后;不配ORDER BY会导致结果不可靠,大OFFSET性能极差,分页需用主键补位排序并避免在视图或UPDATE/DELETE中误用。

LIMIT 是唯一标准方式,但写错位置、不配 ORDER BY、滥用大 OFFSET,都会让结果不可靠或查询变慢。
LIMIT 必须放在 SELECT 末尾,且只能在 ORDER BY 之后
MySQL 语法强制要求 LIMIT 是整个查询的最后一个子句。它不是函数,也不是独立语句,不能写成 LIMIT(10)、LIMIT 10 单独一行,更不能插在 WHERE 或 GROUP BY 中间。
- 错误写法:
SELECT * FROM users WHERE id > 10 LIMIT 5 GROUP BY status→ 触发ERROR 1064 - 正确顺序:SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY →
LIMIT - 没
ORDER BY也能用LIMIT,但返回哪几行完全不确定——InnoDB 表在并发写入下,两次执行SELECT * FROM logs LIMIT 5可能返回完全不同记录
分页必须用 ORDER BY + 主键补位,否则会漏数据或重复
只写 ORDER BY price DESC 很危险:多个商品 price 相同,MySQL 排序时物理顺序不固定,导致同一 LIMIT 20, 10 在不同请求中可能跳过某些行或重复返回。
- 安全写法:
ORDER BY price DESC, id DESC—— 用主键兜底,确保排序唯一 - 时间字段分页也一样:
ORDER BY created_at DESC, id DESC,并建联合索引(created_at, id) - 别用
ORDER BY RAND()分页:无法走索引,大表必全表扫描
LIMIT offset, row_count 越大越慢,不是语法问题,是执行逻辑决定的
查第 1000 页(每页 20 条)写成 LIMIT 19980, 20,MySQL 不会“跳”过去,而是先完整扫描、排序所有匹配行,再丢弃前 19980 行。哪怕只取 20 条,也要处理至少 20000 行。
- OFFSET 超过 10000 就该警惕;真实线上场景中,
LIMIT 100000, 20常伴随Using filesort和高延迟 - 优化不是调 LIMIT 参数,而是换策略:记住上一页最后一条的
id,下一页写WHERE id > 54321 ORDER BY id LIMIT 20 - 视图里不能写
LIMIT(会报ERROR 1349),必须在外层加;但视图定义里没ORDER BY,外层加也救不了顺序问题
UPDATE/DELETE 里不能直接用 LIMIT,除非关安全模式或显式加 WHERE
默认开启 Safe Update Mode 时,DELETE FROM logs WHERE created_at 会报 <code>ERROR 1175,这不是语法错误,而是客户端保护机制。
- 临时绕过:
SET SQL_SAFE_UPDATES = 0,但风险自担 - 更稳妥做法:用子查询锁定目标 ID 集合,再删,例如
DELETE FROM logs WHERE id IN (SELECT id FROM (SELECT id FROM logs WHERE created_at -
UPDATE ... ORDER BY ... LIMIT在 InnoDB 下有效,但 MyISAM 行为不一致,不建议跨引擎依赖
真正容易被忽略的,是 LIMIT 的性能代价和排序依赖完全透明——你写对了语法,不代表查询就快;加了索引,也不代表 LIMIT 就能跳过扫描。关键不在怎么写,而在是否理解它背后是“全量排序后截断”,而不是“精准定位”。


















