mysql如何优化分页查询_mysql分页查询性能优化

来源:这里教程网 时间:2026-02-28 20:33:03 作者:

MySQL分页查询性能差,核心问题不在LIMIT本身,而在于OFFSET过大时需扫描大量无用行。优化的关键是避免全表/全索引扫描跳过前N行,改用基于游标的“无状态分页”或覆盖索引+延迟关联。

用主键/唯一索引字段做条件分页(推荐)

替代

LIMIT 10000,20
这类深分页,改用上一页最后一条记录的主键值作为下一页起点:

第一页:
SELECT id,name,created_at FROM user ORDER BY id LIMIT 20
第二页(假设第一页最大id=125):
SELECT id,name,created_at FROM user WHERE id > 125 ORDER BY id LIMIT 20
必须确保ORDER BY字段有索引(最好是主键或唯一索引),且WHERE条件能高效走索引 不支持直接跳转到第100页,但适合“下一页”场景,响应时间稳定在毫秒级

强制走覆盖索引 + 延迟关联

当必须支持任意页码跳转(如后台管理),且排序字段非主键时:

先用覆盖索引查出ID(只查索引,不回表):
SELECT id FROM user ORDER BY created_at DESC LIMIT 10000,20
再用这些ID关联原表取完整数据:
SELECT u.* FROM user u INNER JOIN (SELECT id FROM user ORDER BY created_at DESC LIMIT 10000,20) t ON u.id = t.id
要求ORDER BY字段上有联合索引(如
INDEX idx_created_id (created_at, id)
),让子查询能走索引扫描
避免
SELECT *
直接分页,减少IO和网络传输量

避免常见陷阱

这些写法会彻底失效索引或加剧性能问题:

在ORDER BY字段上使用函数:
ORDER BY UPPER(name)
→ 索引失效
WHERE和ORDER BY跨不同索引字段:
WHERE status=1 ORDER BY created_at
→ 可能触发filesort
未加索引的文本字段分页:
ORDER BY description
→ 全表扫描不可避免
用UUID或随机字符串作主键分页:
ORDER BY uuid
→ 索引物理顺序无意义,分页效率极低

其他实用建议

结合业务场景进一步压降开销:

前端限制最大可查看页码(如只允许查前100页),后端对超出页码返回空或提示 对实时性要求不高的列表,用Elasticsearch或物化视图预计算分页结果 监控慢查询日志,重点抓
Rows_examined
远大于
Rows_sent
的分页SQL
MySQL 8.0+可尝试
WINDOW FUNCTION
配合
ROW_NUMBER()
,但大数据量下仍不如游标方案高效

相关推荐