MySQL 超大分页优化

📅 2026/7/6 14:23:43
MySQL 超大分页优化
一、超大分页为什么慢InnoDB 索引是 B 树结构执行limit offset, N时数据库执行逻辑数据库需要从头扫描到 offset 条数据跳过前面 100 万行再取后面 20 条如果是普通二级索引还会触发大量回表操作IO 开销成倍增加offset 越大扫描、回表行数越多磁盘 IO、CPU 消耗越高查询耗时指数上涨。举个例子limit 1000000,20MySQL 会读取 1000020 行数据丢弃前 100 万行只返回 20 行大量无效扫描是性能瓶颈。二、方案 1索引覆盖 主键分页最常用数据库层面优化核心思路利用主键有序、索引有序特性先通过索引快速定位分页起始主键再用主键做条件过滤避免扫描丢弃大量数据。1基础写法id 自增主键有序差的写法select * from t_order limit 1000000,20;优化写法-- 先查出第1000000条数据的主键id select id from t_order order by id limit 1000000,1; -- 再用id过滤直接定位起始位置无需扫描前面百万条 select * from t_order where id 查到的id limit 20;2适配前端分页逻辑游标分页替代传统页码分页不给前端传 pageNum、pageSize改为传上一页最后一条数据的主键 ID游标下一页直接where id lastId limit 20。优势无论翻到多少页查询速度稳定无性能衰减限制不支持跳页比如直接跳第 1000 页适合商品列表、订单下拉滚动加载场景。补充非自增、带排序条件场景如果分页需要按创建时间排序给create_time,id建立联合覆盖索引-- 先定位游标 select id from t where order by create_time desc,id desc limit 1000000,1; -- 分页查询 select * from t where create_time 上一页最后时间 or (create_time同时间 and id lastId) order by create_time desc,id desc limit 20;关键前提建立覆盖索引只查 id 时走覆盖索引不用回表定位 offset 的语句速度会大幅提升。三、方案 2延迟关联优化需要 select * 全字段查询场景场景业务必须返回完整字段又要支持跳页游标分页无法使用。 原理先通过覆盖索引快速分页拿到主键再关联原表拿完整数据减少回表次数。-- 差SQL select * from t_order order by id limit 1000000,20; -- 延迟关联优化 select t.* from t_order t inner join (select id from t_order order by id limit 1000000,20) temp on t.id temp.id;逻辑子查询只走索引拿 id没有回表扫描成本低再通过主键精准匹配 20 条完整数据相比直接 limit 百万偏移量性能提升数倍。四、方案 3业务层面限制从源头避免超大分页最优方案数据库优化终究有上限从产品逻辑规避超大分页是线上首选方案前端禁止跳大页码只支持上一页、下一页滚动加载不提供输入页码跳转 1000 页功能直接从根源杜绝limit 100w,20限制最大页码后台限制最多查询前 1000 页超过后提示用户缩小筛选条件增加筛选条件缩小数据集强制用户传入时间范围、状态、商户 ID 等过滤条件通过 where 条件先过滤数据总量offset 自然变小五、方案 4归档分表数据量千万级以上终极方案单表数据几千万、上亿即使优化 limit查询依然缓慢按时间分表订单按月分表查询第几月数据只查对应分表单表数据量可控冷热数据归档把半年前历史订单迁移到归档表线上业务只查近半年热数据分区表MySQL 分区逻辑单表、物理分文件减少单次扫描数据范围。六、方案 5大数据量检索走中间件搜索类场景商品、内容、日志这类需要复杂筛选、超大分页、模糊搜索场景直接放弃 MySQL 分页 使用 ElasticsearchES 基于倒排索引深度分页提供 scroll 游标、search_after海量数据分页性能远优于 MySQLMySQL 只存基础业务数据检索分页交给搜索引擎。七、避坑补充超大分页不要使用order by无索引会触发文件排序 filesort性能雪崩分页排序字段必须建立联合索引不要用offset 0,1000000做统计分页总数count(*)全表扫描耗时高前端可做近似总数缓存普通索引超大分页回表成本极高优先使用覆盖索引减少 IO游标分页无法跳页如果产品强需求跳大页码只能用延迟关联临时兜底长期还是改造产品逻辑。简短总结超大 limit 分页慢的核心是 MySQL 会扫描并丢弃 offset 行数据优化分四层数据库层游标分页id 游标、延迟关联、建立覆盖索引业务层限制大页码、增加筛选条件从源头避免深分页存储层冷热归档、分表分区降低单表数据量检索场景ES 替代 MySQL 做海量数据分页 生产环境优先改造产品使用游标滚动分页性能最稳定。