mysql分页查询sql语句

探索 2026-10-17 04:02:20 61

MySQL的页查语句分页查询,说穿了就是页查语句LIMIT子句那点事。但真到生产环境里,页查语句坑比想象中多。页查语句

先看最基础的页查语句写法。假设一张user表有十万行数据,页查语句你要每页显示20条,页查语句查第三页:

SELECT * FROM user ORDER BY id LIMIT 40,页查语句 20;

LIMIT后面第一个数字是偏移量,第二个是页查语句返回行数。偏移量=(当前页-1)×每页条数。页查语句这个语法简单到看一眼就会,页查语句可一旦数据量上来,页查语句问题就变得很现实。页查语句

我见过一个后台管理系统,页查语句用户表才五万条记录,页查语句但翻到第1000页时,查询耗时从十几毫秒飙升到三秒多。原因不复杂——MySQL要扫描前19980行,然后丢弃,只返回最后20行。偏移量越大,扫描越多,性能自然崩。

这时候有人会想到加索引。可索引只帮你在排序时快一点,解决不了“扫描并丢弃”这个根本问题。真正有效的办法,是换一种查询思路——延迟关联或者基于游标的分页。

延迟关联的思路很直白:先用覆盖索引找出当前页的主键ID,再回表查完整数据。

SELECT * FROM user INNER JOIN (SELECT id FROM user ORDER BY id LIMIT 40, 20) AS tmp ON user.id = tmp.id;

这段SQL里,子查询只查了id列,走的是覆盖索引,速度极快。拿到20个ID后再去主表取数据,避免了全行扫描。我拿那套五万行的数据测过,同样的翻页深度,耗时从3.2秒降到0.08秒。效果立竿见影。

不过延迟关联也有瓶颈。偏移量变成两百万时,子查询依然要扫描两百万个id才能找到那20个。这时候就得换游标分页了——简单说,不告诉数据库“跳过多少行”,而是告诉它“从哪个位置开始往后取”。

SELECT * FROM user WHERE id > 上次翻页最后一条记录的id ORDER BY id LIMIT 20;

这种方式对用户来说有个变化:页面上的页码跳转做不了了,只能“上一页/下一页”这样翻。但换来的是稳定的查询速度——不管翻多深,都只扫描20行。很多社交App的信息流就是用这个思路,配合Redis缓存上次读取的位置,体验相当顺滑。

还有个小细节容易被忽略:ORDER BY的字段必须是唯一的。如果只按create_time排序,而同一秒内插入了多条数据,分页时会出现重复或漏行。我踩过这个坑——一个订单列表翻页时偶尔出现同一笔订单出现在两页里,排查半天才发现是时间戳重复。解决方式是排序加一个唯一字段兜底:

ORDER BY create_time DESC, id DESC

这样即使时间相同,id也能保证顺序稳定。

最后说个实际体验。LIMIT分页写起来是真方便,适合数据量小、操作频繁的内部系统。但只要是面向用户的产品,数据量过十万,就该认真考虑游标方案。别等线上慢查询报警了才去改——那会儿数据已经堆起来了,迁移成本高得多。

分页SQL没有银弹,核心就一句话:别让数据库干“先找一大堆再扔掉”的蠢事。至于用哪种方案,取决于你的数据量、翻页习惯和索引设计。明白了这点,写出来的分页查询才经得起推敲。

本文地址:http://www.79wt.cn/news/1513f1399835.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

友情链接