mysql中LIMIT子句控制返回结果的数量与分页

MySQL中LIMIT N可直接取前N行,如SELECT * FROM orders ORDER BY created_at DESC LIMIT 5;双参数LIMIT offset,row_count用于分页,但offset过大导致全扫描前offset行而性能骤降,推荐游标分页。

MySQL LIMIT 用法:只取前 N 行最简写法

直接写 LIMIT N 就能取前 N 条,比如查最新 5 条订单:

SELECT * FROM orders ORDER BY created_at DESC LIMIT 5;
注意:不加 ORDER BY 时结果顺序不确定,LIMIT 只控制数量,不保证逻辑顺序。

LIMIT offset, row_count:分页必须掌握的双参数形式

跳过前 M 行、取 N 行,语法是 LIMIT offset, row_count。例如第 3 页(每页 10 条)对应:

SELECT * FROM products ORDER BY id LIMIT 20, 10;
这里 20 是偏移量(从 0 开始计数),不是页码。常见错误包括:

  • 把页码直接当 offset(如写成 LIMIT 3, 10
  • offset 过大导致性能骤降(MySQL 需扫描前 offset+row_count 行)
  • 数据实时变动时,用 offset 分页可能漏行或重复(游标分页更稳)

为什么 OFFSET 越大越慢?底层执行逻辑是什么

MySQL 执行 LIMIT 10000, 20 时,并不会跳过前 1 万行再读 20 行,而是会完整扫描并丢弃前 10000 行,再返回后 20 行。这意味着:

  • 全表扫描成本随 offset 线性增长
  • 即使有索引,如果 ORDER BY 字段和 WHERE 条件不能高效定位起始位置,仍要回表或排序
  • 在高并发分页场景下,建议改用基于主键/时间戳的游标分页(如 WHERE id > 12345 ORDER BY id LIMIT 20

MySQL 8.0+ 的 WINDOW 函数能否替代 LIMIT 分页

不能直接替代。窗口函数(如 ROW_NUMBER())可标记行号,但 LIMIT 仍是最终限制输出的最高效方式。例如:

SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn FROM users) t WHERE rn BETWEEN 21 AND 30;
这种写法逻辑上可行,但比原生 LIMIT 20, 10 多一次全集排序和临时表构建,性能更差。仅在需要动态计算“第 N 个排名”等复杂逻辑时才考虑嵌套窗口。