MySQL 深度分页优化

MySQL 深度分页优化

理解总结:

分页使用limit ,前提是要排序好的数据,这时候,就推荐使用带索引的字段排序,因为索引是天然有序的,不需要像是无序的字段一样,全表扫描,如果太大的话,还filesort ,利用文件排序,排序完成之后,才能分页,很慢。但是,如果分页过深的话,比如limit100万,仍然无需要查询到100万数据,中间有大量的io操作(回表查询其它字段),这时候考虑用上子查询,先查到100万位置的往后10条数据(直接用id主键查,因为没有回表,直接索引查,所以很快),然后再关联10条数据,取得完整的数据。

举例:

1. 没有查询条件,没有排序

耗时0.613s

sql 复制代码
select id,m_id, name, identity_no, address, create_time, modify_time  from t1 limit 1000000, 20;

加上主键排序

耗时0.41

sql 复制代码
**select** id,m_id, name, identity_no, address, create_time, modify_time  **from** t1 **order** **by** id limit 1000000, 20;

加上主键排序,使用了主键索引,天然有序,所以只读取前n条数据,所以更快

2. 带排序-排序字段没有索引

sql 复制代码
select id,m_id, name, identity_no, address, create_time, modify_time 
from t1 
order by create_time desc 
limit 10000, 20;

耗时2秒左右

sql 复制代码
select id,m_id, name, identity_no, address, create_time, modify_time
from t2
order by create_time desc
limit 10000, 20;

与t1基本相同,只是加了索引,耗时0.9s左右

对比:没有索引的表,全表扫描,排序用到filesort 。有索引的话,可以利用索引排序,limit 的话,扫描的数据有少。

3. 排序字段有索引,但是分页很深,从100w开始取20条。

sql 复制代码
select id,m_id, name, identity_no, address, create_time, modify_time 
from t2 
order by create_time desc 
limit 1000000, 20;

很慢,没有走索引,因为MySQL优化器发现这条sql查询超过一定的比例,就会自动转成全表扫描

加force index(idx),强制走索引。有效果,但是不明显。

结论即使有索引,再深一点的分页也会有问题,要避免

5. 解决方案

联表子查询

sql 复制代码
-- 改为:
SELECT   
    id, m_id, NAME, identity_no, address, create_time, modify_time 
FROM t2
JOIN ( SELECT id FROM t2 ORDER BY create_time desc LIMIT 1000000, 20 ) x USING ( id );

变成0.7s;原来15s。

sql 复制代码
-- 在t1执行:
SELECT   
    id, m_id, NAME, identity_no, address, create_time, modify_time 
FROM t1
JOIN ( SELECT id FROM t1 ORDER BY create_time desc LIMIT 1000000, 20 ) x USING ( id );

这个也很快,2.8s。原来18s+

分析

直接通过索引树就能拿到查询字段的值,索引快的原因是,子查询查询的方式,减少了回表查询操作,进而减少了大量的回表IO,因为高效。

参考:https://juejin.cn/post/6985478936683610149

相关推荐
gQ85v10Db21 分钟前
Redis分布式锁进阶第十六篇:番外高阶避坑篇 + 隐性埋点锁故障深挖 + 疑难杂症终极兜底方案
数据库·redis·分布式
S1998_1997111609•X28 分钟前
论恶意注入污染蜜罐进程函数值取仺⺋以集团犯罪获取数据爬虫的轮系依据
网络·数据库·爬虫·网络协议·百度
许彰午30 分钟前
# 从OOM到根治的完整过程——导出大数据的应急、根因分析与游标方案
java·大数据·数据库·系统架构
eLIN TECE44 分钟前
nacos2.3.0 接入pgsql或其他数据库
数据库
曾几何时`1 小时前
MySQL(七)索引
数据库·mysql
KmSH8umpK1 小时前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第九篇
数据库·redis·分布式
悠悠121381 小时前
一条 SQL 从敲下回车,到在 MySQL 里“跑完一生”,中间到底经历了啥?
数据库·sql·mysql
秋92 小时前
MySQL 9.7.0 使用详解:新特性、实战与避坑指南
android·数据库·mysql
S1998_1997111609•X2 小时前
恶意注入污染蜜罐HDMI进程函数值进行封禁垃圾蠕虫仓蟲的轮系依据行为戆直㞢仓shell token
数据库·爬虫·网络协议·百度·开闭原则
Yupureki2 小时前
《Redis数据库》1.初识Redis
数据库·redis·缓存