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

目录
  • 一、测试实验
  • 二、 对limit分页问题的性能优化方法
    • 2.1 利用表的覆盖索引来加速分页查询
    • 2.2 利用 id>=的形式:
    • 2.3 利用join
  • 总结:

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

语句如下:

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慢内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL limit分页大偏移量慢的原因及优化方案

    在 MySQL 中通常我们使用 limit 来完成页面上的分页功能,但是当数据量达到一个很大的值之后,越往后翻页,接口的响应速度就越慢. 本文主要讨论 limit 分页大偏移量慢的原因及优化方案,为了模拟这种情况,下面首先介绍表结构和执行的 SQL. 场景模拟 建表语句 user 表的结构比较简单,id.sex 和 name,为了让 SQL 的执行时间变化更加明显,这里有9个姓名列. CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREME

  • MYSQL分页limit速度太慢的优化方法

    在mysql中limit可以实现快速分页,但是如果数据到了几百万时我们的limit必须优化才能有效的合理的实现分页了,否则可能卡死你的服务器哦.    当一个表数据有几百万的数据的时候成了问题! 如 * from table limit 0,10 这个没有问题 当 limit 200000,10 的时候数据读取就很慢,可以按照一下方法解决     第一页会很快    PERCONA PERFORMANCE CONFERENCE 2009上,来自雅虎的几位工程师带来了一篇"EfficientPag

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

    目录 一.测试实验 二. 对limit分页问题的性能优化方法 2.1 利用表的覆盖索引来加速分页查询 2.2 利用 id>=的形式: 2.3 利用join 总结: 阿牛新入职了一家新公司,第一个任务是根据条件导出订单表中的数据到文件中,阿牛心想:这也太简单了,于是很快写好了如下语句,并且告诉测试自己的代码是免测产品. 语句如下: select * from orders where name='lilei' and create_time>'2020-01-01 00:00:00' limit

  • mysql分页的limit参数简单示例

    Mysql的分页的两个参数 select * from user limit 1,2 1表示从第几条数据开始查(默认索引是0,如果写1,从第二条开始查) 2,表示这页显示几条数据 到此这篇关于mysql分页的limit参数的文章就介绍到这了,更多相关mysql分页limit参数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

  • MySQL分页Limit的优化过程实战

    前言 在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能. SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数.LIMIT 接受一个或两个数字参数.参数必须是一个整数常量.如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目.初始记录行的偏移

  • 浅谈MySQL分页Limit的性能问题

    MySQL的分页查询通常通过limit来实现.limit接收1或2个整数型参数,如果是2个参数,第一个是指定第一个返回记录行的偏移量,第二个是返回记录行的最大数目.初始记录行的偏移量是0.为了与PostgreSQL兼容,limit也支持limit # offset #. 问题: 对于小的偏移量,直接使用limit来查询没有什么问题,但随着数据量的增大,越往后分页,limit语句的偏移量就会越大,速度也会明显变慢. 优化思想:避免数据量大时扫描过多的记录 解决:子查询的分页方式或者JOIN分页方式

  • MySql分页时使用limit+order by会出现数据重复问题解决

    目录 摘要 问题描述 分析问题 解决问题 摘要 能把复杂的知识讲的简单很重要 在学习的过程中我们看过很多资料.视频.文档等,因为现在资料视频都较多所以往往一个知识点会有多种多样的视频形式讲解.除了推广营销以外,确实有很多人的视频讲解非常优秀,例如李永乐老师的短视频课,可以在一个黑板上把那么复杂的知识,讲解的那么容易理解,那么透彻.而我们学习编程的人也是,不只是要学会把知识点讲明白,也要写明白. 问题描述 在 MySQL 中我们通常会采用 limit 来进行翻页查询,比如 limit(0,10)

  • mysql分页性能探索

    常见的几种分页方式: 1.扶梯方式 扶梯方式在导航上通常只提供上一页/下一页这两种模式,部分产品甚至不提供上一页功能,只提供一种"更多/more"的方式,也有下拉自动加载更多的方式,在技术上都可以归纳成扶梯方式. 扶梯方式在技术实现上比较简单及高效,根据当前页最后一条的偏移往后获取一页即可.写成SQL可能类似 SELECT*FROMLIST_TABLEWHEREid> offset_id LIMIT n; 1.电梯方式 另外一种数据获取方式在产品上体现成精确的翻页方式,如1,2,

  • SpringMVC+Mybatis实现的Mysql分页数据查询的示例

    周末这天手痒,正好没事干,想着写一个分页的例子出来给大家分享一下. 这个案例分前端和后台两部分,前端使用面向对象的方式写的,里面用到了一些回调函数和事件代理,有兴趣的朋友可以研究一下.后台的实现技术是将分页Pager作为一个实体对象放到domain层,当前页.单页数据量.当前页开始数.当前页结束数.总数据条数.总页数都作为成员属性放到实体类里面. 以前项目数据库用的是oracle,sql语句的写法会从当前页开始数到当前页结束数查询数据.刚刚在这纠结了很长时间,查询到的数据显示数量总是有偏差,后来

  • 利用Spring MVC+Mybatis实现Mysql分页数据查询的过程详解

    前言 因为最近没什么事,所以想着写一个分页的例子出来给大家分享一下.这个案例分前端和后台两部分,前端使用面向对象的方式写的,里面用到了一些回调函数和事件代理,有兴趣的朋友可以研究一下.后台的实现技术是将分页Pager作为一个实体对象放到domain层,当前页.单页数据量.当前页开始数.当前页结束数.总数据条数.总页数都作为成员属性放到实体类里面. 以前项目数据库用的是oracle,sql语句的写法会从当前页开始数到当前页结束数查询数据.刚刚在这纠结了很长时间,查询到的数据显示数量总是有偏差,后来

  • 浅析Oracle和Mysql分页的区别

    一.Mysql使用limit分页 select * from stu limit m, n; //m = (startPage-1)*pageSize,n = pageSize PS: (1)第一个参数值m表示起始行,第二个参数表示取多少行(页面大小) (2)m= (2-1)*10+1,n=10 ,表示 limit 11,10从11行开始,取10行,即第2页数据. (3)m.n参数值不能在语句当中写计算表达式,写到语句之前必须计算好值. 二.Oracle使用rownum分页 select * f

  • php下巧用select语句实现mysql分页查询

    利用select语句的一个特性就可以很方便地实现mysql查询结果的分页,下文对该方法的实现过程作了详细的介绍,希望对您能有所启迪. mysql分页查询是我们经常见到的问题,那么应该如何实现呢?下面就教您一个实现mysql分页查询的好方法,供您参考学习. mysql中利用select语句的一个特性就可以很方便地实现查询结果的分页,select语句实现mysql分页查询的语法: 复制代码 代码如下: SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BI

随机推荐