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

 更新时间:2021年07月25日 10:36:25   作者:程序员阿牛  
在mysql中limit可以实现快速分页,但是如果数据到了几百万时我们的limit必须优化才能有效的合理的实现分页了,否则可能卡死你的服务器

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

语句如下:

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中between的用法及说明

    mysql中between的用法及说明

    这篇文章主要介绍了mysql中between的用法及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Mysql字符串截取函数SUBSTRING的用法说明

    Mysql字符串截取函数SUBSTRING的用法说明

    今天建视图时,用到了MySQL中的字符串截取,很是方便。
    2011-06-06
  • Mysql inner join on的用法实例(必看)

    Mysql inner join on的用法实例(必看)

    下面小编就为大家带来一篇Mysql inner join on的用法实例(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • MySQL中TEXT与BLOB字段类型的区别

    MySQL中TEXT与BLOB字段类型的区别

    这篇文章主要介绍了MySQL中TEXT与BLOB字段类型的区别,本文总结了6大区别,需要的朋友可以参考下
    2014-08-08
  • Linux下Mysql5.7.19卸载方法

    Linux下Mysql5.7.19卸载方法

    在卸载mysql之前需要先查找下以前是否安装过mysql,具体查找命令在本文有介绍,本文重点给大家介绍Linux下Mysql5.7.19卸载方法,需要的朋友参考下吧
    2017-08-08
  • 干涉MySQL优化器使用hash join的方法

    干涉MySQL优化器使用hash join的方法

    这篇文章主要介绍了如何干涉MySQL优化器使用hash join,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • 一文弄懂MySQL自增主键

    一文弄懂MySQL自增主键

    这篇文章主要介绍了MySQL自增主键,MySQL的自增主键并不一定是连续的,自增值的保存位置和修改机制决定了一种自增值不连续的场景,下面就来具体介绍一下,感兴趣的可以了解一下
    2025-01-01
  • MySQL性能优化的一些技巧帮助你的数据库

    MySQL性能优化的一些技巧帮助你的数据库

    你完成了你的品牌新的应用程序,一切工作就像一个魅力;突然间,一个大爆发的用户你的MySQL服务器,您的网站已关闭,是什么问题导致的呢?以下是MySQL性能优化的一些技巧,将帮助你,帮助你的数据库
    2013-01-01
  • 深入解析MySQL的窗口函数

    深入解析MySQL的窗口函数

    这篇文章主要介绍了深入解析MySQL的窗口函数,窗口可以理解为记录集合,窗口函数就是在满足某种条件的记录集合上执行的特殊函数,即:应用在窗口内的函数,需要的朋友可以参考下
    2023-07-07
  • Navicat工具中设置MySQL允许外部访问

    Navicat工具中设置MySQL允许外部访问

    默认情况下MySQL只允许本地登录,即只能在安装MySQL环境所在的主机下访问,这篇文章主要给大家介绍了关于Navicat工具中设置MySQL允许外部访问的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-04-04

最新评论