在 MySQL 里只取前几条、或者做分页,靠的是 LIMIT:单参数表示「取前 N 条」,配合 OFFSET 表示「跳过前面若干条再取」。本文先把写法讲清,再把深分页的性能坑一次说透。

你有一张几千行的订单表,页面只想先显示最新的十条,翻页时再看后面。这时候就需要 LIMIT 分页。写错最常见的后果有两种:要么取多了把数据库拖慢,要么翻到第 100 页时查询突然变卡。今天这篇文章,编程狮就把 MySQL 的 LIMIT 与 OFFSET 讲透。
一、先搞懂 LIMIT 的两种写法
LIMIT 最简单的形式是只跟一个数字:LIMIT 10 表示「从头取 10 条」。要分页,就加 OFFSET:LIMIT 10 OFFSET 20 表示「跳过前 20 条,再取 10 条」,也就是第 3 页(每页 10 条)。
一个容易忽略的点:LIMIT 自己不保证顺序。同样一句 LIMIT 5,今天查和明天查可能返回不同的 5 行,因为底层存储顺序会随写入、删除、重建表而变化。所以「取前几条」永远要和 ORDER BY 配对,把「前」定义清楚,否则分页就失去了意义。
⚠️ 注意:OFFSET 的数值越大,数据库要「数过」的行就越多。它并不是直接跳到第 N 行,而是先读完前面所有行再丢弃,深分页会明显变慢。
如果还没装好环境或想复习语法,可以先过一遍 MySQL 教程,把查询基础过一遍。
二、方案一:取前 N 条,最常用
只看最新或最相关的几条,直接 ORDER BY 加 LIMIT 即可。顺序一定要先定好,否则「前 N 条」每次结果可能不同。
SELECT id, title, created_at
FROM orders
ORDER BY created_at DESC
LIMIT 5;
上面这段做了什么:先按创建时间倒序排,再取最前面的 5 条。执行后你应该看到最新的 5 个订单。没有 ORDER BY 时数据库按存储顺序返回,排序不稳定,生产环境务必带上。
如果你用的是带参数的查询(比如 LIMIT ?),占位符只接受非负整数,传字符串或 NULL 会直接报错,这也是为什么偏移量要先在代码里算好、校验好再传入,别直接把前端参数拼进 SQL。
常用语法记不住的话,MySQL 速查手册 可以放在旁边随时翻。

三、方案二:LIMIT 与 OFFSET 做标准分页
分页的核心公式是:LIMIT 每页条数 OFFSET (页码-1)*每页条数。比如每页 10 条、看第 3 页:
SELECT id, title
FROM orders
ORDER BY id ASC
LIMIT 10 OFFSET 20;
同样的语义,MySQL 也支持更紧凑的 LIMIT 20, 10(逗号前是偏移量,逗号后是条数),但可读性差,团队里容易看错前后顺序,建议统一写 LIMIT 10 OFFSET 20。想了解新版差异可以看 MySQL8 教程,窗口函数等特性在 8.0 之后更完整。
在应用代码里算偏移量时,记得做边界处理:页码最小是 1,所以 OFFSET 至少要是 0;如果前端传了负数或超大页码,要先 clamp 再拼 SQL,避免查出空页或把数据库拖垮。ORM 框架(如 MyBatis、SQLAlchemy)通常提供 page / limit / offset 参数,本质上还是会翻译成同一句 LIMIT ... OFFSET ...,理解底层写法才能调好性能。
四、方案三:深分页用「游标/键集」代替 OFFSET
当 OFFSET 到了几万,查询会越来越慢。更好的做法是记住上一页最后一条的 id,下一页只取「id 比它大」的记录,这就是键集分页。
SELECT id, title
FROM orders
WHERE id > 上次最后id
ORDER BY id ASC
LIMIT 10;
假设上一页最后一条的 id 是 1000,下一页就写:
SELECT id, title
FROM orders
WHERE id > 1000
ORDER BY id ASC
LIMIT 10;
数据库用主键索引直接定位到 id > 1000 的第一条,再顺取 10 条,无论翻到第几页耗时都基本恒定。代价是「不能随机跳到第 N 页」,更适合无限滚动这类「一页接一页」的交互;如果产品必须支持「跳到第 50 页」,还是得回到 OFFSET,只是要对深分页做缓存或限制最大页数。
| 方式 | 写法 | 适合场景 | 深分页表现 |
|---|---|---|---|
| 取前 N 条 | LIMIT 5 |
最新几条、排行榜 | 很快 |
| OFFSET 分页 | LIMIT 10 OFFSET 20 |
前几页、小表 | 越深越慢 |
| 键集分页 | WHERE id > ? LIMIT 10 |
无限滚动、大数据 | 稳定 |
键集分页依赖一个有序且唯一的列(通常是主键),它能利用索引直接定位,跳过了「数过前面所有行」这一步。对 MySQL 通义灵码教程 这类实战场景,深翻页基本都该换成这种方式。
五、踩坑清单
三个最常翻车的地方,每个给现象、原因和办法。
- 现象:翻到第 50 页突然变卡。原因:OFFSET 太大,数据库扫描并丢弃了大量行。解决:改用键集分页,用上一页末值做条件。
- 现象:同一句 LIMIT 两次查出来顺序不一样。原因:少了
ORDER BY,返回顺序由存储决定。解决:分页查询必须带稳定排序。 - 现象:逗号写法
LIMIT 20,10取到的不是想要的页。原因:把偏移量和条数顺序搞反了。解决:改用LIMIT 条数 OFFSET 偏移的清晰写法。 - 现象:分页器显示「共 1000 页」但点进去很多页是空的。原因:用
COUNT(*)算总数时没带和列表相同的WHERE条件,或数据在翻页期间被删。解决:总数查询和分页查询用同一套过滤条件,并对深页码做上限保护。
验证最直接:在一张已知数据上,分别跑 LIMIT 5 和 LIMIT 5 OFFSET 5,确认第二批正好是前一批之后的 5 条、且不与前面重叠。预期结果(未在本机执行)是两段互不相交、合起来覆盖前 10 条。
实际 运行 时,先 配置 好排序字段的索引,再 检查 执行计划有没有走索引;如果深翻页 失败 地变慢,就改用键集分页。这个写法更 适用 于按 id 顺序翻页、且数据量大的场景。
总结
MySQL 的 LIMIT 分页,简单取前 N 条用 LIMIT n,标准翻页用 LIMIT n OFFSET m,深翻页要换成「键集分页」用条件过滤代替大 OFFSET。关键是始终带上稳定的 ORDER BY,否则分页结果不可靠。
要点带走:
- LIMIT 单参数是取前 N 条,加 OFFSET 才分页;
- OFFSET 越深越慢,大数据量改键集分页;
- 分页查询必须带 ORDER BY,顺序才稳定。
下一步可以看看索引怎么配合排序,让 LIMIT 查询在千万级数据上也能稳稳命中索引。
延伸学习
想把这块知识系统补齐,可以按这个顺序来:
- 先过一遍 MySQL 系统课程,把查询与索引基础铺平;
- 想看更多分页写法,翻 MySQL 分页查询三种实现方式;
- 想进阶实战,MySQL 进阶实战课程 适合边学边练。
常见问题
Q:LIMIT 5 OFFSET 10 和 LIMIT 10 OFFSET 5 一样吗?
A:不一样。前者是跳过 10 条取 5 条,后者是跳过 5 条取 10 条。OFFSET 决定跳过多少,LIMIT 决定取多少,顺序写错页码就全乱了。
Q:为什么翻页越往后越慢?
A:OFFSET 越大,数据库要先扫描并丢弃前面所有行。它不是真正「跳过去」,而是数过再扔,所以深分页会明显变慢,应该用键集分页规避。
Q:分页一定要加 ORDER BY 吗?
A:生产环境一定要。没有 ORDER BY 时返回顺序依赖存储布局,两次查询结果可能不一致,分页会出现重复或漏数据。

TRAE-AI编程



