offset越大越慢是事实,因MySQL必须先跳过前offset行再取count行,即使有索引也无法跳过逻辑偏移;排序不稳定时需加主键保证顺序。
MySQL 的 LIMIT offset,count 执行时,**必须先跳过前 offset 行**,再取 count 行。这意味着 SELECT * FROM orders LIMIT 100000,20 实际上要扫描至少 100020 行(甚至更多,取决于索引覆盖情况),而不仅仅是返回最后 20 行。
ORDER BY 字段没走索引或查询字段未被覆盖,MySQL 仍需回表逐行计数跳过LIMIT 0,20)几乎无开销;偏移量到 50 万以上时,响应可能从毫秒级升至秒级LIMIT n 和 LIMIT 0,n 功能完全一样,都表示取前 n 行;但它们在分页上下文中容易引发混淆。
LIMIT 10 → 安全、简洁,适合首页或“取最新 10 条”场景LIMIT 20,10 → 明确表达“跳过 20 行,取 10 行”,是标准分页写法,但 offset 必须是常量,不能是表达式(比如 LIMIT (page-1)*size, size 在 SQL 层直接报错)offset ≥ 0,负数会直接触发 ERROR 1064(例如 LIMIT -1,10 或 LIMIT 5,-1 全部非法)当多行记录在 ORDER BY 字段上值相同时(比如按 created_at 排序,但有几十条同秒插入的订单),MySQL 不保证这些行之间的相对顺序。下一页可能跳过某些行,或重复出现上一页的某几条。
ORDER BY 后追加主键(或唯一非空列),例如 ORDER BY created_at DESC, id DESC
WHERE created_at ),彻底避开 OFFSET
MySQL 支持 LIMIT count OFFSET offset 语法(如 LIMIT 10 OFFSET 20),和 LIMIT 20,10 完全等价,只是参数顺序调换、语义更直白。

OFFSET 后面不能跟负数,也不能是变量或子查询结果,仍是硬编码整数常量SELECT id, title, created_at FROM articles WHERE status = 'published' ORDER BY created_at DESC, id DESC LIMIT 20 OFFSET 40;
分页真正难的从来不是语法,而是 offset 增长后 MySQL 仍坚持“老老实实数数”这个行为——它不会因为你翻到了第 1000 页就自动换策略。