在mysql中实现分页查询主要依靠LIMIT子句,这是mysql内置的分页功能支持,能够满足绝大多数业务场景下的分页需求,无论是简单的列表分页还是复杂查询的分页都可以用对应的语法实现。

mysql分页查询基础语法
mysql的分页查询核心是使用LIMIT关键字,基础语法有两种常见形式,第一种是指定返回的记录数:
-- 查询前10条用户数据 SELECT id, username, age FROM user_table LIMIT 10;
第二种是同时指定偏移量和返回记录数,语法为LIMIT offset, row_count,其中offset表示跳过前面的多少条记录,row_count表示返回多少条记录:
-- 查询第11到20条用户数据,跳过前10条,返回10条 SELECT id, username, age FROM user_table LIMIT 10, 10;
也可以使用LIMIT row_count OFFSET offset的写法,语义更清晰:
-- 和上面的语句效果一致,跳过10条,返回10条 SELECT id, username, age FROM user_table LIMIT 10 OFFSET 10;
常见分页场景实战
普通列表分页
最常见的场景是前端传递页码和每页条数,后端计算偏移量后查询,假设每页显示10条,查询第n页的数据,偏移量计算公式为(n-1)*10:
-- 查询第3页数据,每页10条,偏移量为(3-1)*10=20 SELECT id, username, age FROM user_table ORDER BY id ASC LIMIT 20, 10;
带条件过滤的分页
如果分页查询需要加过滤条件,直接在WHERE子句后添加条件即可,注意如果有排序需求要加ORDER BY,否则分页结果可能不稳定:
-- 查询年龄大于18岁的用户,第2页,每页10条,按注册时间倒序 SELECT id, username, age, register_time FROM user_table WHERE age > 18 ORDER BY register_time DESC LIMIT 10, 10;
关联查询的分页
多表关联的分页查询同样适用LIMIT语法,只需要保证查询的字段和关联逻辑正确即可:
-- 查询用户及其对应的订单信息,第1页,每页10条 SELECT u.id, u.username, o.order_no, o.order_amount FROM user_table u LEFT JOIN order_table o ON u.id = o.user_id ORDER BY u.id ASC LIMIT 0, 10;
大偏移量分页的性能问题与优化
当偏移量很大的时候,比如LIMIT 100000, 10,mysql需要扫描前100010条记录,然后丢弃前100000条,只返回最后10条,性能会明显下降。
优化方案一:使用子查询优化
先通过子查询拿到分页的起始主键id,再关联查询完整数据,减少扫描的行数:
-- 优化前:LIMIT 100000, 10 性能较差 -- 优化后:先查偏移100000对应的id,再查数据 SELECT id, username, age FROM user_table WHERE id >= (SELECT id FROM user_table ORDER BY id ASC LIMIT 100000, 1) ORDER BY id ASC LIMIT 10;
优化方案二:使用游标分页
如果业务场景不需要跳页,只需要上一页下一页的翻页,可以使用游标分页,基于上一页最后一条记录的主键id查询下一页数据:
-- 假设上一页最后一条记录的id是12345,查询下一页10条数据 SELECT id, username, age FROM user_table WHERE id > 12345 ORDER BY id ASC LIMIT 10;
分页查询注意事项
- 分页查询如果有排序需求,一定要加ORDER BY子句,否则mysql返回的记录顺序可能不固定,导致分页结果重复或者遗漏
- 偏移量offset是从0开始计数的,所以第一页的偏移量是0,不是1
- 如果查询的数据量很大,尽量避免使用大偏移量的分页,优先选择子查询或者游标分页的优化方案
- 分页查询的SQL如果频繁执行,可以给排序字段和过滤条件的字段加合适的索引,提升查询性能