浅谈MySQL分页Limit的性能问题

 更新时间:2019年08月22日 10:28:45   作者:MChopin  
这篇文章主要介绍了浅谈MySQL分页Limit的性能问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

MySQL的分页查询通常通过limit来实现。limit接收1或2个整数型参数,如果是2个参数,第一个是指定第一个返回记录行的偏移量,第二个是返回记录行的最大数目。初始记录行的偏移量是0。为了与PostgreSQL兼容,limit也支持limit # offset #。

问题:

对于小的偏移量,直接使用limit来查询没有什么问题,但随着数据量的增大,越往后分页,limit语句的偏移量就会越大,速度也会明显变慢。

优化思想:避免数据量大时扫描过多的记录

解决:子查询的分页方式或者JOIN分页方式。JOIN分页和子查询分页的效率基本在一个等级上,消耗的时间也基本一致。

下面举个例子。一般MySQL的主键是自增的数字类型,这种情况下可以使用下面的方式进行优化。

以真实的生产环境的6万条数据的一张表为例,比较一下优化前后的查询耗时:

-- 传统limit,文件扫描
[SQL]
SELECT * FROM tableName ORDER BY id LIMIT 50000,2;
受影响的行: 0
时间: 0.171s

-- 子查询方式,索引扫描
[SQL]
SELECT * FROM tableName
WHERE id >= (SELECT id FROM tableName ORDER BY id LIMIT 50000 , 1)
LIMIT 2;
受影响的行: 0
时间: 0.035s

-- JOIN分页方式
[SQL]
SELECT * FROM tableName AS t1
JOIN (SELECT id FROM tableName ORDER BY id LIMIT 50000, 1) AS t2
WHERE t1.id <= t2.id ORDER BY t1.id LIMIT 2;
受影响的行: 0
时间: 0.036s

可以看到经过优化性能提高了很多倍。

优化原理:

子查询是在索引上完成的,而普通的查询时在数据文件上完成的。通常来说,索引文件要比数据文件小得多,所以操作起来也会更有效率。因为要取出所有字段内容,第一种需要跨越大量数据块并取出,而第二种基本通过直接根据索引字段定位后,才取出相应内容,效率自然大大提升。因此,对limit的优化,不是直接使用limit,而是首先获取到offset的id,然后直接使用limit size来获取数据。

在实际项目使用,可以利用类似策略模式的方式去处理分页。例如,每页100条数据,判断如果是100页以内,就使用最基本的分页方式;如果大于100,则使用子查询的分页方式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 浅谈MySQL之浅入深出页原理

    浅谈MySQL之浅入深出页原理

    首先,我们需要知道,页(Pages)是InnoDB中管理数据的最小单元。Buffer Pool中存的就是一页一页的数据。当我们要查询的数据不在Buffer Pool中时,InnoDB会将记录所在的页整个加载到Buffer Pool中去;同样,将Buffer Pool中的脏页刷入磁盘时,也是按照页为单位刷入磁盘的
    2021-06-06
  • Navicat for MySQL(mysql图形化管理工具)是什么?

    Navicat for MySQL(mysql图形化管理工具)是什么?

    这里就给大家介绍一个常用的MySQL数据库管理工具:Navicat for MySQL,需要的朋友可以参考下
    2015-09-09
  • MySQL实战教程之Join语句执行流程

    MySQL实战教程之Join语句执行流程

    这篇文章主要介绍了MySQL Join语句执行流程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • Mysql的longblob字段插入数据问题解决

    Mysql的longblob字段插入数据问题解决

    在使用mysql的过程中,有个问题就是mysql的优化,mysql中longblob字段在5.5版本中默认的为1M,需要解决问题的朋友可以参考下
    2014-01-01
  • mysql常用监控脚本命令整理

    mysql常用监控脚本命令整理

    mysql监控脚本常用命令整理,感兴趣的朋友可以了解下哈
    2013-06-06
  • MySQL全局锁和表锁的深入理解

    MySQL全局锁和表锁的深入理解

    这篇文章主要给大家介绍了关于MySQL全局锁和表锁的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用MySQL具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • MySQL函数与存储过程字符串长度限制的解决

    MySQL函数与存储过程字符串长度限制的解决

    本文主要介绍了MySQL函数与存储过程字符串长度限制的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • MySQL中的隐藏列的具体查看

    MySQL中的隐藏列的具体查看

    mysql中存在一些隐藏列,例如行标识、事务ID、回滚指针等,不知道大家是否和我一样好奇过,要怎样才能实际地看到这些隐藏列的值呢,感兴趣的可以了解一下
    2021-09-09
  • 清理MySQL Binlog二进制日志的三种方式

    清理MySQL Binlog二进制日志的三种方式

    Binlog日志非常重要,但是占用的磁盘空间也很大,我们也需要定期的去清理二进制日志,在MySQL数据库中,提供了自动清理Binlog日志的参数,本文给大家介绍了清理MySQL Binlog二进制日志的三种方式,文中通过代码讲解非常详细,需要的朋友可以参考下
    2024-01-01
  • 详解MySQL中存储函数创建与触发器设置

    详解MySQL中存储函数创建与触发器设置

    这篇文章主要为大家详细介绍了MySQL中存储函数的创建与触发器的设置,文中的示例代码讲解详细,具有一定的学习价值,需要的可以参考一下
    2022-08-08

最新评论