一说起分页查询,很多人的第一反应就是“加个 LIMIT 呗”。但说实话,我见过太多项目,分页写着写着就卡成狗,尤其是数据量一上来,那个慢啊,简直让人抓狂。今天这篇文章,就是想跟你聊聊 LIMIT 到底怎么用,才能让你的分页查询从“能用”变成“高效”,别让它成为系统里的“卡顿黑洞”。

先搞清楚 LIMIT 的基本语法。在 MySQL、PostgreSQL 等主流关系型数据库里,LIMIT 常见写法是 或者 。比如要查询第 11 到 20 条数据,就写 ,意思是跳过前 10 条,取 10 条。逻辑很简单,但坑就藏在“跳过”这两个字里。数据库要执行这个查询,得先扫描到第 10 条之后,再把后面的 10 条返回。数据量小的时候,比如只有几百条,几乎感觉不到;但一旦表里有几百万行,你要查第 100 万页的数据,就得先扫描 100 万行,再丢掉前面的 99 万 9900 行,只留下 10 行。这相当于翻一本 1000 页的书,每次翻到第 999 页,都得从第一页重新翻起,效率能高吗?
很多人觉得 LIMIT 就是用来分页的,这没错,但它的本质其实是“限制返回行数”。理解这一点很重要。比如做报表统计,只需要前 10 条热门文章,直接 ,数据库找到前 10 条就收工,非常快。但一旦涉及 ,性能就会下降,因为 OFFSET 意味着数据库必须“计算”并“抛弃”前面的行,这个过程无法利用索引优化。所以,分页查询的性能瓶颈往往不在 LIMIT 本身,而在不断增大的 OFFSET。
那怎么优化呢?一个经典思路是“基于游标的分页”,也叫“键集分页”。说白了,就是不用 OFFSET,而是用上一页最后一条记录的唯一字段(比如 ID)作为条件,查询下一页。比如查询文章列表,每页 10 条,上一页最后一条的 ID 是 100,那么下一页的 SQL 可以写成 。这样数据库直接走主键索引,找到 ID 大于 100 的前 10 条,完全不需要扫描前面的数据。不管是第 1 页还是第 100 万页,性能都一样稳定。这招在数据量大、实时性要求高的场景里,简直是神器。
当然,游标分页也有局限。它要求排序字段必须唯一且有序,比如自增 ID、时间戳加唯一索引。如果排序规则特别复杂,如按点赞数、评论数或随机排序,就不能直接用游标。这时可以考虑“延迟关联”或“子查询优化”。比如要查询按更新时间排序的第 100 万页,直接 会很慢。可以先查出一个子集:,这个子查询只返回 ID,走索引很快。然后再用这些 ID 去关联主表:。虽然仍用了 OFFSET,但扫描的数据量从全行变成了只扫索引,性能提升明显。
还有一个容易被忽视的细节:LIMIT 与索引的关系。很多时候,你以为加了 LIMIT 就万事大吉,但优化器可能会“自作聪明”。例如有联合索引 ,查询条件是 ,可以完美利用索引,因为索引已经按 a、b 排序,直接取前 10 条非常快。但如果改成 ,情况就复杂了。IN 条件会导致索引的排序失效,数据库可能需要全表扫描或文件排序,即使有 LIMIT 也救不了。所以写 LIMIT 查询时,一定要查看执行计划,确认是否真的在走索引,别被表面现象骗了。
再聊聊深分页问题。所谓深分页,就是 OFFSET 特别大的情况。比如一个帖子有 100 万条评论,用户要翻到第 10 万页,这时任何基于 OFFSET 的写法都会慢。除了游标分页,还有一种思路是“禁止跳页”。很多产品其实不需要用户精确跳转到第 N 页,例如微博、抖音的“下拉加载更多”,本质就是游标分页。如果必须支持跳页,就要有心理准备:数据量大时,深分页必然慢,这是物理规律。可以在业务上做限制,比如只允许查看前 100 页,或者用缓存把热门页的数据提前加载。
说点实战经验。不要迷信 “LIMIT 1” 就是最快的。有时候你只想查一条数据,但如果没有使用合适的索引,数据库仍然需要全表扫描。比如 ,如果 没有索引,数据库会把所有 的行都找出来,再取第一条。这个“找出来”的过程仍然是遍历全表,LIMIT 1 只影响返回结果,而不减少工作量。因此,LIMIT 的加速效果前提是索引能够快速定位目标行;没有索引,LIMIT 只是一种摆设。
另外,不同数据库对 LIMIT 的实现也有细微差别。MySQL 的 LIMIT 在排序后执行,所以 会先为所有行生成随机数再排序,性能极差。PostgreSQL 的实现相对更智能,但大 OFFSET 同样慢。Oracle 和 SQL Server 使用 ROWNUM 或 TOP,原理类似。所以,掌握 LIMIT 的核心思想比死记硬背语法更重要。
总结一下,数据库 LIMIT 的用法核心可以概括为两句话:小数据量随便用,大数据量别用 OFFSET。能走游标就走游标,走不了就用延迟关联或子查询优化。永远记住,LIMIT 不是银弹,它只是工具,用得好能让你爽,用不好能让你哭。下次写分页查询时,多考虑数据量、索引和业务场景,别让一个简单的 LIMIT 成为系统卡顿的罪魁祸首。掌握这些技巧,你的分页查询才能真正做到高效不卡顿。


