表里数据太多只看前几条?MySQL LIMIT 写法与分页坑

编程狮(w3cschool.cn) 2026-10-15 07:08:32 浏览数 (55)
反馈

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

MySQL LIMIT 分页示意图

你有一张几千行的订单表,页面只想先显示最新的十条,翻页时再看后面。这时候就需要 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 速查手册 可以放在旁边随时翻。

MySQL LIMIT 分页三种场景图

三、方案二: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 查询在千万级数据上也能稳稳命中索引。

延伸学习

想把这块知识系统补齐,可以按这个顺序来:

  1. 先过一遍 MySQL 系统课程,把查询与索引基础铺平;
  2. 想看更多分页写法,翻 MySQL 分页查询三种实现方式;
  3. 想进阶实战,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 时返回顺序依赖存储布局,两次查询结果可能不一致,分页会出现重复或漏数据。

0 人点赞