为什么MySQL分页用limit会越来越慢


Posted in MySQL onJuly 25, 2021

阿牛新入职了一家新公司,第一个任务是根据条件导出订单表中的数据到文件中,阿牛心想:这也太简单了,于是很快写好了如下语句,并且告诉测试自己的代码是免测产品。

语句如下:

select * from orders where name=‘lilei' and create_time>'2020-01-01 00:00:00' limit start,end

没想到上线一段时间后,生产开始预警,显示这条sql为慢SQL,执行时间50多秒,严重影响到了业务。
阿牛赶紧请教大佬猿猿帮忙查找原因,猿猿很快就帮其解决了,并且给阿牛做了以下实验:

一、测试实验

mysql分页直接用limit start, count分页语句:

select * from product limit start, count

当起始页较小时,查询没有性能问题,我们分别看下从10, 100, 1000, 10000开始分页的执行时间(每页取20条),如下:

select * from product limit 10, 20 0.016秒
select * from product limit 100, 20 0.016秒
select * from product limit 1000, 20 0.047秒
select * from product limit 10000, 20 0.094秒

我们已经看出随着起始记录的增加,时间也随着增大, 这说明分页语句limit跟起始页码是有很大关系的,
那么我们把起始记录改为40w看下(也就是记录的一半左右)

select * from product limit 400000, 20 3.229秒

再看我们获取最后一页记录的时间

select * from product limit 866613, 20 37.44秒

像这种分页最大的页码页显然这种时间是无法忍受的。
从中我们也能总结出两件事情:
limit语句的查询时间与起始记录的位置成正比。
mysql的limit语句是很方便,但是对记录很多的表并不适合直接使用。

二、 对limit分页问题的性能优化方法

2.1 利用表的覆盖索引来加速分页查询

我们都知道,利用了索引查询的语句中如果只包含了那个索引列(覆盖索引),那么这种情况会查询很快。
因为利用索引查找有优化算法,且数据就在查询索引上面,不用再去找相关的数据地址了,这样节省了很多时间。
另外Mysql中也有相关的索引缓存,在并发高的时候利用缓存就效果更好了。
在我们的例子中,我们知道id字段是主键,自然就包含了默认的主键索引。现在让我们看看利用覆盖索引的查询效果如何:
这次我们之间查询最后一页的数据(利用覆盖索引,只包含id列),如下:

select id from product limit 866613, 20

查询时间为0.2秒,相对于查询了所有列的37.44秒,提升了大概100多倍的速度。
那么如果我们也要查询所有列,有两种方法,

2.2 利用 id>=的形式:

SELECT * FROM product 
WHERE ID > =(select id from product limit 866613, 1) limit 20

查询时间为0.2秒,简直是一个质的飞跃啊。

2.3 利用join

SELECT * FROM product a 
JOIN (select id from product limit 866613, 20) b ON a.ID = b.id

总结:

是不是认为我没说理由,原因就是使用select * 的情况下直接用limit 600000,10 扫描的是约60万条数据,并且是需要回表60W次,也就是说大部分性能都耗在随机访问上,到头来只用到10条数据,如果先查出来ID,再关联去查询记录,就会快很多,因为索引查找符合条件的ID很快,然后再回表10次。就可以拿到我们想要的数据。

到此这篇关于为什么MySQL分页用limit会越来越慢的文章就介绍到这了,更多相关MySQL分页limit慢内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
浅谈Mysql多表连接查询的执行细节
Apr 24 MySQL
将图片保存到mysql数据库并展示在前端页面的实现代码
May 02 MySQL
MySQL CHAR和VARCHAR该如何选择
May 31 MySQL
mysql外连接与内连接查询的不同之处
Jun 03 MySQL
MySQL索引失效的典型案例
Jun 05 MySQL
SQL实现LeetCode(197.上升温度)
Aug 07 MySQL
MySQL表锁、行锁、排它锁及共享锁的使用详解
Apr 02 MySQL
MySQL的存储过程和相关函数
Apr 26 MySQL
MySQL的prepare使用以及遇到的bug
May 11 MySQL
MySQL普通表如何转换成分区表
May 30 MySQL
MySQL自定义函数及触发器
Aug 05 MySQL
分享很少见很有用的SQL功能CORRESPONDING
Aug 05 MySQL
MySQL深度分页(千万级数据量如何快速分页)
ORM模型框架操作mysql数据库的方法
mysql 直接拷贝data 目录下文件还原数据的实现
MySQL索引是啥?不懂就问
MySQL 四种连接和多表查询详解
MySQL 聚合函数排序
MySQL 那些常见的错误设计规范,你都知道吗
Jul 16 #MySQL
You might like
PHP也可以?成Shell Script
2006/10/09 PHP
有关php运算符的知识大全
2011/11/03 PHP
色色整理的PHP面试题集锦
2012/03/08 PHP
PHP依赖注入(DI)和控制反转(IoC)详解
2017/06/12 PHP
重构Javascript代码示例(重构前后对比)
2013/01/23 Javascript
JQuery调webservice实现邮箱验证(检测是否可用)
2013/05/21 Javascript
CSS鼠标响应事件经过、移动、点击示例介绍
2013/09/04 Javascript
javascript模拟实现ajax加载框实例
2014/10/15 Javascript
JS实现的左侧竖向滑动菜单效果代码
2015/10/19 Javascript
详解JS中定时器setInterval和setTImeout的this指向问题
2017/01/06 Javascript
angularJS 指令封装回到顶部示例详解
2017/01/22 Javascript
JS触摸与手势事件详解
2017/05/09 Javascript
Node错误处理笔记之挖坑系列教程
2018/06/05 Javascript
微信小程序实现传递多个参数与事件处理
2019/08/12 Javascript
Python中获取对象信息的方法
2015/04/27 Python
python制作websocket服务器实例分享
2016/11/20 Python
浅谈五大Python Web框架
2017/03/20 Python
python导出hive数据表的schema实例代码
2018/01/22 Python
Python实现的json文件读取及中文乱码显示问题解决方法
2018/08/06 Python
python leetcode 字符串相乘实例详解
2018/09/03 Python
Python Django 页面上展示固定的页码数实现代码
2019/08/21 Python
python向企业微信发送文字和图片消息的示例
2020/09/28 Python
python爬取”顶点小说网“《纯阳剑尊》的示例代码
2020/10/16 Python
使用javascript和HTML5 Canvas画的四渐变色播放按钮效果
2014/04/10 HTML / CSS
英国汽车和货车租赁网站:Hertz英国
2016/09/02 全球购物
瑞典Happy Socks美国官网:购买色彩斑斓的快乐袜子
2016/10/19 全球购物
澳大利亚设计的优质鞋类和适合澳大利亚生活方式的服装:Rivers
2019/04/23 全球购物
函授本科自我鉴定
2014/02/04 职场文书
一份创业计划书范文
2014/02/08 职场文书
班干部竞选演讲稿
2014/04/24 职场文书
大学国际贸易专业自荐信
2014/06/05 职场文书
群众路线个人对照检查材料
2014/09/23 职场文书
七年级作文之《我和我的祖国》观后感作文
2019/10/18 职场文书
自从在 IDEA 中用了热部署神器 JRebel 之后,开发效率提升了 10(真棒)
2021/06/26 Java/Android
windows11怎么查看wifi密码? win11查看wifi密码的技巧
2021/11/21 数码科技
python manim实现排序算法动画示例
2022/08/14 Python