MySQL大表分页越查越慢,优化方案
时间:2026-10-9 07:27 作者:emer 分类: 无
数据量小的时候分页很快,一旦表数据上百万条,翻到后面的页就慢得要死?这是MySQL分页最常见的问题,下面说几个实用的优化方案。
1. 先看为什么会慢
SELECT * FROM 表名 ORDER BY id LIMIT 100000, 10;
这个SQL的意思是:扫描前100010条,丢掉前100000条,返回后10条。
数据量越大,扫描的行数越多,就越慢。这就是为什么越往后翻越慢。
2. 方案一:子查询优化(最常用)
SELECT * FROM 表名
WHERE id >= (SELECT id FROM 表名 ORDER BY id LIMIT 100000, 1)
LIMIT 10;
原理:
- 子查询先通过索引找到第100001条的id
- 然后直接从这个id开始往后查
- 不需要扫描前10万条
速度对比:
- 原SQL:扫描10万+行,耗时几秒
- 优化后:走索引,几毫秒就出来
3. 方案二:游标分页(推荐用在后台)
-- 第一页
SELECT * FROM 表名 ORDER BY id LIMIT 10;
-- 第二页(记住上一页最后一条的id)
SELECT * FROM 表名 WHERE id > 100 ORDER BY id LIMIT 10;
-- 第三页
SELECT * FROM 表名 WHERE id > 110 ORDER BY id LIMIT 10;
优点:
- 永远都是走索引,不管翻到第几页都一样快
- 适合无限滚动加载
缺点:
- 不能直接跳到第100页
- 不适合传统的"上一页/下一页"翻页
4. 方案三:延迟关联
SELECT t.* FROM 表名 t
INNER JOIN (
SELECT id FROM 表名 ORDER BY id LIMIT 100000, 10
) tmp ON t.id = tmp.id;
原理:
- 先通过索引查出需要的10个id
- 再用这10个id去关联原表查完整数据
- 避免回表太多行
5. 方案四:限制最大翻页深度
如果不是必须让用户翻到很后面,可以直接限制:
-- 最多只允许翻100页(1000条数据)
IF 页码 > 100 THEN
-- 提示用户"请搜索更精确的条件"
END IF;
一般用户也不会翻到很后面的页,限制一下性能就好很多。
6. 方案五:用ES做搜索
如果是文章、商品之类的内容,直接用Elasticsearch做全文搜索和分页,MySQL只存原始数据。
ES天生适合做大数据量的分页搜索,MySQL不是干这个的。
常见坑
坑1:ORDER BY 字段没加索引
ORDER BY 的字段一定要加索引,不然不管怎么优化都是全表扫描。
坑2:OFFSET 太大了
OFFSET 100万,不管怎么优化都慢,直接用游标分页。
*坑3:SELECT 不要用**
只查需要的字段,减少回表数据量。
遇到问题加QQ23979811 协助处理